一个美术需求引发的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. 一些特殊字符,如“&”,“- ...
随机推荐
- System中记录体函数命名怪异
//1019unit System; 中发现记录体函数命名怪异//乍一看,很怪异,其实是结构体里面 的变量后面直接写 函数类型了.不像传统先定义T***Event = procedure(S ...
- Asp.net MVC中Html.Partial, RenderPartial, Action,RenderAction 区别和用法(mvc部分视图的添加)
Partial 和RenderPartial:这两个的性质都是一样, 只指把一个个View给镶入进来, 只是回传值有点不一样Partial 回传的一个Object (MvcHtmlString), 回 ...
- hive 创建三种文件类型的表
--TextFile set hive.exec.compress.output=true; set mapred.output.compress=true; set mapred.output.co ...
- Day 1:开始重新学习
离开很久,前几天翻出以前做过的程序居然还能正常运行.有一点后悔,为什么当初没有坚持做下去.Delphi园地前一阵也曾经宣布要关站,但仍然坚持过来了,在此向站长致敬!我也要重新开始! 附图:Delphi ...
- C# SQL 面试题自我总结
1,asp.net单点登录机制 2,多线程同步机制 3,写一个冒泡排序算法 4,写一个递归算法 5,字符串反转 字符串分隔后调用reverse 方法. 6,sql 中ID自动增长,查询31到40条记录 ...
- Python3.5 day3作业一:实现简单的shell sed替换功能
需求: 1.使python具有shell中sed替换功能. #!/usr/bin/env python #_*_conding:utf-8_*_ #sys模块用于传递参数,os模块用于与系统交互. i ...
- 在linux下Java的环境配置
最近开始学习Java语言. 对于我这种初学者来说,一开始,我想先体验,大致看了一下Java语言是什么,如何实现... 然并卵o_O,表示看得很迷糊.还是实践最重要,把环境配置好再开始深入学习. 1.首 ...
- STM32之PWM君
PWM..英语好的人估计又知道这三个大写字母代表哪三个英语单词了.小弟不才,就说中文意思好了:脉冲宽度调制,玩过飞思卡尔的人估计对PWM非常的不陌生吧.电机驱动需要PWM,控制舵机的转向需要PWM,总 ...
- setTimeout 学习闭包
@(技术笔记)[css] 学习参考网站 css 网站,可供参考 javascript学习网站 var create = function (i){ return function(){ console ...
- perl学习之路1
一切要从Hollo world开始 公司要用perl....啊, 不会只能自学了, 毕竟是公司啊, 不是学校...公司不学习就滚蛋了...惨惨惨 因为是学习嘛, 感觉开虚拟机比较麻烦所以直接用了个 瘟 ...