一个美术需求引发的Custom Inspector
需求
- Editor模式下,在运行或者非运行状态下,能够按照指定的变化率来自动改变material中属性数值。
需求分析
- 如何在Editor模式下获得一个游戏对象及其组件,尤其是在非运行状态下?我们知道在Unity IDE运行起来后是很容易获得一个对象和组件的,在GameObject上挂一个脚本即可。但是在非运行状态下呢, - transform.GetComponent这样的方法怎么执行?好在unity已经为我们考虑到了这个问题,提供了- [ExecuteInEditMode]Attribute,通过指定这个attribute使得组件类中的方法可以在edit模式下执行,并且是在非运行状态下的。
- 如何在非运行状态下匀速改变数值呢?update方法中配合 - Time.deltaTime是一个完美的方案,但是即使设置了- [ExecuteInEditMode],update的表现在非运行和运行时也是完全不同的,查资料看到is only called when something in the scene changed.这句话时也有种吐槽的冲动。好在unity又为大家考虑到了这个问题(话说unity editor确实功能强大,AssetAtore里面那些插件真是厉害),Edit模式下提供了- EditorApplication.update,这是一个事件,我们注册一个自己的方法就可以在非运行状态下实现update的功能。我个人比较推荐使用EditorCoroutine,一个基于- EditorApplication.update的协程实现。
功能实现
- 使用一个自定义组件来实现material中数值的修改,这个类在UI上要体现出能够设置变化速率和初始值。并且在UI上通过点击按钮的形式来触发改变。
- 使用Custom Inspector来实现组件UI的自定义。
- 在运行状态下通过使用默认的update来实现匀速变化,在非运行状态下通过使用EditorCoroutine来实现。
代码实现
using UnityEngine;
using System.Collections;
using UnityEditor;
public class UVAnimation : MonoBehaviour
{
    public Vector2 TilingSpeed = new Vector2(1, 1);
    public Vector2 OffsetSpeed = new Vector2(0.1f, 0.1f);
    public Vector2 Tiling = new Vector2(1, 1);
    public Vector2 Offset = new Vector2(0, 0);
    float rate = 0.02f;
    EditorCoroutine coroutineOffset;
    EditorCoroutine coroutineTiling;
    bool isOffset = false;
    bool isTiling = false;
    // Use this for initialization
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
    }
    void FixedUpdate()
    {
        if (isOffset)
        {
            transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureOffset += OffsetSpeed * Time.deltaTime;
        }
        if (isTiling)
        {
            transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureScale += TilingSpeed * Time.deltaTime;
        }
    }
    public void ChangeOffset()
    {
        if (EditorApplication.isPlaying)
        {
            isOffset = true;
        }
        else
        {
            if (coroutineOffset != null)
            {
                coroutineOffset.stop();
            }
            coroutineOffset = EditorCoroutine.start(ChangeOffsetCoroutine());
        }
    }
    IEnumerator ChangeOffsetCoroutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(rate);
            transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureOffset += OffsetSpeed * rate;
        }
    }
    public void ChangeTiling()
    {
        if (EditorApplication.isPlaying)
        {
            isTiling = true;
        }
        else
        {
            if (coroutineTiling != null)
            {
                coroutineTiling.stop();
            }
            coroutineTiling = EditorCoroutine.start(ChangeTilingCoroutine());
        }
    }
    IEnumerator ChangeTilingCoroutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(rate);
            transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureScale += TilingSpeed * rate;
        }
    }
    public void SetOffset()
    {
        transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureOffset = Offset;
    }
    public void SetTiling()
    {
        transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureScale = Tiling;
    }
    public void Reset()
    {
        isOffset = false;
        isTiling = false;
        transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureScale = new Vector2(1, 1);
        transform.GetComponent<Renderer>().sharedMaterials[0].mainTextureOffset = new Vector2(0, 0);
        if (coroutineOffset != null)
        {
            coroutineOffset.stop();
        }
        if (coroutineTiling != null)
        {
            coroutineTiling.stop();
        }
    }
}
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(UVAnimation))]
public class UVAnimationBuilderEditor : Editor {
	public override void OnInspectorGUI ()
	{
	   base.OnInspectorGUI ();
		//DrawDefaultInspector ();
		UVAnimation uva = (UVAnimation)target;
		if (GUI.changed) {
			uva.SetTiling ();
			uva.SetOffset ();
		}
		if (GUILayout.Button("Change Tiling")) {
			uva.ChangeTiling ();
			EditorUtility.SetDirty (target);
		}
		if (GUILayout.Button("Change Offset")) {
			uva.ChangeOffset ();
		}
		if (GUILayout.Button("Reset")) {
			uva.Reset ();
		}
	}
}
代码解析
- [CustomEditor(typeof(UVAnimation))]为UVAnimation创建的Editor类,在这个类里面可以修改UVAnimation类的UI,可以调用UVAnimation类中的方法。
- OnInspectorGUI方法,顾名思义在里面可以对UI进行编程,注意一下这个方法会自己生产一句代码- base.OnInspectorGUI ();,我所注释掉的- DrawDefaultInspector ();这句代码都是用来绘制默认UI的,二者只可留其一。
- transform.GetComponent<Renderer>().sharedMaterials在edit模式下获取材质球的对象需要用- sharedMaterials。
- mainTextureScale对应的就是UI上的Tiling。命名这让人吐槽。
一个美术需求引发的Custom Inspector的更多相关文章
- 由一个项目需求引发的 - textarea中的换行和空格
		当我们使用 textarea 在前台编辑文字,并用 js 提交到后台的时候,空格和换行是我们最需要考虑的问题.在textarea 里面,空格和换行会被保存为/s和/n,如果我们前台输入和前台显示的文字 ... 
- Spring之LoadTimeWeaver——一个需求引发的思考---转
		原文地址:http://www.myexception.cn/software-architecture-design/602651.html Spring之LoadTimeWeaver——一个需求引 ... 
- Unity编辑器扩展 Chapter3--Create Custom Inspector
		一.Create Custom Inspector 重绘inspector面板一方面是我们的挂在脚本的窗口变得友好,另一方面可以让其变得更强大,比如添加一些有效性验证. 二.重要说明 1.Editor ... 
- 一个purge参数引发的惨案——从线上hbase数据被删事故说起
		在写这篇blog前,我的心情久久不能平静,虽然明白运维工作如履薄冰,但没有料到这么一个细小的疏漏会带来如此严重的灾难.这是一起其他公司误用puppet参数引发的事故,而且这个参数我也曾被“坑过”. ... 
- 【深入浅出.Net IL】1.一个For循环引发的IL
		.Net底层剖析目录章节 1.[深入浅出.Net IL]1.一个For循环引发的IL 2.[.Net底层剖析]2.stfld指令-给对象的字段赋值 3.[.Net底层剖析]3.用IL来理解属性 1.准 ... 
- Mysql中where条件一个单引号引发的性能损耗
		日常写SQL中可能会有一些小细节忽略了导致整个sql的性能下降了好几倍甚至几十倍,几百倍.以下这个示例就是mysql语句中的一个单引号('')引发的性能耗损,我相信很多朋友都遇到过,甚至还在这样写. ... 
- Spring 循环引用(一)一个循环依赖引发的 BUG
		Spring 循环引用(一)一个循环依赖引发的 BUG Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring 循环 ... 
- Linux Framebuffer驱动剖析之中的一个—软件需求
		嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT双方面的原创技术分享,稍后会公布嵌入式企鹅圈的2 ... 
- 一个由正则表达式引发的血案  vs2017使用rdlc实现批量打印  vs2017使用rdlc  [asp.net core 源码分析] 01 - Session  SignalR  sql for xml path用法  MemCahe  C# 操作Excel图形——绘制、读取、隐藏、删除图形   IOC,DIP,DI,IoC容器
		1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ... 
随机推荐
- Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息
			Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息 http://www.cnblogs.com/zhwx/archive/2012/08/28/266055 ... 
- 封装jdbc  单例模式的应用
			实现增删该查的jdbc封装 import java.io.IOException; import java.io.InputStream; import java.sql.Connection; im ... 
- HDU5838 Mountain(状压DP + 容斥原理)
			题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5838 Description Zhu found a map which is a N∗M ... 
- Solr DIH JDBC 源码解析
			Solr DIH 源码解析 DataImportHandler.handleRequestBody()中的importer.runCmd(requestParams, sw) if (DataImpo ... 
- 【填坑】bzoj3224 splay裸题
			人生第一道splay不出所料是一道裸题,一道水题,一道2k代码都不到的题 #include <cstdio> ,n,p,q; ],c[][],size[],sp[]; void rot(i ... 
- Notepad++ 默认快捷键
			Notepad++绝对是windows下进行程序编辑的神器之一,要更快速的使用以媲美VIM,必须灵活掌握它的快捷键,下面对notepad++默认的快捷键做个整理(其中有颜色的为常用招数): 1 ... 
- VMware Workstation 12序列号
			VMware Workstation 12序列号:5A02H-AU243-TZJ49-GTC7K-3C61N 就好像之前微软,让大家用盗版一样,这样可以更快的拥有市场占有率.事实上,输入key即可永久 ... 
- 复习排序with javascript
			最近又翻看了一下数据结构(数据结构学渣). 以前总是看不懂,连冒泡和选择排序都要纠结半天,后来才慢慢有意识能区分开来. 当真的理解了快速排序之后,才觉得,这是个很赞的排序,很容易理解. 于是简单的,模 ... 
- [LintCode] Merge Two Sorted Lists 混合插入有序链表
			Merge two sorted (ascending) linked lists and return it as a new sorted list. The new sorted list sh ... 
- <十二>JDBC_批量处理
			import java.sql.Connection;import java.sql.PreparedStatement;import org.junit.Test;import com.kk.jdb ... 
