UGUI ScrollView中显示模型和特效

Posted pj2933

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UGUI ScrollView中显示模型和特效相关的知识,希望对你有一定的参考价值。

游戏开发中有时候会遇到在UI上显示模型和特效的需求,这次需要在ScrollView上显示。我们使用UGUI的Screen Space - Camera模式,修改模型和特效的layer使之显示在UI上面,但是会遇到ScrollView的mask无法剔除模型和特效的问题。

解决思路:计算出ScrollView的显示矩形框的世界坐标和尺寸,传给模型和特效的shader,在shader里判断这个像素的世界坐标是否超过矩形框,来判断是否显示图像。

 

C#代码部分:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScrollViewModelAndEffectClip : MonoBehaviour
{
    
    public  RectTransform scrollViewArea;
    float mWidth, mHeight, m_canvasScale;
    Canvas mCanvas;
    public  Vector4 area;
    List<Material> modelMaterials = new List<Material>();
    // Start is called before the first frame update
    void Start()
    {
        
        var renderers=GetComponentsInChildren<Renderer>();
        for(int i = 0; i < renderers.Length; i++)
        {
            //Debug.LogError(renderers[i]);
            modelMaterials.AddRange(renderers[i].GetMaterials());
        }
        for(int i = 0; i < modelMaterials.Count; i++)
        {
            modelMaterials[i].shader = Shader.Find(modelMaterials[i].shader.name + "ScrollViewClip");
            //Debug.LogError(modelMaterials[i].shader.name + "ScrollViewClip");
        }

        mCanvas = GetComponentInParent<Canvas>();
        GetArea();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void GetArea()
    {
        m_canvasScale = mCanvas.transform.localScale.x;
        mWidth = scrollViewArea.rect.width * m_canvasScale;
        mHeight = scrollViewArea.rect.height * m_canvasScale;

        area = CalculateArea(scrollViewArea.position, scrollViewArea.pivot);

        for (int i = 0; i < modelMaterials.Count; i++)
        {
            //Debug.LogError(area);
            modelMaterials[i].SetVector("_Area", area);
        }

    }

    Vector4 CalculateArea(Vector3 position,Vector2 pivot)
    {
        return new Vector4()
        {
            x = position.x - mWidth*pivot.x,
            y = position.y - mHeight * pivot.y,
            z = position.x + mWidth *(1- pivot.x),
            w = position.y + mHeight * (1 - pivot.y)
        };
    }
 
}

接下来是Shader:

Shader "SonicDance/AddtiveScrollViewClip"
{
    Properties
    {
        _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
        _MainTex ("Particle Texture", 2D) = "white" {}
        _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
            //Clip新增
        _Area("Area", Vector) = (0,0,1,1)
            //
    }

    Category 
    {
        SubShader
        {
            Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
            Blend SrcAlpha OneMinusSrcAlpha
            ColorMask RGB
            Cull Off
            Lighting Off 
            ZWrite Off
            
            Pass {
            
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 2.0
                #pragma multi_compile_particles
                #pragma multi_compile_fog
                

                #include "UnityCG.cginc"

                struct appdata_t 
                {
                    float4 vertex : POSITION;
                    fixed4 color : COLOR;
                    float4 texcoord : TEXCOORD0;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                    
                };

                struct v2f 
                {
                    float4 vertex : SV_POSITION;
                    fixed4 color : COLOR;
                    float4 texcoord : TEXCOORD0;
                    float4 worldPos:TEXCOORD3;
                    UNITY_FOG_COORDS(1)
                    #ifdef SOFTPARTICLES_ON
                    float4 projPos : TEXCOORD2;
                    #endif
                    UNITY_VERTEX_OUTPUT_STEREO
                    
                };
                
                uniform sampler2D _MainTex;
                uniform fixed4 _TintColor;
                uniform float4 _MainTex_ST;
                uniform sampler2D_float _CameraDepthTexture;
                uniform float _InvFade;
                //Clip新增
                float4 _Area;
                //
                
                v2f vert ( appdata_t v  )
                {
                    v2f o;
                    UNITY_SETUP_INSTANCE_ID(v);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                    

                    v.vertex.xyz +=  float3( 0, 0, 0 ) ;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.worldPos= mul(unity_ObjectToWorld, v.vertex);
                    #ifdef SOFTPARTICLES_ON
                        o.projPos = ComputeScreenPos (o.vertex);
                        COMPUTE_EYEDEPTH(o.projPos.z);
                    #endif
                    o.color = v.color;
                    o.texcoord = v.texcoord;
                    UNITY_TRANSFER_FOG(o,o.vertex);
                    return o;
                }

                fixed4 frag ( v2f i  ) : SV_Target
                {
                    
                    //新增,判断顶点坐标是否在裁剪框内
                 
                    bool inArea = i.worldPos.x >= _Area.x && i.worldPos.x <= _Area.z && i.worldPos.y >= _Area.y && i.worldPos.y <= _Area.w;
                    if (!inArea)
                        discard;
                    //----end----

                    #ifdef SOFTPARTICLES_ON
                        float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                        float partZ = i.projPos.z;
                        float fade = saturate (_InvFade * (sceneZ-partZ));
                        i.color.a *= fade;
                    #endif

                    

                    fixed4 col = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord.xy*_MainTex_ST.xy + _MainTex_ST.zw );
                    UNITY_APPLY_FOG(i.fogCoord, col);
                    return col;
                }
                ENDCG 
            }
        }    
    }
    CustomEditor "ASEMaterialInspector"
}

这个方法有一个问题就是,需要复制一份显示的模型和特效的shader,并且增加上面shader中注释的部分,如果模型和特效的shader多种多样的话,那工作量就比较大,需要其他的方法。

 

以上是关于UGUI ScrollView中显示模型和特效的主要内容,如果未能解决你的问题,请参考以下文章

Unity3d中UGUI组件精简复盘(十三)ScrollView组件

Unity3d中UGUI组件精简复盘(十三)ScrollView组件

Unity3D UGUI之ScrollView弹簧效果

Unity实现滑动列表(ScrollView)-UGUI

Unity3D-UGUI系列ScrollView 滚动视图组件详解

ugui学习——可动态改变Content大小的ScrollView