0x001 需求
当UGUI的某些组件 如:Text Button 创建的时候,自动为该组件添加指定的脚本。
0x002 分析
- 可否直接为Text组件编写编辑器扩展脚本。
引用momo大神文章地址:Unity3D研究院编辑器之不影响原有布局拓展Inspector
经过测试这在UGUI的某些组件中不生效,原因未知。解决办法:我们可以为 RectTransform 编写编辑器扩展,因为只要是UGUI组件肯定会有 RectTransform 的。
0x003 实现步骤
1. 实现编辑器脚本 AutoAddScript.cs
第一想到的是我能不能直接集成RectTransformEditor ----- 答案是不能的(访问级别问题)。
其次想到可不可以直接集成Editor ----- 答案是可以,但是会破坏原有的Inspector样式。
那么结合上文分析我给出最佳实现方案,套用momo大神文章在不影响原有布局的前提下。
- 首先我们要去文章处把DecoratorEditor这个类copy回来。
- 然后新建一个AutoAddScript类继承自DecoratorEditor
- 实现空构造函数并且base("RectTransformEditor")
- 书写OnEnable方法 在方法内部实现我们的监控
using UnityEditor;
[CustomEditor(typeof(RectTransform))]
public class AutoAddScript : DecoratorEditor
{
public AutoAddScript() : base("RectTransformEditor") { }
public void OnEnable()
{
//这里的target 是在Editor中的变量 也就是当前对象 要里式转换一下
Debug.Log(target as RectTransform);
}
}
我们把这个代码连同DecoratorEditor.cs一起放到Editor目录下,然后我们创建几个UI测试一下输出。
测试输出
2. 实现自动添加脚本
- 我们随便编写一个继承于MonoBehaviour的脚本,我暂且命名为Test
- 在AutoAddScript 编辑器扩展中的OnEnable方法里判断是添加了什么UI
- 如果是我们想要的UI组件,那么就添加Test脚本
- 如果已经有了脚本就不要再次添加了
using UnityEditor;
using UnityEngine.UI;
[CustomEditor(typeof(RectTransform))]
public class AutoAddScript : DecoratorEditor
{
public AutoAddScript() : base("RectTransformEditor") { }
public void OnEnable()
{
//这里的target 是在Editor中的变量 也就是当前对象 要里式转换一下
RectTransform rectTransform = target as RectTransform;
//这里要引用UnityEngine.UI
Text text = rectTransform.GetComponent<Text>();
if (text!=null && rectTransform.GetComponent<Test>()==null)
{
rectTransform.gameObject.AddComponent<Test>();
}
}
}
测试添加脚本
3. 实现当Text被移除的时候Test也要被移除
- 因为我们是用的OnEnable生命周期,他在编译器中的话每次状态改变都会调用一下
- 所以移除Text的时候也会调用一次,那么我们可以直接在里面编写
- 判断当前Text是否存在,不存在的话也要移除Test
- 注意这里的移除组件必须为立即移除 也就是说Object.Destroy在这里是不能用的
- 因为Object.Destroy是下一帧移除,我们可以用Object.DestroyImmediate这个方法立即移除组件
using UnityEditor;
using UnityEngine.UI;
[CustomEditor(typeof(RectTransform))]
public class AutoAddScript : DecoratorEditor
{
public AutoAddScript() : base("RectTransformEditor") { }
public void OnEnable()
{
//这里的target 是在Editor中的变量 也就是当前对象 要里式转换一下
RectTransform rectTransform = target as RectTransform;
//这里要引用UnityEngine.UI
Text text = rectTransform.GetComponent<Text>();
Test test = rectTransform.GetComponent<Test>();
if (text!=null && test == null)
{
rectTransform.gameObject.AddComponent<Test>();
}else if (text == null && test != null)
{
//注意这里必须是立即移除
Object.DestroyImmediate(test);
}
}
}
0x004 实现效果
最终实现效果0x005 后记
那么你要问了,这个可以拿来做什么 我能想到的就是框架的约束了,防止少挂在脚本,做全自动本地化相关等。
网友评论