需求
- Editor模式下钞速,在運(yùn)行或者非運(yùn)行狀態(tài)下,能夠按照指定的變化率來(lái)自動(dòng)改變material中屬性數(shù)值。
需求分析
如何在Editor模式下獲得一個(gè)游戲?qū)ο蠹捌浣M件,尤其是在非運(yùn)行狀態(tài)下降瞳?我們知道在Unity IDE運(yùn)行起來(lái)后是很容易獲得一個(gè)對(duì)象和組件的,在GameObject上掛一個(gè)腳本即可蚓胸。但是在非運(yùn)行狀態(tài)下呢挣饥,
transform.GetComponent
這樣的方法怎么執(zhí)行?好在unity已經(jīng)為我們考慮到了這個(gè)問(wèn)題沛膳,提供了[ExecuteInEditMode]
Attribute扔枫,通過(guò)指定這個(gè)attribute使得組件類中的方法可以在edit模式下執(zhí)行,并且是在非運(yùn)行狀態(tài)下的锹安。如何在非運(yùn)行狀態(tài)下勻速改變數(shù)值呢短荐?update方法中配合
Time.deltaTime
是一個(gè)完美的方案倚舀,但是即使設(shè)置了[ExecuteInEditMode]
,update的表現(xiàn)在非運(yùn)行和運(yùn)行時(shí)也是完全不同的忍宋,查資料看到 is only called when something in the scene changed. 這句話時(shí)也有種吐槽的沖動(dòng)瞄桨。好在unity又為大家考慮到了這個(gè)問(wèn)題(話說(shuō)unity editor確實(shí)功能強(qiáng)大,AssetAtore里面那些插件真是厲害),Edit模式下提供了EditorApplication.update
讶踪,這是一個(gè)事件芯侥,我們注冊(cè)一個(gè)自己的方法就可以在非運(yùn)行狀態(tài)下實(shí)現(xiàn)update的功能。我個(gè)人比較推薦使用EditorCoroutine乳讥,一個(gè)基于EditorApplication.update
的協(xié)程實(shí)現(xiàn)柱查。
功能實(shí)現(xiàn)
- 使用一個(gè)自定義組件來(lái)實(shí)現(xiàn)material中數(shù)值的修改,這個(gè)類在UI上要體現(xiàn)出能夠設(shè)置變化速率和初始值云石。并且在UI上通過(guò)點(diǎn)擊按鈕的形式來(lái)觸發(fā)改變唉工。
- 使用Custom Inspector來(lái)實(shí)現(xiàn)組件UI的自定義。
- 在運(yùn)行狀態(tài)下通過(guò)使用默認(rèn)的update來(lái)實(shí)現(xiàn)勻速變化汹忠,在非運(yùn)行狀態(tài)下通過(guò)使用EditorCoroutine來(lái)實(shí)現(xiàn)淋硝。
代碼實(shí)現(xiàn)
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創(chuàng)建的Editor類,在這個(gè)類里面可以修改UVAnimation類的UI宽菜,可以調(diào)用UVAnimation類中的方法谣膳。OnInspectorGUI
方法,顧名思義在里面可以對(duì)UI進(jìn)行編程铅乡,注意一下這個(gè)方法會(huì)自己生產(chǎn)一句代碼base.OnInspectorGUI ();
继谚,我所注釋掉的DrawDefaultInspector ();
這句代碼都是用來(lái)繪制默認(rèn)UI的,二者只可留其一阵幸。transform.GetComponent<Renderer>().sharedMaterials
在edit模式下獲取材質(zhì)球的對(duì)象需要用sharedMaterials
花履。mainTextureScale
對(duì)應(yīng)的就是UI上的Tiling。命名這讓人吐槽挚赊。