当前位置:   article > 正文

【Unity3D ugui】UI特效的位置自适应及调整层次关系的一种解决方案_ugui 自适应多层级

ugui 自适应多层级

前言

在UI上显示3D的特效,要考虑两个问题:
1、特效的位置自适应与UGUI自适应一致,否则在16:9下把特效调好位置后,切成16:10后,位置对应不上
2、特效显示层次最好能夹在UI中间

UGUI毕竟是个新的UI系统,各方面还很不成熟,显示特效的问题着实让我头疼了一番。
1、UI特效叠层显示可以参考雨松MOMO的博客:UGUI研究院之不添加摄像机解决UI与UI特效叠层问题(九),但是只能解决叠层的问题,而且对于复杂的界面系统,每一层都加一个UIDepth的组件非常蛋疼。自适应的问题要根据不同分辨率再进行一番艰难的调整,除非你可以写一套类似的Canvas自适应系统。
2、使用UGUI的RawImage,把Camera拍摄特效输出的RenderTexture拖到RawImage上,运行时即可看到效果。这种方法不仅能使用UGUI的自适应,而且层级也可以调整,通常显示UI模型时都是用这种方法,但是对于半透明的粒子、Mesh就不那么好处理了。最后找到一位前辈的文章,终于解决了困扰了我好几天的问题。想看原文点这里

原理

1、用一个单独的相机,对着特效拍照,设置输出的Target Texture
2、使用UGUI的RawImage组件,设置Texture为相机输出的Texture

这部分的内容,其实官方已经给出demo,打开RenderTexture场景就可以看到这个例子,就不详述了

实现

参照原文
下面用图来说明几个步骤:
先说一下demo的层次结构,“Window”下有两个Image,一个RawImage,RawImage夹在两个Image中间,我们想要的效果就是RawImage在Image1上,在Image2下。
这里写图片描述

1、相机参数设置
这里写图片描述

2、特效设置层次为UI3D(自己添加的Layer)
这里写图片描述
相机拍到特效的效果如下:
这里写图片描述

3、在UI中加上一个RawImage,设置Texture为上一步相机输出的Texture,加一个Default No-Alpha的材质(Shader在下面贴出,demo资源里也有)
这里写图片描述

4、运行查看效果
这里写图片描述

一些问题

1、RenderTexture的尺寸越大,内存占用越多,尽可能缩减RenderTexture的尺寸吧
2、RenderTexture的尺寸要与RawImage的大小一致,否则出现拉伸变形
3、每个特效对应一个相机,如果特效多的话,还是用代码管理特效相机吧
进一步思考,通常美术把一个特效的prefab发过来,我们只要把这个prefab和UI中的RawImage绑定即可,相机什么的才不想每次都动手加一遍,所以有了下面偷懒的代码

using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(RawImage))]
public class UI3DEffect : MonoBehaviour
{
    [SerializeField]
    private GameObject effectPrefab;
    private GameObject effectGO;
    private RenderTexture renderTexture;
    private Camera rtCamera;
    private RawImage rawImage;

    void Awake()
    {
        //RawImage可以手动添加,设置no alpha材质,以显示带透明的粒子
        rawImage = gameObject.GetComponent<RawImage>();
        if (rawImage == null)
        {
            rawImage = gameObject.AddComponent<RawImage>();
        }
    }

    public RectTransform rectTransform
    {
        get
        {
            return transform as RectTransform;
        }
    }

    void OnEnable()
    {
        if (effectPrefab != null)
        {
            effectGO = Instantiate(effectPrefab);

            GameObject cameraObj = new GameObject("UIEffectCamera");
            rtCamera = cameraObj.AddComponent<Camera>();
            renderTexture = new RenderTexture((int)rectTransform.sizeDelta.x, (int)rectTransform.sizeDelta.y, 24);
            renderTexture.antiAliasing = 4;
            rtCamera.clearFlags = CameraClearFlags.SolidColor;
            rtCamera.backgroundColor = new Color();
            rtCamera.cullingMask = 1 << 8;
            rtCamera.targetTexture = renderTexture;

            effectGO.transform.SetParent(cameraObj.transform, false);

            rawImage.enabled = true;
            rawImage.texture = renderTexture;
        }
        else
        {
            rawImage.texture = null;
            Debug.LogError("EffectPrefab can't be null");
        }
    }

    void OnDisable()
    {
        if (effectGO != null)
        {
            Destroy(effectGO);
            effectGO = null;
        }
        if (rtCamera != null)
        {
            Destroy(rtCamera.gameObject);
            rtCamera = null;
        }
        if (renderTexture != null)
        {
            Destroy(renderTexture);
            renderTexture = null;
        }
        rawImage.enabled = false;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

当RawImage启用时,立刻创建动态相机、RenderTexture,设置参数。不启用时,自动销毁相机和RenderTexture。当然特效多的话,也可以做个对象池把Camera和RenderTexture缓存起来。
然后用的时候是这样的,只需要一步,把特效prefab拖进来即可
这里写图片描述

demo

UI-Default-No-Alpha.shader

Shader "UI/Default No-Alpha"
{
    Properties
    {
        [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
        _Color("Tint", Color) = (1,1,1,1)

        _StencilComp("Stencil Comparison", Float) = 8
        _Stencil("Stencil ID", Float) = 0
        _StencilOp("Stencil Operation", Float) = 0
        _StencilWriteMask("Stencil Write Mask", Float) = 255
        _StencilReadMask("Stencil Read Mask", Float) = 255

        _ColorMask("Color Mask", Float) = 15
    }

    SubShader
    {
        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
            "PreviewType" = "Plane"
            "CanUseSpriteAtlas" = "True"
        }

        Stencil
        {
            Ref[_Stencil]
            Comp[_StencilComp]
            Pass[_StencilOp]
            ReadMask[_StencilReadMask]
            WriteMask[_StencilWriteMask]
        }

        Cull Off
        Lighting Off
        ZWrite Off
        ZTest[unity_GUIZTestMode]
        Fog{ Mode Off }
        Blend One Zero
        ColorMask[_ColorMask]
        Blend One OneMinusSrcAlpha // 源rgba*1 + 背景rgba*(1-源A值)  

        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 = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
        #ifdef UNITY_HALF_TEXEL_OFFSET  
                OUT.vertex.xy -= (_ScreenParams.zw - 1.0);
        #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
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/108119
推荐阅读
相关标签
  

闽ICP备14008679号