ildarin
@ildarin

Как сделать прозрачным группу спрайтов SpriteRenderer одновременно?

Как сделать прозрачным группу спрайтов SpriteRenderer одновременно?
66554ce532209762556939.png
Если делать по отдельности - задние спрайты становится видно, а не должно. Нужно, чтобы весь рисунок из спрайтов был прозрачным без этого.
66554cf78af98309746441.png
Я придумал способ через SpriteMask - создавать на каждый SpriteRenderer копию MaskSprite с CustomRange. Есть способы проще/лучше?

Нашел еще 2 варианта.
Stencil Buffer
https://forum.unity.com/threads/blending-alpha-val...
RenderTexture
https://forum.unity.com/threads/how-to-fade-out-mu...
Оба непростые, насчет производительности - хз.
  • Вопрос задан
  • 34 просмотра
Пригласить эксперта
Ответы на вопрос 2
@namee
видел как-то на просторах решение этой задачи через шейдеры.
Вроде как вот этот

// Шейдер при наложении спрайтов отключает просвечивание

Shader "Custom/SpriteAlpha"
{
	Properties
	{
		[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
		_Color ("Tint", Color) = (1,1,1,1)
	}

	SubShader
	{
		Tags
		{ 
			"Queue"="Transparent" 
			"IgnoreProjector"="True" 
			"RenderType"="Transparent" 
			"PreviewType"="Plane"
			"CanUseSpriteAtlas"="True"
		}
		
		Cull Off
		Lighting Off
		ZWrite On
		ZTest Less
		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			
			struct appdata_t
			{
				float4 vertex   : POSITION;
				float4 color    : COLOR;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f
			{
				float4 vertex   : SV_POSITION;
				fixed4 color    : COLOR;
				half2 texcoord  : TEXCOORD0;
			};
			
			fixed4 _Color;

			v2f vert(appdata_t IN)
			{
				v2f OUT;
				OUT.vertex = UnityObjectToClipPos(IN.vertex);
				OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
				OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
#endif
				OUT.color = IN.color * _Color;
				return OUT;
			}

			sampler2D _MainTex;

			fixed4 frag(v2f IN) : SV_Target
			{
				half4 color = tex2D(_MainTex, IN.texcoord) * IN.color;
				clip (color.a - 0.01);
				return color;
			}
		ENDCG
		}
	}
}
Ответ написан
ildarin
@ildarin Автор вопроса
Вот исходники моего решения (два класса, один - хелпер)
UnityHelper.Current.OrderMinValue=-32767

Решение так себе т.к. сильно ресурсозатратно.

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public static class UnityExtensions
{
    public static void SetColorAlpha(this Image image, float value)
    {
        image.color = new Color(image.color.r, image.color.g, image.color.b, value);
    }

    public static void SetColorAlpha(this SpriteRenderer spriteRenderer, float value)
    {
        spriteRenderer.color = new Color(spriteRenderer.color.r, spriteRenderer.color.g, spriteRenderer.color.b, value);
    }

    public static IEnumerable<Transform> GetAllChildrenRecurcive(this Transform transform)
    {
        foreach (Transform child in transform)
        {
            yield return child;
            foreach (var innerChild in child.GetAllChildrenRecurcive())
            {
                yield return innerChild;
            }
        }
    }

    public static IEnumerable<T> GetComponents<T>(this IEnumerable<Transform> transforms)
    {
        return transforms.Select(t => t.GetComponent<T>()).Where(c => c != null);
    }
}

public class MaskOpacityBehaviour : MonoBehaviour
{
    private List<ChildSpriteMask> ChildSpriteMasks { get; set; }

    private void Start()
    {
        ChildSpriteMasks = new();
        var children = transform.GetAllChildrenRecurcive().GetComponents<SpriteRenderer>().ToList();
        foreach (var child in children)
        {
            child.maskInteraction = SpriteMaskInteraction.VisibleOutsideMask;

            var maskGo = new GameObject(child.name + "mask");
            maskGo.transform.parent = transform;
            var spriteMask = maskGo.AddComponent<SpriteMask>();
            spriteMask.isCustomRangeActive = true;

            UpdateSpriteMask(child, spriteMask);

            ChildSpriteMasks.Add(new ChildSpriteMask(child, spriteMask));
        }
    }

    private void Update()
    {
        foreach (var cm in ChildSpriteMasks)
        {
            UpdateSpriteMask(cm.Child, cm.SpriteMask);
        }
    }

    private static void UpdateSpriteMask(SpriteRenderer child, SpriteMask spriteMask)
    {
        spriteMask.sprite = child.sprite;
        spriteMask.frontSortingLayerID = child.sortingLayerID;
        spriteMask.frontSortingOrder = child.sortingOrder - 1;
        spriteMask.backSortingLayerID = child.sortingLayerID;
        spriteMask.backSortingOrder = UnityHelper.Current.OrderMinValue;
        spriteMask.transform.position = child.transform.position;
        spriteMask.transform.rotation = child.transform.rotation;
        spriteMask.transform.localScale = child.transform.localScale;
    }

    private class ChildSpriteMask
    {
        public ChildSpriteMask(SpriteRenderer child, SpriteMask spriteMask)
        {
            Child = child;
            SpriteMask = spriteMask;
        }

        public SpriteRenderer Child { get; }
        public SpriteMask SpriteMask { get; }
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы