C/C++教程

RectMask2D裁剪Canvas无效问题

本文主要是介绍RectMask2D裁剪Canvas无效问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

类似下面这样的层级结构,白色区域为ScrollView可见区域,RectMask2D添加在ScrollView上。

可以看到Canvas下的Image1没被裁剪掉,不在Canvas下的Image2裁剪掉了。

 

 【原因分析】

RectMask2D内部有一个裁剪对象列表,只有在这个列表中的对象才会被裁剪,这边就是Image1没被添加到这个列表中造成的。

ugui的实现逻辑就是,如果MaskableGraphic对象和RectMask2D层级间,如果出现了Canvas,那这个对象就不会添加进去。

具体的实现可以查看:MaskableGraphic.UpdateClipParent,在这个函数中确定被哪个RectMask2D裁剪(添加到它的裁剪对象列表中)

 

【解决思路】

添加一个代理类,这个类对象会被添加到RectMask2D的裁剪对象列表中,然后在收到裁剪调用的时候,我们把调用转发到Image1去。

 1 [DisallowMultipleComponent]
 2 public class ClipProxy : MaskableGraphic
 3 {
 4     //手动设定转发给哪几个MaskableGraphic, 如果不指定将获取所有子孙上的MaskableGraphic组件
 5     [SerializeField] private MaskableGraphic[] _manualMaskables;
 6     private List<MaskableGraphic> _maskableList;
 7     
 8     public class ClippableEvent : UnityEvent<Rect, bool> {}
 9     
10     private ClippableEvent _OnCull = new ClippableEvent();
11     public ClippableEvent onCull
12     {
13         get { return _OnCull; }
14         set { _OnCull = value; }
15     }
16     
17     private ClippableEvent _OnSetClipRect = new ClippableEvent();
18     public ClippableEvent onSetClipRect
19     {
20         get { return _OnSetClipRect; }
21         set { _OnSetClipRect = value; }
22     }
23     
24     #region Empty4Raycast的功能
25 
26     protected ClipProxy()
27     {
28         useLegacyMeshGeneration = false;
29     }
30     protected override void OnPopulateMesh(VertexHelper toFill)
31     {
32         toFill.Clear();
33     }
34     
35     #endregion
36     
37     
38     protected override void Awake()
39     {
40         base.Awake();
41 
42         if (null == _manualMaskables || 0 == _manualMaskables.Length)
43         {
44             _maskableList = new List<MaskableGraphic>();
45             GetComponentsInChildren(false, _maskableList);
46         }
47         else
48         {
49             _maskableList = new List<MaskableGraphic>(_manualMaskables);
50         }
51     }
52 
53     public override void Cull(Rect clipRect, bool validRect)
54     {
55         base.Cull(clipRect, validRect);
56         if (null != _maskableList)
57         {
58             for (var j = 0; j < _maskableList.Count; ++j)
59             {
60                 var maskable = _maskableList[j];
61                 if (null != maskable & maskable != this)
62                     maskable.Cull(clipRect, validRect);
63             }
64         }
65     }
66 
67     public override void SetClipRect(Rect value, bool validRect)
68     {
69         base.SetClipRect(value, validRect);
70         if (null != _maskableList)
71         {
72             for (var j = 0; j < _maskableList.Count; ++j)
73             {
74                 var maskable = _maskableList[j];
75                 if (null != maskable && maskable != this)
76                     maskable.SetClipRect(value, validRect);
77             }
78         }
79     }
80     
81 }

 

最终效果:

 

【关于IClippable接口】

void Cull(Rect clipRect, bool validRect)

void SetClipRect(Rect value, bool validRect)

这两个函数的参数类似,可能容易产生混淆。

Cull用于检测是否要把自己从渲染中剔除的,比如:可以在这边判断是否不在ScrollView的可见区域内,不在时可以从渲染中剔除,一定程度上提高渲染性能。

SetClipRect用于设置自己的裁剪区域,比如裁剪区域变大时,重新调整裁剪区域。或者裁剪区域没了,关掉裁剪区域。

这篇关于RectMask2D裁剪Canvas无效问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!