经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
RectMask2D裁剪Canvas无效问题
来源:cnblogs  作者:yanghui01  时间:2021/12/24 8:47:50  对本文有异议

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

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

 

 【原因分析】

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

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

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

 

【解决思路】

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

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

 

最终效果:

 

【关于IClippable接口】

void Cull(Rect clipRect, bool validRect)

void SetClipRect(Rect value, bool validRect)

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

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

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

原文链接:http://www.cnblogs.com/sailJs/p/15712842.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号