• 360彩票官网

  • 360彩票官网

  • 360彩票官网

  • 熱門pao)ㄌ/h3>

360彩票官网

作者︰  發布日期(qi)︰2020-02-21 19:57:05
Tag標簽(qian)︰編輯(ji)器  狀態  
  • 文章作者︰松陽

    本(ben)文出自 阿修羅道,禁(jin)止用于商業用途,轉載請注明(ming)出處(chu)。

    原(yuan)文鏈(lian)接︰http://blog.csdn.net/fansongy/article/details/53318791

     

     

     

     

     

     

     

     

     



     


     

    做編輯(ji)器插件時,我總是想要(yao)拿到(dao)監听編輯(ji)器的狀態變化。比如在(zai)打(da)開編輯(ji)器開始運行自己的服務。這時ben)托枰yao)用戶打(da)開編輯(ji)器的事(shi)件。再比如我希望在(zai)游(you)戲(xi)退出運行模式之前(qian),把一(yi)些(xie)編輯(ji)的東西(xi)緩存出來,然(ran)後對(dui)這些(xie)數(shu)據(ju)做自動化處(chu)理,那麼(me)我就需要(yao)退出運行模式的事(shi)件。諸如此類吧。

    另一(yi)方面,我希望用觀察者模式,並且能自動化注冊。因為我注意到(dao),導入資shi)詞鋇ssetImporter回調就是這樣做的。用戶只(zhi)需要(yao)實現(xian)一(yi)個接口,就可(ke)以收(shou)到(dao)回調。極大的簡化了擴展(zhan)流程(cheng)。編輯(ji)器代(dai)碼又(you)不必考慮效率(lv)問題,借助C#的反射,可(ke)以很容(rong)易的實現(xian)這種功能。

    概述

    整套框架(jia)的啟動核心是屬性(xing)InitializeOnLoad。當Unity3d運行或(huo)啟動時,會重新加載有腳本(ben)。當bi)shi)用這個宏時,編輯(ji)器會自動將被標注的類實例化到(dao)內存中。因此我們可(ke)以利(li)用這個特性(xing),在(zai)它的構造函數(shu)中拉(la)起我們整個服務。 這里(li)有個小技巧。在(zai)啟動Unity編輯(ji)器的情況下,如果在(zai)構造函數(shu)中創建對(dui)象,會被其他清除函數(shu)干掉。我認(ren)為是腳本(ben)jing)跏薊 承xu),或(huo)是場景切換(huan)引起的,具體(ti)原(yuan)因得問Unity了。為了解決這個問題,我借助了update函數(shu),跳(tiao)了一(yi)幀執行應有的邏(luo)輯(ji)。

    自動注冊是借助C#的反射,通過GetAssemblies和GetTypes獲取到(dao)所(suo)有的類,然(ran)後創建出對(dui)應的實例。

    包(bao)裝

    這個類我覺得有個特別適合的名字——NightWatch。如果你沒看過冰與火之歌,可(ke)能理解這個框架(jia)還算有點(dian)難度(du)。總的說(shuo)來,這個框架(jia)講(jiang)述了一(yi)個少年加入守夜人(ren)隊you)椋 ???cheng)之外戰斗的故事(shi)...

    實現(xian)

    接口類如下︰

    public interface ICrow{ /// <summary> /// Join the Nights Watch /// </summary> void Enroll(); /// <summary> /// Before to Enter Wild /// </summary> void PrepareForBattle(); /// <summary> /// To the Weirwood outside the wall /// </summary> void FaceWeirwood(); /// <summary> /// Back To the Castle Black /// </summary> void OpenTheGate(); /// <summary> /// Tell Vow to the Old God /// </summary> void Vow();}

    實例類如下︰

    using UnityEngine;using System.Collections;using System.Collections.Generic;using UnityEditor;[InitializeOnLoad]public class NightsWatch{ #region Public Attributes #endregion #region Private Attributes private static List<ICrow> m_crows = new List<ICrow>(); #endregion #region Public Methods static NightsWatch() { if (!EditorApplication.isPlayingOrWillChangePlaymode) {  EditorApplication.update += WelcomeToCastleBlack; } else  {  EditorApplication.update += BeyondTheWall; } } static void WelcomeToCastleBlack() { EditorApplication.update -= WelcomeToCastleBlack; //Debug.Log("Welcome To castle black"); m_crows.Clear(); var crows = GetAllImplementTypes<ICrow>(System.AppDomain.CurrentDomain); foreach (var eachCrow in crows) {  eachCrow.Enroll();  m_crows.Add(eachCrow); } EditorApplication.update += WaitForWild; } static void WaitForWild() { if (EditorApplication.isPlayingOrWillChangePlaymode) {  foreach (var eachCrow in m_crows)  {  eachCrow.PrepareForBattle();  }  EditorApplication.update -= WaitForWild; } } static void BeyondTheWall() { EditorApplication.update -= BeyondTheWall; //Debug.Log("Welcome To The Wild"); m_crows.Clear(); var crows = GetAllImplementTypes<ICrow>(System.AppDomain.CurrentDomain); foreach (var eachCrow in crows) {  eachCrow.FaceWeirwood();  m_crows.Add(eachCrow); } EditorApplication.update += WaitForCrowReturn; } static void WaitForCrowReturn() { if (!EditorApplication.isPlayingOrWillChangePlaymode ) {  //Debug.Log("Open the Door");  EditorApplication.update -= WaitForCrowReturn;  foreach (var eachCrow in m_crows)  {  eachCrow.OpenTheGate();  }  EditorApplication.update += WelcomeToCastleBlack; } } public static void CrowsVow() { foreach (var eachCrow in m_crows) {  eachCrow.Vow(); } } [MenuItem("Land/CastleBlack")] public static void MakeVow() { NightsWatch.CrowsVow(); } #endregion #region Override Methods #endregion #region Private Methods public static T[] GetAllImplementTypes<T>(System.AppDomain aAppDomain) where T : class { var result = new List<T>(); var assemblies = aAppDomain.GetAssemblies(); foreach (var assembly in assemblies) {  var types = assembly.GetTypes();  foreach (var type in types)  {  if (typeof(T).IsAssignableFrom(type))  {   if (!type.IsAbstract)   {   var tar = assembly.CreateInstance(type.FullName) as T;   result.Add(tar);   }  }  } } return result.ToArray(); } #endregion}

    簡單解釋一(yi)下,所(suo)有的接口都是qian)湊氈牖鷸 柚械木縝槎ding)義。當在(zai)編輯(ji)狀態下lv)保 崠唇 dui)應的實例類,並調用Enroll函數(shu),這相當于Jon剛剛進入CastleBlack。當點(dian)擊Play運行時,會先調用PrepareForBattle,相當于在(zai)城(cheng)堡中準備出征。當游(you)戲(xi)開始運行時,會調用FaceToWeirWood,這里(li)對(dui)應的是城(cheng)外那顆魚梁木,一(yi)般出征之前(qian)都是要(yao)去祈禱一(yi)下。然(ran)後當游(you)戲(xi)運行結束時,會調用OpenTheGate,對(dui)應出征回來,在(zai)長城(cheng)下面喊門。然(ran)後有個Vow接口,這個是用來點(dian)名的,城(cheng)堡里(li)的烏鴉都jia) 卸喲ldquo;道”。

    使(shi)用

    新建兩個實例︰ 一(yi)個是JonSnow:

    public class JonSnow : ICrow{ public void Enroll() { Debug.Log(this + " join the NightWatch!"); } public void PrepareForBattle() { Debug.Log(this + " follow your lead!"); } public void FaceWeirwood() { Debug.Log("I'm the wolf in the north"); } public void OpenTheGate() { Debug.Log(this + " request enter Castle Black"); } public void Vow() { Debug.Log(this + " For The Watch"); }}

    一(yi)個是Samwell:

    public class Samwell : ICrow{ public void Enroll() { Debug.Log(this + " I came form Lord Randyll Tarly,and I even his oldest son ..."); } public void PrepareForBattle() { Debug.Log(this + " is not ready yet..."); } public void FaceWeirwood() { Debug.Log("I'm a useless warrior,but may be ... helpful"); } public void OpenTheGate() { Debug.Log(this + " also want enter"); } public void Vow() { Debug.Log(this + " For The ... alive"); }}

    測(ce)試(shi)

    當寫好me)dai)碼編譯完成時,就能在(zai)輸出中看到(dao)他倆(lian)到(dao)長城(cheng)去報道了。點(dian)擊運行程(cheng)序(xu),關閉運行程(cheng)序(xu),會分別有日志輸出,效果如下︰


    其中紅線是點(dian)擊Play操作,綠線是停止Unity運行的操作,紅線以上(shang)的日志是打(da)開unity或(huo)重新編譯時bi)涑齙摹Ryi)切按照預期(qi)實現(xian),收(shou)zhan)?/p>

    如果你覺得這篇文章對(dui)你有幫助,可(ke)以順手點(dian)個頂(ding),不但不huan)嵯駁鋇 鼓莧黴噯ren)能看到(dao)它...
     

About IT165 -廣(guang)告服務 -隱私聲(sheng)明(ming) -版權申明(ming) -免責條款 -網站地(di)圖 -網友投稿 -聯系方式
本(ben)站內容(rong)來自于互聯網,僅(jin)供用于網絡技術學(xue)習,學(xue)習中請遵(zun)循相關法律(lv)法規
360彩票官网 | 下一页