25
2021
09

杩峰鍦板浘缂栬緫鍣細Xnode鎻掍欢瀹炶返

鍓嶈█


鍦╱nity寮鍙戞父鎴忕紪杈戝櫒鎵╁睍涓紝鎴戜滑甯稿父浼氱敤鍒拌妭鐐圭紪杈戝櫒銆傝妭鐐圭紪杈戝櫒灏辨槸鐢ㄨ妭鐐瑰拰鑺傜偣杩炴帴鐨勫浘褰㈣瘽缂栬緫鍣紝姣斿unity鑷甫鐨剆hadergraph灏辨槸涓涓妭鐐圭紪杈戝櫒銆傜敤鎴烽氳繃鑺傜偣涔嬮棿鐨勬嫋鎷栨媺鎷夛紝杩炵嚎灏辫兘寰楀埌鎯宠鐨勭粨鏋溿

鍦ㄤ竴娈垫椂闂撮噷锛屾墦绠楀仛涓涓糠瀹殑鍦板浘缂栬緫鍣紝姣忎釜鍦板浘鏈変笂涓嬪乏鍙4涓棬锛屽彲浠ュ拰鍏朵粬鍦板浘杩炴帴銆備簬鏄墦绠楀紑鍙戜竴涓紪杈戝櫒锛岄氳繃鍙鍖栫殑鏂瑰紡鍘荤敓鎴愭暣涓糠瀹殑鏁版嵁銆傛煡浜嗗緢澶氱殑鑺傜偣鎻掍欢锛寈node浣滀负杞婚噺绾х殑鑺傜偣缂栬緫鍣ㄥ氨闈炲父閫傚悎鐢ㄦ潵鍋氫簩娆″紑鍙

Xnode锛https://github.com/Siccity/xNode锛夋槸寮婧愮殑杞婚噺绾х殑鑺傜偣缂栬緫鍣ㄦ彃浠躲傛墍浠ョ悊瑙e拰寮鍙戣捣鏉ラ潪甯告柟渚

鏈缁堝紑鍙戞晥鏋滃涓嬨傚彲浠ュ湪绐楀彛鍐呭垱寤鸿妭鐐癸紝璁剧疆鍥涗釜闂ㄧ殑璺宠浆鍏崇郴锛屾渶缁堢偣鍑诲鍑轰繚瀛樹负涓涓寚瀹氱殑鏁版嵁鏂囦欢

灞忓箷鎴浘 2021-09-25 193709


瀹夎Xnode


浠巊ithub涓嬭浇杩欎釜鎻掍欢锛岃В鍘嬪嚭鏉ユ斁鍦ˋssets鐩綍涓嬪嵆鍙

涓嶈繃杩欓噷鎴戝仛浜嗕竴鐐圭偣鏀瑰姩銆傝冭檻鍒板彧鎯宠xnode鐨勭紪杈戝櫒鍔熻兘锛屼笉鎵撶畻鎵撳寘鐨勬椂鍊欐妸xnode鐨勪唬鐮佸甫鍒版渶缁堢殑鍖呴噷闈紝鎵浠ユ妸runtime鐨勪唬鐮佸叏閮ㄦ斁鍒颁簡Editor鐩綍閲岄潰銆傝繖鏍峰氨鍙互淇濊瘉鎵撳寘鏃跺欙紝鎴戜滑娓告垙鐨勫伐绋嬫槸鍜寈node鐩镐簰鐙珛鐨勩

濡傚浘鎵绀猴紝鐜板湪宸ョ▼閲岄潰浠g爜鍏ㄩ儴鍦‥ditor涓嬮潰

灞忓箷鎴浘 2021-09-25 194330


瀹氫箟鍥惧拰鑺傜偣


xnode鏄潪甯歌交閲忕骇鐨勯潪甯告槗寮鍙戠殑銆傚畠鐨勬蹇靛氨鏄浘Graph锛岃妭鐐筃ode锛岀鍙ort銆傜鍙f垜浠彲浠ュ厛涓嶅叧蹇冦傚厛鏉ュ畾涔変竴涓嬪浘

[CreateAssetMenu(fileName = "mazelayer", menuName = "UmGame/鍦烘櫙/杩峰缂栬緫鍣ㄦ暟鎹")]
public class MazeLayerGraph : NodeGraph
{
}

灏辨槸杩欎箞绠鍗曪紝缁ф壙涓涓婲odeGraph鍗冲彲銆

杩欓噷缁橫azeLayerGraph鍔犱簡涓涓狢reateAssetMenu鏍囩銆傝繖鏍峰氨鍙互鍦≒roject闈㈡澘涓紝閫氳繃鍙抽敭鑿滃崟鐨勬柟寮忓垱寤哄嚭杩欎釜鍥炬枃浠躲

灞忓箷鎴浘 2021-09-25 195638

鍒涘缓涔嬪悗锛屽氨鍙互閫氳繃鍙屽嚮杩欎釜鏂囦欢鎴栬呭湪Inspector闈㈡澘涓偣鍑籓pen鎴栬呯偣鍑籈ditGraph閮藉彲浠ユ墦寮

灞忓箷鎴浘 2021-09-25 200003

鎵撳紑鐨勭晫闈粈涔堥兘娌℃湁锛屽彸閿彍鍗曢噷闈篃娌′粈涔堜笢瑗

灞忓箷鎴浘 2021-09-25 200210

杩欐槸鍥犱负杩樻病鏈夊畾涔夎妭鐐筃ode锛屾墍浠ュ紑濮嬪畾涔変竴涓婲ode

涔熷緢绠鍗曪紝缁ф壙Node鍗冲彲銆傝繖閲屽洜涓哄悗闈㈡墦绠楄鐢讳竴涓糠瀹埧闂寸殑鍥撅紝杩樿璁板綍鎴块棿鐨処D锛屾墍浠ュ畾涔変簡涓浜涘彉閲忋傚洖鍒皍nity锛屽彸閿氨鍙互鐪嬪埌鏈変竴涓彍鍗曚簡

灞忓箷鎴浘 2021-09-25 200917

閫夋嫨杩欎釜鑿滃崟灏卞彲浠ュ垱寤哄嚭涓涓妭鐐逛簡

灞忓箷鎴浘 2021-09-25 201637

浣嗘槸杩欎簺鏁版嵁涓嶆槸鎴戞兂鍦ㄥ浘涓睍绀虹殑锛屾墍浠ユ墦绠楅噸鍐欒妭鐐圭殑缁樺埗銆


Node閲嶇粯


xnode涓疄鐜癗ode閲嶇粯闈炲父绠鍗曪紝鍙绫讳技unity鍐欎竴涓狢ustomEditor灏卞彲浠ャ傚浜屾寮鍙戦潪甯稿弸濂姐

namespace Game
{

    [CustomNodeEditor(typeof(MazeLayerRoomNode))]
     public class MazeLayerRoomNodeEditor : NodeEditor
     {
         public override void OnHeaderGUI()
         {
             var tar = (MazeLayerRoomNode)target;
             var head = tar.RoomID.ToString();
             if (!string.IsNullOrEmpty(tar.RoomName))
                 head += ":" + tar.RoomName;
             EditorGUILayout.LabelField(head, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
         }

        public override int GetWidth()
         {
             return 115;
         }

        public Rect[] Points = new Rect[4];

        public override void OnBodyGUI()
         {
             var tar = (MazeLayerRoomNode)target;
             var width = GetWidth();
             if (tar.Tex == null)
                 tar.Tex = AssetDatabase.LoadAssetAtPath<Texture2D>(
                     $"Assets/Game/Art/Map/levelmap/{tar.TerrianID}.png");
             GUILayout.Label("", GUILayout.Width(width - 20), GUILayout.Height(210 / 2f));

            var r = new Rect(20, 35, 150 / 2f, 210 / 2f);
             if (tar.Tex != null)
                 EditorGUI.DrawPreviewTexture(r, tar.Tex);
             else
                 EditorGUI.DrawRect(r, Color.white);

            var height = GUILayoutUtility.GetLastRect().yMax;
             EditorGUILayout.LabelField("", GUILayout.Height(height));
             var rect = new Rect(0, 0, 16, 16);
             foreach (var port in target.DynamicPorts)
             {
                 var rport = port;
                 var strs = rport.fieldName.Split('_');
                 if (strs.Length != 2)
                     continue;
                 var doorid = (EmDoorID)int.Parse(strs[0]);
                 switch (doorid)
                 {
                     case EmDoorID.Bottom:
                         rect.y = height;
                         if (rport.IsInput)
                             rect.x = width / 2f + 8;
                         else
                             rect.x = width / 2f - 8 - 16;
                         break;
                     case EmDoorID.Left:
                         rect.x = 0;
                         if (rport.IsInput)
                             rect.y = height / 2f - 8 - 16;
                         else
                             rect.y = height / 2f + 8;
                         rect.y += 15;
                         break;
                     case EmDoorID.Right:
                         rect.x = width - 16;
                         if (rport.IsInput)
                             rect.y = height / 2f + 8;
                         else
                             rect.y = height / 2f - 8 - 16;
                         rect.y += 15;
                         break;
                     case EmDoorID.Top:
                         rect.y = 0;
                         if (rport.IsInput)
                             rect.x = width / 2f - 8 - 16;
                         else
                             rect.x = width / 2f + 8;
                         break;
                     default:
                         throw new ArgumentOutOfRangeException();
                 }

                var color = rport.IsInput ? Color.red : Color.green;

                NodeEditorGUILayout.DrawPortHandle(rect, Color.black, color);
                 portPositions[rport] = rect.center;
             }
         }

        public override void AddContextMenuItems(GenericMenu menu)
         {
             base.AddContextMenuItems(menu);
             var tar = (MazeLayerRoomNode)target;
             if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node)
             {
                 menu.AddItem(new GUIContent("澧炲姞闂/鈫戜笂"), false, () => tar.AddDoor(EmDoorID.Top));
                 menu.AddItem(new GUIContent("澧炲姞闂/鈫撲笅"), false, () => tar.AddDoor(EmDoorID.Bottom));
                 menu.AddItem(new GUIContent("澧炲姞闂/涓婁笅"), false, () =>
                 {
                     tar.AddDoor(EmDoorID.Bottom);
                     tar.AddDoor(EmDoorID.Top);
                 });
                 menu.AddItem(new GUIContent("澧炲姞闂/鈫愬乏"), false, () => tar.AddDoor(EmDoorID.Left));
                 menu.AddItem(new GUIContent("澧炲姞闂/鈫掑彸"), false, () => tar.AddDoor(EmDoorID.Right));
                 menu.AddItem(new GUIContent("澧炲姞闂/宸﹀彸"), false, () =>
                 {
                     tar.AddDoor(EmDoorID.Right);
                     tar.AddDoor(EmDoorID.Left);
                 });
                 menu.AddItem(new GUIContent("澧炲姞闂/涓婁笅宸﹀彸"), false, () =>
                 {
                     tar.AddDoor(EmDoorID.Bottom);
                     tar.AddDoor(EmDoorID.Top);
                     tar.AddDoor(EmDoorID.Right);
                     tar.AddDoor(EmDoorID.Left);
                 });
             }
         }
     }
}

