UnityのMecanimをC#で作り差し替えてみた
本章では、UnityのAnimatorControllerをプログラムで動的に作り、差し替える方法について共有します。
Mecanim
3Dモデルの制作の流れ
3Dモデル制作の流れを確認します。制作のフローを大きく分類すると、以下のように分類できます。
- モデリング
- テクスチャリング
- セットアップ
- アニメーション
これらは、基本的にMayaやMaxといった3DCGソフトウェアを利用して制作します。ゲーム開発の現場では、3DCGソフトウェアで制作したモデルをUnityにインポートさせて、利用するケースが大半を占めます。
Unityでの3Dモデルを扱うには
エンジニアがUnityで3Dモデルを直接利用することは難しいです。そこでUnityでは、3Dモデルを簡単に扱う機構として、「Mecanim」があります。Mecanimには、キャラクタの動きを簡単に制御するための機能として、「ブレンドツリー」や「ステートマシーン」などがあります。これらは、GUIで視覚的に編集ができるため、エンジニアでない人にも簡単に扱えます。
スクリプト
以下に、Animator ControllerをC#で作り差し替えるプログラムを示します。
#if UNITY_EDITOR AnimatorController mecanimController = null; // Animation Controllerファイルを新規作成 mecanimController = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/Resources/Mecanims/HeroMecanim.controller"); // Animation Controllerにアニメーションを遷移させるための条件となるパラメータを追加 mecanimController.AddParameter("RunTrigger", AnimatorControllerParameterType.Trigger); mecanimController.AddParameter("JumpTrigger", AnimatorControllerParameterType.Trigger); mecanimController.AddParameter("SlidingTrigger", AnimatorControllerParameterType.Trigger); mecanimController.AddParameter("DownTrigger", AnimatorControllerParameterType.Trigger); // rootのState Machineを取得 var rootStateMachine = mecanimController.layers[0].stateMachine; // 「Entry State」と「Any State」の位置座標を変更 rootStateMachine.entryPosition = new Vector3(0f, 0f, 0f); rootStateMachine.anyStatePosition = new Vector3(0f, 50f, 0f); // 各アニメーションのState Machineを作成・配置 var runState = rootStateMachine.AddState("runState", new Vector3(200f, 0f, 0f)); mecanimController.SetStateEffectiveMotion(runState, (Motion)Resources.Load<AnimationClip>("AnimationClips/hero_run")); var jumpState = rootStateMachine.AddState("jumpState", new Vector3(200f, 100f, 0f)); mecanimController.SetStateEffectiveMotion(jumpState, (Motion)Resources.Load<AnimationClip>("AnimationClips/hero_jump")); var slidingState = rootStateMachine.AddState("slidingState", new Vector3(200f, 200f, 0f)); mecanimController.SetStateEffectiveMotion(slidingState, (Motion)Resources.Load<AnimationClip>("AnimationClips/hero_sliding")); var downState = rootStateMachine.AddState("downState", new Vector3(200f, 300f, 0)); mecanimController.SetStateEffectiveMotion(downState, (Motion)Resources.Load<AnimationClip>("AnimationClips/hero_down")); // アニメーションの遷移条件を設定 runState.AddTransition(jumpState).AddCondition(AnimatorConditionMode.If, 0, "JumpTrigger"); runState.AddTransition(slidingState).AddCondition(AnimatorConditionMode.If, 0, "SlidingTrigger"); runState.AddTransition(downState).AddCondition(AnimatorConditionMode.If, 0, "DownTrigger"); jumpState.AddTransition(runState).AddCondition(AnimatorConditionMode.If, 0, "RunTrigger"); jumpState.AddTransition(downState).AddCondition(AnimatorConditionMode.If, 0, "DownTrigger"); slidingState.AddTransition(runState).AddCondition(AnimatorConditionMode.If, 0, "RunTrigger"); slidingState.AddTransition(downState).AddCondition(AnimatorConditionMode.If, 0, "DownTrigger"); downState.AddTransition(runState).AddCondition(AnimatorConditionMode.If, 0, "RunTrigger"); #else // UnityのEditor環境でない場合、ResourceフォルダからAnimation Controllerを取得 RuntimeAnimatorController mecanimController = Resources.Load<RuntimeAnimatorController>("Mecanims/HeroMecanim"); #endif // Animatorが設定されているオブジェクトを取得 this.heroAnimator = gameObject.GetComponent<Animator>(); #if UNITY_EDITOR // 上記で作成したAnimation ControllerをAnimatorのruntimeAnimatorControllerに設定 this.heroAnimator.runtimeAnimatorController = new AnimatorOverrideController() { runtimeAnimatorController = (RuntimeAnimatorController)mecanimController }; #else // 上記で取得したAnimation ControllerをAnimatorのruntimeAnimatorControllerに設定 this.heroAnimator.runtimeAnimatorController = new AnimatorOverrideController() { runtimeAnimatorController = mecanimController }; #endif
注意点として、Animator側のAnimator Controllerには、Runtime Animator ControllerにAnimator Controllerを設定する必要があります。またEditor上でのみ、Animator Controllerを作れるので、本番環境では生成されたAnimator Controllerを利用しましょう。