You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现透过不可见游戏对象查看时隐藏部分游戏对象?

解决AR帽子与头部的遮挡问题

嘿,我来帮你搞定这个头疼的遮挡逻辑!先把需求掰明白:头部作为不可见的遮罩,要挡住帽子被它覆盖的区域,但当视线落在帽子自身区域时,被头部挡住的那部分帽子不能变透明——说白了就是,帽子戴在头上时,内侧被头挡住的部分要隐藏,但从外面看帽子的外侧,哪怕和头重叠也得正常显示。

第一步:完善头部的遮罩着色器

你现有的遮罩着色器方向是对的,但得把模板缓冲和深度的设置补全,让它只做标记不输出颜色:

Shader "Custom/Stencil/HeadMask" {
    SubShader {
        Tags { 
            "RenderType"="Opaque" 
            "Queue"="Geometry-1" // 比普通几何体早渲染,确保先写入模板缓冲
        }
        ColorMask 0 // 不输出任何颜色,只做遮罩标记
        ZWrite On // 写入深度,避免后续物体错误覆盖
        Cull Off // 确保头部所有面都能标记模板,不管朝向

        Stencil {
            Ref 1 // 设置模板参考值为1
            Comp Always // 总是通过模板测试
            Pass Replace // 将对应像素的模板值设为1
        }

        Pass {
            // 空Pass,只执行模板和深度操作
        }
    }
}

把这个着色器给你的头部对象,记得禁用它的MeshRenderer的阴影相关选项(不需要投射/接收阴影),先确保头部的Mesh能完整覆盖需要遮挡帽子的区域。

第二步:设置帽子的专属着色器

帽子的着色器要结合模板缓冲和深度来判断是否显示:只有当帽子像素在头部后面且处于头部模板标记区域时,才会被隐藏;如果帽子在头部前面,哪怕和头重叠也要正常渲染。

Shader "Custom/Stencil/HatShader" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader {
        Tags { 
            "RenderType"="Opaque" 
            "Queue"="Geometry" // 在遮罩之后渲染,确保能读取到模板值
        }
        ZWrite On
        Cull Off // 根据你的帽子模型调整,比如帽子内侧需要显示就开Off

        Stencil {
            Ref 1
            Comp Equal // 只处理被头部标记过的区域(模板值为1)
            Pass Keep // 保留模板值,不修改
            Fail Keep
        }

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float depth : DEPTH;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Color;

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.depth = -UnityObjectToViewPos(v.vertex).z * _ProjectionParams.w; // 获取视图空间深度
                return o;
            }

            fixed4 frag (v2f i) : SV_Target {
                // 从深度缓冲中采样头部的深度值
                float headDepth = LinearEyeDepth(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.vertex)).r);
                // 如果帽子像素在头部后面(深度更大),就丢弃该像素实现遮挡
                if (i.depth > headDepth) {
                    discard;
                }
                // 否则正常渲染帽子
                fixed4 col = tex2D(_MainTex, i.uv) * _Color;
                return col;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

关键逻辑拆解

  1. 头部遮罩先渲染,在模板缓冲中标记出自己的区域(值为1),同时把深度写入缓冲。
  2. 帽子渲染时,先筛选出被头部标记的区域,再对比当前像素和头部的深度:
    • 帽子在头部后面 → 丢弃像素(实现遮挡)
    • 帽子在头部前面 → 正常渲染(避免透过帽子看时那部分透明)

额外小提示

  • 确保相机能渲染头部所在的Layer,否则模板缓冲不会被正确写入。
  • 测试时可以暂时打开头部MeshRenderer的颜色(注释掉ColorMask 0),确认遮罩区域是否覆盖正确,之后再改回去。

内容的提问来源于stack exchange,提问作者alex okochutin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:42:38