unity 滚动 UI Scroll Rect

本文详细介绍如何在Unity中创建可滑动的面板,包括新建Canvas、设置滚动区域、添加滑动组件及遮罩等步骤。

1.新建Canvas
2.新建Panel,命名为ViewScroll,设置宽高,即 可视滚动区域。
这里写图片描述
3.在ViewScroll 面板添加ScrollRect 组件用于滑动,添加 Mask 组件用于遮罩
4.在ViewScroll下新建 Panel 名为Content,Content面板的大小一定要超过ViewScroll的大小,才能滑动
5.将ScrollRect 的Content 设为 Content面板
这里写图片描述

6.将ScrollRect 的MovementType 设置为 Clamped,将不会回弹
7. 把Mask组件 勾上会遮罩超出可视滑动区域

### Scroll Rect 裁剪 Additive Shader 的机制与自定义 Shader 的差异 UnityScroll Rect 组件依赖于 UGUI 的裁剪系统,该系统通过 `RectMask2D` 或 `Mask` 组件实现。在默认情况下,UnityUI 系统使用一种特殊的裁剪方式,即在 GPU 层面通过修改顶点坐标或使用 `clip()` 函数来丢弃超出裁剪区域的像素。Additive Shader(如 Unity 的内置粒子着色器)通常会遵循这些规则,因为它们在编写时已经考虑了 UGUI 的裁剪需求。 然而,自定义 Shader 往往不会自动适配 UGUI 的裁剪逻辑,除非开发者显式地在着色器中加入对裁剪区域的支持。这是由于 UGUI 的裁剪信息(如裁剪矩形的坐标)并不会自动传递给自定义着色器,导致裁剪无法生效[^1]。 ### Additive Shader 可以被裁剪的原因 Unity 内置的 Additive Shader(例如 `UI/Particles/Additive`)在编写时已经集成了对 UGUI 裁剪系统的支持。这些着色器通常会使用 `clip()` 函数,并结合裁剪区域的坐标信息(通过 `_ClipRect` 传递)来判断当前像素是否在裁剪区域内。例如: ```hlsl sampler2D _MainTex; float4 _ClipRect; fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.texcoord); clip(i.texcoord.x >= _ClipRect.x && i.texcoord.x <= _ClipRect.z && i.texcoord.y >= _ClipRect.y && i.texcoord.y <= _ClipRect.w ? 1.0 : -1.0); return col; } ``` 上述代码中,`_ClipRect` 是 Unity 自动传递的裁剪矩形参数,确保只有在 `Scroll Rect` 可视区域内的像素才会被保留[^1]。 ### 自定义 Shader 无法被裁剪的原因 自定义 Shader 缺乏对 `_ClipRect` 参数的处理逻辑,导致即使 `Scroll Rect` 启用了裁剪功能,这些着色器也无法响应裁剪区域的变化。此外,如果使用了 `clip()` 函数但未正确引入 `_ClipRect`,裁剪逻辑将无法正常工作。因此,自定义着色器中的 `clip()` 通常仅用于透明通道裁剪(如 alpha 测试),而不是用于响应 UI 裁剪区域。 ### 解决方案:在自定义 Shader 中加入裁剪逻辑 为了使自定义 Shader 支持 Scroll Rect 的裁剪功能,需要手动引入 `_ClipRect` 参数,并在像素着色器中使用它来控制 `clip()` 的行为。以下是修改后的着色器示例: ```hlsl Properties { _MainTex ("Texture", 2D) = "white" {} _ClipRect ("Clip Rect", vector) = (0,0,0,0) } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 texcoord : TEXCOORD0; }; sampler2D _MainTex; float4 _ClipRect; v2f vert (appdata_t v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.texcoord); clip(i.texcoord.x >= _ClipRect.x && i.texcoord.x <= _ClipRect.z && i.texcoord.y >= _ClipRect.y && i.texcoord.y <= _ClipRect.w ? 1.0 : -1.0); return col; } ENDCG } } ``` 通过这种方式,自定义 Shader 将能够正确响应 Scroll Rect 的裁剪区域变化,从而实现与 Unity 内建 Additive Shader 一致的裁剪效果。 ### 替代方案:使用双 Camera 投影裁剪 另一种方式是通过设置两个 Camera,分别用于 UI 和特效显示。将 Scroll Rect 的内容设置为特定 Layer(如 `RewardEffect`),并将一个独立的 Camera 设置为仅渲染该 Layer。通过调整该 Camera 的 `Viewport Rect` 与 Scroll Rect 的可视区域一致,可以实现对自定义 Shader 的裁剪效果。这种方式不依赖着色器内部的 `clip()` 逻辑,而是通过 Camera 的视口控制来实现裁剪[^2]。 ### 总结 Scroll Rect 可以裁剪 Unity 内建的 Additive Shader 是因为这些着色器已经集成了 `_ClipRect` 参数并使用了 `clip()` 函数进行裁剪判断。而自定义 Shader 由于缺乏这些逻辑,默认情况下无法响应 Scroll Rect 的裁剪区域变化。通过在自定义 Shader 中手动引入 `_ClipRect` 并添加裁剪逻辑,或使用双 Camera 的方式,可以有效解决 Scroll Rect自定义 Shader 无法裁剪的问题。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tianyongheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值