有段时间没写东西了,最近有点小累啊。最近美术在K动画反映的问题,如果Image组件挂了新材质后,无法在Image上K材质中的效果。
使用MeshRenderer组件是可以K的,这里简单的给Image材质拓展了一个置灰的效果。如下图所示,MeshRenderer组件就可K材质动画。
所以我觉得,如果给Image组件同时在绑定MeshRenderer组件。动效师给MeshRenderer组件K动画,在Update中实时将数据同步给Image就可以了。如下图所示,脚本通过读取Image的材质取出所有属性,因为Update不需要将所有数据都同步,这里需要勾选那些数据进行同步。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; #if UNITY_EDITOR using UnityEditor; #endif [RequireComponent(typeof(MeshRenderer))] [RequireComponent(typeof(Image))] public class ImageAnim : MonoBehaviour { [System.Serializable] public class Data { public string name; public string type; public bool enable; } public List<Data> Property = new List<Data>(); private Image m_Image; private Material m_ImageMat; private MeshRenderer m_MeshRenderer; private MaterialPropertyBlock m_MaterialPropertyBlock; private void Awake() { m_MeshRenderer = GetComponent<MeshRenderer>(); m_MaterialPropertyBlock = new MaterialPropertyBlock(); m_Image = GetComponent<Image>(); m_ImageMat = Instantiate(m_Image.material); m_Image.material = m_ImageMat; } private void LateUpdate() { if (m_MeshRenderer.HasPropertyBlock()) { m_MeshRenderer.GetPropertyBlock(m_MaterialPropertyBlock); foreach (var item in Property) { if (item.enable) { SetValue(item.name, item.type); } } } } void SetValue (string name, string type) { switch (type) { case "Color": m_Image.color = m_MaterialPropertyBlock.GetColor(name); break; case "Float": case "Range": m_Image.material.SetFloat(name,m_MaterialPropertyBlock.GetFloat(name)); break; case "Vector": m_Image.material.SetVector(name, m_MaterialPropertyBlock.GetVector(name)); break; default: break; } } } #if UNITY_EDITOR [CustomEditor(typeof(ImageAnim))] public class MyTestEditor : Editor { ImageAnim myTest; MeshRenderer meshrenderer; private void OnEnable() { myTest = (target as ImageAnim); meshrenderer = myTest.GetComponent<MeshRenderer>(); } public override void OnInspectorGUI() { base.OnInspectorGUI(); if (GUILayout.Button("refresh")) { myTest.Property = new List<ImageAnim.Data>(); Shader shader = meshrenderer.sharedMaterial.shader; int count = shader.GetPropertyCount(); for (int i = 0; i < count; i++) { myTest.Property.Add(new ImageAnim.Data() { name = shader.GetPropertyName(i), type = shader.GetPropertyType(i).ToString() }); } } } } #endif |
接着对image的MeshRenderer组件K一个Gray的置灰系数。
OK 大功告成,image已经可以由动画控制了。
这个方法只是我的一个思路,我也没有在项目中放手使用,有相关经验的朋友欢迎讨论。
- 本文固定链接: https://www.xuanyusong.com/archives/4881
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!
大神的方法果然妙
需要做材质的实例化 在编辑器状态下预览就会导致各种资源丢失问题。其实都不需要Meshrender 只需要把材质属性弄出来 用一个脚本包裹一下K帧就行
啥都发布
使用另外一种方式实现。新建一个脚本,继承BaseMeshEffect。将需要修改的材质属性暴露出来,通过寄存器通道传递给shader处理。这样,做动画时,就可以直接控制暴露出来的变量。参考如下。https://www.zhihu.com/question/437168564/answer/1654231245
我们做过类似的方法, 但是美术同学比较抵制, 他们希望可以和MeshRenderer一样K动画的体验,如果不订制修改源码是实现不了的。。
大佬,但是不能对贴图的Offset 进行K帧,可有解决方案??
很好