关于 Unity UGUI 中修改 Mask 组件下 Image 等子节点组件的材质无效的问题
前几天同事做了一个效果,希望在原本使用了遮罩组件 Mask 的技能图标(让技能图标变成圆形)上在添加一个置灰的功能,但问题来了:因为是动态根据游戏中玩家的条件才动态置灰,以修改 Mask 下子节点 Image 组件的材质来实现的,但是实际上怎么修改也不起作用,呈现出的效果都只停留在第一次运行时的样子。
一开始我也以为是 shader 的问题,修改的 property 没有生效,但是通过各种测试发现 shader 是已经修改成功的了。就是没有应用上,在查阅了各方资料无效果的情况下只能翻阅 unity 托管在 BitBucket 上的 UI 源码了(赞一个)。
先看看 Mask.cs,通过 StencilBuffer 实现遮罩,继承自 IMaterialModifier,需要实现接口:Material GetModifiedMaterial(Material baseMaterial); 这个接口是用来修改获取的材质来实现遮罩效果。在各种 MonoBehaviour 改变时都会通过 MaskUtilities 这个静态类来向所有的子节点发送 Stencil 状态改变的消息。
所以想知道为什么材质效果总是维持在第一次启动执行时,就看看 Mask.OnEnable 里调用的 MaskUtilities.NotifyStencilStateChanged(this); 做了什么。
public static void NotifyStencilStateChanged(Component mask)
{
var components = ListPool<Component>.Get();
mask.GetComponentsInChildren(components);
for (var i = ; i < components.Count; i++)
{
if (components[i] == null || components[i].gameObject == mask.gameObject)
continue; var toNotify = components[i] as IMaskable;
if (toNotify != null)
toNotify.RecalculateMasking();
}
ListPool<Component>.Release(components);
}
看以上代码可以得知,Mask 会调用所有子节点中继承自 IMaskable 组件(Image 继承 MaskableGraphic, MaskableGraphic 继承自此)的 RecalculateMasking() 函数。该函数将
MaskableGraphic 中的 m_ShouldRecalculateStencil 修改为 true,这样当开始渲染时,每个组件都会被调用 GetModifiedMaterial 以返回一个适用于当前渲染的 材质(有可能会返回一个修改过的拷贝),当 Imange.m_ShouldRecalculateStencil = true 时,会在 GetModifiedMaterial 中返回一个支持 Stencil 的修改过的材质,用于实现 Mask 遮罩效果,所以问题也很明了了,修改 Mask 下的 Image 组件原始的材质是不起作用的,因为实际渲染使用的不是它。
那么如何修改?只需要自己继承一个比如 Image 组件,并重载 GetModifiedMaterial 方法,将基类返回材质保存即可,这就是实际渲染使用的材质,当你想修改置灰时,使用这个材质即可。代码如下:
public class CustomImage : Image
{
public override Material GetModifiedMaterial(Material baseMaterial)
{
Material cModifiedMat = base.GetModifiedMaterial(baseMaterial);
// Do whatever you want with this "cModifiedMat"...
// You can also hold this and process it in your grayscale code.
// ...
return cModifiedMat;
}
}
也可以去看看我在 Unity Answer 上对于该问题的回答:http://answers.unity3d.com/questions/1130203/ui-mask-override-my-shaders-custom-property.html
关于 Unity UGUI 中修改 Mask 组件下 Image 等子节点组件的材质无效的问题的更多相关文章
- C#中怎样在ToolStripMenuItem下再添加子级菜单
场景 在右键菜单ContextMenuStrip下添加子菜单选项可以通过 ContextMenuStrip menuStrip ToolStripMenuItem mnuChartOption = n ...
- 问题:jQuery中遍历XML文件时候,获取子节点children不支持的情况(已解决)
问题描述: 今天在写一个基于 jquery 的读取xml文件的程序时候,需要遍历xml的节点. 代码片段如下: function parse_xml_node(parent,result){ // r ...
- Unity UGUI图文混排(七) -- 下划线
之前更新超链接的时候,忘了搭配实现一个下划线的功能,这篇文章就是来补上这一个功能,时间有点长,一方面没有很好的思路,一方面也没多少时间. 先在网上收集了一下下划线的实现操作,一种是在文本下再创建一个文 ...
- jquery 中选择当前标签下众多相同子标签中的第n个
可以用jquery选择器的:eq选择器或者jquery遍历的eq()方法,下面带那给出ul下第4个li的内容 $("ul li:eq(3)") // 元素的index位置工0开始 ...
- C# 递归程序 获取某个节点下的全部子节点
/// <summary> /// 获取组织结构树 /// </summary> /// <param name="list"></par ...
- Unity优化方向——优化Unity游戏中的图形渲染(译)
CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...
- Unity UGUI —— 无限循环List
还记得大学毕业刚工作的时候是做flash的开发,那时候看到别人写的各种各样的UI组件就非常佩服,后来自己也慢慢尝试着写,发现其实也就那么回事.UI的开发其实技术的成分相对来说不算多,但是一个好的UI是 ...
- Unity ugui屏幕适配与世界坐标到ugui屏幕坐标的转换
我们知道,如今的移动端设备分辨率五花八门,而开发过程中往往只取一种分辨率作为设计参考,例如采用1920*1080分辨率作为参考分辨率. 选定了一种参考分辨率后,美术设计人员就会固定以这样的分辨率来设计 ...
- Unity UGUI之Button
创建Button后,会出现一个Image组件和一个Button组件,以及Button子节点Text(可以删除不影响功能) 其中Image的Image Type中有四个选项--Simple.Sliced ...
随机推荐
- maven使用之烦人的.lastUpdated文件
项目使用maven管理jar包,很容易因为各种原因(网速慢.断网)导致jar包下载不下来,出现很多.lastUpdated文件.这些文件一个一个删除太麻烦.下面是全部删除的方法 windows系统 c ...
- 计数排序之python 实现源码
old = [2, 5, 3, 0, 2, 3, 0, 3] new = [0, 0, 0, 0, 0, 0] for i in range(len(old)): new[old[i]] = new[ ...
- (转) sphinx 高亮显示搜索词
http://hi.baidu.com/tewuapple/item/7a7bc34adbda24a8df2a9fe5 (转)
- cmake,gtest单元测试程序
参考:http://blog.csdn.net/stdcoutzyx/article/details/8284183 PROJECT (HELLO) SET(SRC_LIST main.c) MESS ...
- 【实习记】2014-09-01从复杂到简单:一行命令区间查重+长整型在awk中的bug
9月1号,导出sql文件后,想到了awk,但很复杂.想到了用sed前期处理+python排序比较的区间查重法.编写加调试用了约3小时. 9月2号,编写C代码的sql语句过程中,发现排序可以交m ...
- compass sprite
1.compass init 初始化一个compass项目,并创建一个images文件夹用来存放合成的sprite图 2.将切好的小图放到images文件夹中 3.在sass文件夹中新建一个test. ...
- SQL Cursor(游标)
1.游标在数据表没有id(identity(1,1))时好用,但是游标会吃更多的内存,减少可用的并发,占用宽带,锁定资源,当然还有更多的代码量 2.如果能不用游标,尽量不要使用游标,用完用完之后一定要 ...
- PL/SQL学习(六)触发器
原文参考:http://plsql-tutorial.com/ 创建语法: CREATE [OR REPLACE ] TRIGGER trigger_name {BEFORE | AFTER | IN ...
- JavaScript学习总结【11】、JS 运动
动画效果在网站中是一种非常常见的交互式体验效果,比如侧边栏分享.图片淡入淡出,我们把这种动画效果就叫做运动,也就是让物体动起来.如果想让一个物体动起来,无非就是改变它的速度,也就是改变属性值,比如 l ...
- yii2源码学习笔记(十三)
模型类DynamicModel主要用于实现模型内的数据验证yii2\base\DynamicModel.php <?php /** * @link http://www.yiiframework ...