1銆佺户鎵縉odeEditor锛屾瘮鐢–ustomNodeEditor鍜屾垜浠嚜瀹氫箟鐨凬ode鐩稿叧鑱

2銆佸鍐欎簡OnHeaderGUI锛岃鑺傜偣澶撮儴鏄剧ず鎴块棿鐨処D鍜屽悕绉帮紝杩欐牱鏌ョ湅姣旇緝鏂逛究

3銆佸鍐橤etWidth銆傚洜涓烘垜鐭ラ亾鐢荤殑鍥剧殑澶у皬锛屽叾浠栦笉鎯虫樉绀猴紝鎵浠ュ浐瀹氫负115

4銆佸鍐橭nBodyGUI銆傝繖涓槸閲嶇偣銆傚洜涓哄湪鑺傜偣鐢诲嚭鍥撅紝鎵浠ュ湪杩欎釜鍑芥暟閲岄潰锛屽厛鍘籄ssetDataBase閲岄潰鎵惧埌鍥撅紝鐒跺悗浣跨敤DrawPreviewTexture鐢诲嚭鏉ャ傛渶鍚庢垜瑕佺敾鍑洪棬鐨勫嚭鍏ュ彛锛屾墍浠ヤ娇鐢∟ode鐨凞ynamicPorts瀛樺偍闂ㄧ殑鏁版嵁銆傛渶鍚庢妸杩欎簺port鐨勪綅缃褰曞埌portPositions鏁扮粍涓紝杩欐牱鍒版椂鍊欏幓灏卞彲浠ュ幓鍋氳繛绾夸簡銆

5銆佸鍐橝ddContextMenuItems锛屽湪鑺傜偣鐨勫彸閿彍鍗曠殑鏃跺欏姞涓婁竴浜涘姩鎬佸姞闂ㄧ殑鏂规硶

灞忓箷鎴浘 2021-09-25 203058

濡傚浘锛屾坊鍔4涓棬涔嬪悗锛屽氨鍦ㄨ妭鐐瑰懆鍥寸敾鍑轰簡4涓叆鍙e拰4涓嚭鍙

澶氬姞鍑犱釜鑺傜偣锛岀劧鍚庤繛鎺ヨ捣鏉

灞忓箷鎴浘 2021-09-25 203300

杩欎釜鏇茬嚎涓嶆庝箞婊℃剰锛屾庝箞鍔炪


Graph閲嶇粯


鍦▁node涓紝涓嶄粎Node鍙互閲嶇粯锛孏raph涔熷彲浠

    [CustomNodeGraphEditor(typeof(MazeLayerGraph))]
    public class MazeLayerGraphEditor : NodeGraphEditor
    {

               public override NoodlePath GetNoodlePath(NodePort output, NodePort input)
                {
                     return NoodlePath.Straight;
                }

    }


绫讳技鐨勶紝鎴戜滑鍙缁ф壙NodeGraphEditor锛屽苟鐢–ustomNodeGraphEditor鍜屾垜浠嚜瀹氫箟鐨凣raph鍏宠仈灏卞彲浠ヤ簡銆

涓轰簡瀹炵幇鏇茬嚎鍙樼洿绾匡紝鎴戜滑鍙澶嶅啓GetNoodlePath鍗冲彲锛孨oodlePath.Straight琛ㄧず鐩寸嚎

灞忓箷鎴浘 2021-09-25 203756

OK銆傞偅澶ч儴鍒嗗氨瀹屾垚浜嗐傛渶鍚庡氨鏄繚瀛樹簡銆傛垜浠湪MazeLayerGraphEditor涓殑OnGUI鍙互鍐欎竴涓猙uttom锛岀劧鍚庢妸鐩稿叧鏁版嵁鍐欏埌鑷畾涔夌殑鏁版嵁灏卞彲浠ヤ簡銆



芦 涓婁竴绡 涓嬩竴绡 禄