Unity3D讀取模型文件自動生成AnimatorController簡單實例


前幾天接到一個任務,做一個導入、控制模型動畫的工具類,沒有太具體的要求,於是就自行思考實際需求,最終根據宣雨松老師的一篇博客,自己規范了一下寫了一個工具類。相關工具代碼及測試用例已上傳至Github。

https://github.com/hcy12321/UnityAnimatorControllerMaker

該demo需在導入Unity后執行菜單Tools/CreateAnimator項后再執行。

1.需求及規范

需求是指實際使用時需要實現的地方,規范是最終使用這套工具需要遵守的規則。

1.1 實際需求

1. 能自動遍歷fbx文件,且生成對應的AnimatorController文件。

2. 能獲取fbx文件中所有的動畫片段(AnimationClip),並存入第一步生成的AnimatorController的狀態機中。

3.(個人假設需求)狀態機默認指向一個空的動畫。 

1.2 使用規范

1. 所有fbx文件需放置在Assets/Resources/fbx目錄(該目錄可在代碼中更改)中的子目錄中,該子目錄以fbx名稱(不可包含中文)命名,將fbx文件和貼圖放到該子目錄中,然后將fbx文件重命名為原名_model。

如:wukong.fbx。因和其貼圖一起放置在 Assets\Resources\fbx\wukong目錄中,然后改名為wukong_model.fbx。

 

2.功能實現

該部分主要介紹邏輯功能代碼

2.1 生成菜單方法

在Editor目錄下添加類文件AnimatorTool.cs,該類共有三個方法:

void CreateAnimationAssets(): 工具菜單方法,內有遍歷目錄生成動畫控制器、生成預設的邏輯

using System;
using UnityEngine;
using System.Collections;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.Animations;

public class AnimatorTool : MonoBehaviour
{

    /// <summary>
    /// 菜單方法,遍歷文件夾創建Animation Controller
    /// </summary>
    [MenuItem("Tools/CreateAnimator")]
    static void CreateAnimationAssets()
    {
        string rootFolder = "Assets/Resources/fbx/";
        if (!Directory.Exists(rootFolder))
        {
            Directory.CreateDirectory(rootFolder);
            return;
        }
        // 遍歷目錄,查找生成controller文件
        var folders = Directory.GetDirectories(rootFolder);
        foreach (var folder in folders)
        {
            DirectoryInfo info = new DirectoryInfo(folder);
            string folderName = info.Name;
            // 創建animationController文件
            AnimatorController aController =
                AnimatorController.CreateAnimatorControllerAtPath(string.Format("{0}/animation.controller", folder));
            // 得到其layer
            var layer = aController.layers[0];
            // 綁定動畫文件
            AddStateTranstion(string.Format("{0}/{1}_model.fbx", folder, folderName), layer);
            // 創建預設
            GameObject go = LoadFbx(folderName);
            PrefabUtility.CreatePrefab(string.Format("{0}/{1}.prefab", folder, folderName), go);
            DestroyImmediate(go);
        }


    }

    /// <summary>
    /// 添加動畫狀態機狀態
    /// </summary>
    /// <param name="path"></param>
    /// <param name="layer"></param>
    private static void AddStateTranstion(string path, AnimatorControllerLayer layer)
    {
        AnimatorStateMachine sm = layer.stateMachine;
        // 根據動畫文件讀取它的AnimationClip對象
        var datas = AssetDatabase.LoadAllAssetsAtPath(path);
        if (datas.Length == 0)
        {
            Debug.Log(string.Format("Can't find clip in {0}", path));
            return;
        }
        // 先添加一個默認的空狀態
        var emptyState = sm.AddState("empty");
        sm.AddAnyStateTransition(emptyState);
        // 遍歷模型中包含的動畫片段,將其加入狀態機中
        foreach (var data in datas)
        {
            if (!(data is AnimationClip))
                continue;
            var newClip = data as AnimationClip;
            if (newClip.name.StartsWith("__"))
                continue;
            // 取出動畫名字,添加到state里面
            var state = sm.AddState(newClip.name);
            state.motion = newClip;
            // 把State添加在Layer里面
            sm.AddAnyStateTransition(state);
        }

    }

    /// <summary>
    /// 生成帶動畫控制器的對象
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static GameObject LoadFbx(string name)
    {
        var obj = Instantiate(Resources.Load(string.Format("fbx/{0}/{0}_model", name))) as GameObject;
        obj.GetComponent<Animator>().runtimeAnimatorController =
            Resources.Load<RuntimeAnimatorController>(string.Format("fbx/{0}/animation", name));
        return obj;
    }
}

2.2 測試用例

測試用例中主要包含如何調用播放動畫、暫停動畫、重播動畫等功能。

using UnityEngine;
using System.Collections;

public class AnimatorTest : MonoBehaviour
{
    private Animator animator;

    public string animationName = "run";

    public float Speed = 1.0f;
    // Use this for initialization
    void Start()
    {
        animator = GetComponent<Animator>();
    }

    /// <summary>
    /// 添加一些測試功能按鈕
    /// </summary>
    void OnGUI()
    {
#if UNITY_EDITOR
        if (GUILayout.Button("Play"))
        {
            Play(animationName);
        }
        if (GUILayout.Button("Replay"))
        {
            RePlay(animationName);
        }
        if (GUILayout.Button("Pause"))
        {
            Pause();
        }
#endif
    }

    /// <summary>
    /// 設置速度
    /// </summary>
    /// <param name="speed"></param>
    public void SetSpeed(float speed)
    {
        Speed = speed;
    }

    /// <summary>
    /// 重新播放指定名稱動畫
    /// </summary>
    /// <param name="name"></param>
    public void RePlay(string name)
    {
        animator.speed = Speed;
        animator.Play(name, 0, 0.0f);
    }

    /// <summary>
    /// 播放指定名稱動畫
    /// </summary>
    /// <param name="name"></param>
    public void Play(string name)
    {
        animator.speed = Speed;
        animator.Play(name);
    }

    /// <summary>
    /// 暫停動畫
    /// </summary>
    public void Pause()
    {
        animator.speed = 0.0f;
    }
}

3.總結

該工具在項目實際使用中還有許多待優化的地方,如只考慮了一個模型,如果是一個人物有多個模型那么還要根據需求再重新設計。還有狀態機中還沒有根據模型直接生成結構動畫、序列動畫的功能,需要在以后繼續改進。

本工具參考了宣雨松老師的一篇博客:http://www.xuanyusong.com/archives/2811

如有問題請指正,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM