前几天同事做了一个效果,希望在原本使用了遮罩组件 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 等子节点组件的材质无效的问题的更多相关文章

  1. C#中怎样在ToolStripMenuItem下再添加子级菜单

    场景 在右键菜单ContextMenuStrip下添加子菜单选项可以通过 ContextMenuStrip menuStrip ToolStripMenuItem mnuChartOption = n ...

  2. 问题:jQuery中遍历XML文件时候,获取子节点children不支持的情况(已解决)

    问题描述: 今天在写一个基于 jquery 的读取xml文件的程序时候,需要遍历xml的节点. 代码片段如下: function parse_xml_node(parent,result){ // r ...

  3. Unity UGUI图文混排(七) -- 下划线

    之前更新超链接的时候,忘了搭配实现一个下划线的功能,这篇文章就是来补上这一个功能,时间有点长,一方面没有很好的思路,一方面也没多少时间. 先在网上收集了一下下划线的实现操作,一种是在文本下再创建一个文 ...

  4. jquery 中选择当前标签下众多相同子标签中的第n个

    可以用jquery选择器的:eq选择器或者jquery遍历的eq()方法,下面带那给出ul下第4个li的内容 $("ul li:eq(3)")  // 元素的index位置工0开始 ...

  5. C# 递归程序 获取某个节点下的全部子节点

    /// <summary> /// 获取组织结构树 /// </summary> /// <param name="list"></par ...

  6. Unity优化方向——优化Unity游戏中的图形渲染(译)

    CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...

  7. Unity UGUI —— 无限循环List

    还记得大学毕业刚工作的时候是做flash的开发,那时候看到别人写的各种各样的UI组件就非常佩服,后来自己也慢慢尝试着写,发现其实也就那么回事.UI的开发其实技术的成分相对来说不算多,但是一个好的UI是 ...

  8. Unity ugui屏幕适配与世界坐标到ugui屏幕坐标的转换

    我们知道,如今的移动端设备分辨率五花八门,而开发过程中往往只取一种分辨率作为设计参考,例如采用1920*1080分辨率作为参考分辨率. 选定了一种参考分辨率后,美术设计人员就会固定以这样的分辨率来设计 ...

  9. Unity UGUI之Button

    创建Button后,会出现一个Image组件和一个Button组件,以及Button子节点Text(可以删除不影响功能) 其中Image的Image Type中有四个选项--Simple.Sliced ...

随机推荐

  1. 转:HashMap的工作原理,及笔记

    HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...

  2. Codevs 1198 国王游戏 2012年NOIP全国联赛提高组

    1198 国王游戏 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 恰逢 H 国国庆,国王邀 ...

  3. thinkphp 整合 ucenter

    http://xcodebox.com/2013/06/8855.html 参考 1   ucenter源码目录下 /advanced/examples/api目录 copy到thinkphp项目根目 ...

  4. 【实习记】2014-09-04浏览代码查middle资料+总结我折腾过的源码浏览器

        浏览着代码,看源码可以先看make文件,make文件有制造的流程信息. 一般可以从运行的程序对应的cpp看起.然而如果有框架,那就不容易了,会关系错纵复杂. 总结一下我折腾过的源码阅读器. s ...

  5. nginx 中出现nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

    有其他的程序占用的80端口.只需把相关程序关闭,fuser -k 80/tcp 然后再次 /usr/local/nginx/sbin/nginx,就能开启nginx服务了

  6. 关于ubuntu上执行错误命令报错

    Sorry, command-not-found has crashed! 新安装了一台ubuntu server 安装时用中文安装的,之后命令行下各种乱码,最后也不知道是修改哪里造成的 每次执行一次 ...

  7. jQuery学习 day01

    最近受某大牛指点(我不会说他姓范),了解了一下jQuery,据说很牛X,就了解了一下,第一天,分享给大家一些心得吧. 1.首先就是导入jQuery文件了,这里我是去jQuery官网下载的.(大家可以去 ...

  8. css3流式布局

    css3布局方式: 不推荐使用float,有时候使用浮动的时候,对于可适应的流氏布局,无法胜任. 推荐使用css3的display:webkit-box. 使用的html代码 <div clas ...

  9. python基础教程笔记—画幅好画(详解)

    今天写一下基础教程里面的第二个项目,主要使用python来做一个pdf的图,比较简单. 首先我们需要安装用到的模块pip install reportlab即可. 书上是用urlopen从往上下了一个 ...

  10. STM32之系统滴答定时器

    一.SysTick(系统滴答定时器)概述 操作系统需要一个滴答定时器周期性产生中断,以产生系统运行的节拍.在中断服务程序里,基于优先级调度的操作系统会根据进程优先级切换任务,基于时间片轮转系统会根据时 ...