由一個(gè)美術(shù)需求引發(fā)的Custom Inspector

需求

  • 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。命名這讓人吐槽挚赊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诡壁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子荠割,更是在濱河造成了極大的恐慌妹卿,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涨共,死亡現(xiàn)場(chǎng)離奇詭異纽帖,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)举反,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)懊直,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人火鼻,你說(shuō)我怎么就攤上這事室囊〉癖溃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵融撞,是天一觀的道長(zhǎng)盼铁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)尝偎,這世上最難降的妖魔是什么饶火? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮致扯,結(jié)果婚禮上肤寝,老公的妹妹穿的比我還像新娘。我一直安慰自己抖僵,他們只是感情好鲤看,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著耍群,像睡著了一般义桂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹈垢,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天慷吊,我揣著相機(jī)與錄音,去河邊找鬼耘婚。 笑死罢浇,一個(gè)胖子當(dāng)著我的面吹牛陆赋,可吹牛的內(nèi)容都是我干的沐祷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼攒岛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赖临!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起灾锯,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤兢榨,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后顺饮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吵聪,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年兼雄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吟逝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赦肋,死狀恐怖块攒,靈堂內(nèi)的尸體忽然破棺而出励稳,到底是詐尸還是另有隱情,我是刑警寧澤囱井,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布驹尼,位于F島的核電站,受9級(jí)特大地震影響庞呕,放射性物質(zhì)發(fā)生泄漏新翎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一住练、第九天 我趴在偏房一處隱蔽的房頂上張望料祠。 院中可真熱鬧,春花似錦澎羞、人聲如沸髓绽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)顺呕。三九已至,卻和暖如春括饶,著一層夾襖步出監(jiān)牢的瞬間株茶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工图焰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留启盛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓技羔,卻偏偏與公主長(zhǎng)得像僵闯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子藤滥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容