您好,登錄后才能下訂單哦!
很慚愧從事游戲開發三年半才開始記錄,之前也有一些零散信息記錄在有道云筆記里,但都不成體系。那就從現在開始吧!
最近項目剛出完demo,有些銜接的時間,花了一天時間寫了一個方便美術同學操作的小工具。第一次寫拓展編輯器,做好之后超級興奮的說,哈哈~這個工具主要是根據某類人物的AnimatorController的模板,拷貝并將當前人物的動作自動賦值的過程,避免了手動拖拽動作操作的繁雜和失誤。比如,monster一般可以共用AnimatorController的layer信息,只是各個state中的motion要對應各個人物的動作。
當然,寫的還不夠靈活,有一些目錄和命名的要求。
1、AnimatorController模板文件的目錄地址:放在該類型人物的文件夾下,如monster文件夾下
2、每個人物模型的skin文件的目錄地址:放在該人物的文件夾下,如怪物1文件夾下
3、各個動作文件命名規范:怪物名@動作名,如monster_blk@skin、monster_blk@idlel01
monster文件夾
—AnimatorController(monster共用的AnimatorController模板文件)
—monster_blk(怪物1的資源文件夾)
—Anim(怪物1的動作文件夾)
—Materials(怪物1的材質文件夾)
—Tex(怪物1的貼圖文件夾)
—monster_blk@skin(怪物1的skin文件)
—monster_blkw(怪物2的資源文件夾)
—Anim(怪物2的動作文件夾)
—Materials(怪物2的材質文件夾)
—Tex(怪物2的貼圖文件夾)
—monster_blkw@skin(怪物2的skin文件)
和美術同學規范好細節后,就可以開始編碼啦~話不多說,直接上代碼~
新建一個EditorAnimatorController腳本,放在工程目錄Editor下。
using UnityEditor; using UnityEngine; using System.Collections; using System.IO; public class EditorAnimatorController{ //controller模板名和拷貝后的名稱 private static string fileName = "AnimatorController.controller"; [MenuItem("AnimatorController/CreateAnimatorController")] static void CreateAnimatorController() { //獲得當前選中為GameObject格式的文件 object[] objs = Selection.GetFiltered (typeof(GameObject), SelectionMode.Assets); GameObject selectObj = null; if (objs.Length < 1) { Debug.LogError("Please select a model file"); return; } //判斷是否選中了skin文件,名字含有"@skin" foreach (GameObject obj in objs) { if(obj.name.Contains("@skin")) { selectObj = obj; } } //如果沒有選中,則提示錯誤并返回 if (selectObj == null) { Debug.LogError("Please select a skin file"); return; } //獲得模板文件的路徑(沒有找到獲得上一級上上級目錄的API,只好使用字符切割了) string selectObjPath = AssetDatabase.GetAssetPath((Object) selectObj); string[] array = selectObjPath.Split('/'); string templetControlPath = null; string animatorControllerPath = null; for (int i = 0; i < array.Length; ++i) { if(i == (array.Length - 1) ) continue; animatorControllerPath += array[i] + "/"; if(i == (array.Length - 2) ) continue; templetControlPath += array[i] + "/"; } //判斷模板文件是否在該類型人物文件夾下 if (!File.Exists (templetControlPath + fileName)) { Debug.LogError("The templet control file is missing"); return; } //如果還沒有生成AnimatorController文件,則將模板文件拷貝 if (!File.Exists (animatorControllerPath + fileName)) { FileUtil.CopyFileOrDirectory (templetControlPath + fileName, animatorControllerPath + fileName); Debug.Log("copy animator control success"); } //注意下方高能坑!之前沒有刷新,導致下面的animatorController一直為null AssetDatabase.Refresh (); //通過AssetDatabase類load新拷貝的文件,獲得animatorController對象 UnityEditor.Animations.AnimatorController animatorController = AssetDatabase.LoadAssetAtPath (animatorControllerPath + fileName, typeof(UnityEditor.Animations.AnimatorController)) as UnityEditor.Animations.AnimatorController; //獲得layer信息 UnityEditor.Animations.AnimatorControllerLayer layer = animatorController.layers[0]; //獲得stateMachine信息 UnityEditor.Animations.AnimatorStateMachine sm = layer.stateMachine; //獲得該人物文件夾下Anim文件夾中的動作資源 string animPath = animatorControllerPath + "Anim"; string[] assets = AssetDatabase.FindAssets( "t:GameObject" , animPath.Split() ); AnimationClip[] animClip = new AnimationClip[assets.Length]; //獲得目錄下所有的AnimationClip對象 for (int i = 0; i < assets.Length; ++i) { string path = AssetDatabase.GUIDToAssetPath(assets[i]); animClip[i] = AssetDatabase.LoadAssetAtPath(path, typeof(AnimationClip)) as AnimationClip; } //通過名稱匹配,將AnimationClip一一對應上state的motion for (int i = 0; i < sm.states.Length; ++i) { for(int j = 0 ; j < animClip.Length ; ++j) { if(animClip[j].name.Contains(sm.states[i].state.name)) { sm.states[i].state.motion = animClip[j]; } } } } }
好啦,先記錄到這~周一繼續寫將當前AnimatorController附加到人物身上并生成Prefab到指定目錄~
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。