[Unity]Trilib2でゲームの実行時にFbxのアニメーションをロードする
Trilib2を使用してUnityでゲームの実行時にFbxのアニメーションをロードするメモです。
- Unity 2020.3
- Trilib2
- MixamoでダウンロードしたFbxファイルからモデルとアニメーションをロードする
- 任意のHumanoidモデルにロードしたMixamoのアニメーションを適用する
Trilib2について
Unityは、Editorでは簡単にFbxをロードできますが、ゲームの実行中にFbxをロードする方法は提供されていません。
ゲームの実行中にFbxをロードする場合、Trilib2
という有料アセットを使用することで簡単に実現することができます。
公式サイト
アセットストア
Trilib2の使い方に関しては、以下のQiitaの記事が非常に参考になります。
ファイルパスを指定してFbxファイルを読み込む
AssetLoader.LoadModelFromFile
メソッドで指定したパスからモデルをロードします。
Materialまでロードが完了した後、OnMaterialsLoad
メソッドがコールバックで呼び出されます。
読み込んだモデルは、AssetLoaderContext.RootGameObject
から参照できます。
using TriLibCore;
public class MyFbxLoader : MonoBehaviour
{
public void Load(string loadPath)
{
var asetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions();
AssetLoader.LoadModelFromFile(loadPath, null, OnMaterialsLoad, null, null, null, assetLoaderOptions);
}
private void OnMaterialsLoad(AssetLoaderContext context)
{
var loadedGameObject = context.RootGameObject;
// goを色々処理
}
}
Humanoid対応のモデルのAvatarを読み込む
Humanoid対応のモデルを読み込む場合、AssetLoaderOptionsを適切に設定することで、自動的にAvatarを構成してくれるようになります。
-
assetLoaderOptions.AnimationType
をAnimationType.Humanoid
に設定 -
assetLoaderOptions.HumanoidAvatarMapper
にモデルと対応したHumanoidAvatarMapper
を指定
Mixamoからダウンロードしたモデルをロードする場合、MixamoAndBipedByNameHumanoidAvatarMapper
というマッパーがデフォルトで含まれているため、こちらを使用することができます。
using TriLibCore;
using TriLibCore.General;
using TriLibCore.Mappers;
// ~~ 中略 ~~
// MixamoAndBipedByNameHumanoidAvatarMapperを参照しておく
[SerializeField]
private HumanoidAvatarMapper avatarMapper;
private void Load(string loadPath)
{
var asetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions();
// AnimationTypeをHumanoidに設定
assetLoaderOptions.AnimationType = AnimationType.Humanoid;
// HumanoidAvatarMapperを設定
assetLoaderOptions.HumanoidAvatarMapper = avatarMapper;
AssetLoader.LoadModelFromFile(loadPath, null, OnMaterialsLoad, null, null, null, assetLoaderOptions);
}
private void OnMaterialsLoad(AssetLoaderContext context)
{
var loadedGameObject = context.RootGameObject;
// Animator経由でAvatarを取得
var animator = loadedGameObject.GetComponent<Animator>();
var avatar = animator.avatar;
}
Fbx内のアニメーションを読み込む
Trilib2は、残念ながら動的にMecanimのアニメーションをインポートすることはできません。
公式のKnown Issues/Limitations
のページにTriLib can't import Mecanim Animation Clips due to a Unity limitation.
と記載があり、Unityの制限によりMecanimアニメーションはインポートできないそうです。
そのため、アニメーションを再生する場合は、以下の設定を行い、レガシーアニメーションとしてロードする必要があります。
-
assetLoaderOptions.AnimationType
にAniamtionType.Legacy
を指定
using TriLibCore;
using TriLibCore.General;
using TriLibCore.Extensions;
// ~~ 中略 ~~
private void Load(string loadPath)
{
var asetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions();
// AnimationTypeにLegacyを設定
assetLoaderOptions.AnimationType = AnimationType.Legacy;
AssetLoader.LoadModelFromFile(loadPath, null, OnMaterialsLoad, null, null, null, assetLoaderOptions);
}
private void OnMaterialsLoad(AssetLoaderContext context)
{
var loadedGameObject = context.RootGameObject;
// Animation経由でレガシーアニメーションのクリップを取得
var animation = loadedGameObject.GetComponent<Animation>();
// GetAllAnimationClipsはTriLibCore.Extensionsに定義されている
// 全てのアニメーションクリップを取得する
var clips = animation.GetAllAnimationClips();
}
読み込んだアニメーションを(無理やり)他のHumanoidモデルに適用する
Trilib2で読み込んだアニメーションはレガシーのため、基本的に他のHumanoidモデルに適用することはできません。
ただ、動かすだけであれば、以下の方法で無理やり動かすことはできました。
- Humanoid対応のモデルをAvatar付きで読み込む
- Humanoid対応のモデルのAnimationを読み込む
- Avatar付きのモデル上でAnimationを再生する
- Avatar付きのモデルのHumanPoseを、アニメーションを適用したいモデルのHumanPoseにコピーする
HumanPose経由でポーズを複製することで、それぞれのHumanoidモデルに合わせた状態でモデルを動かすことができます。
元のモデルを動かしておく必要があるので、使えるケースは限られますが、何でもいいから動けばいい場合であれば、一応使えるかなと思います。
Avatar付きのモデル上でAnimationを再生する
AvatarGameObjectとAnimationGameObjectにそれぞれAvatarとAnimationが読み込まれている状態で、AvatarGameObjectにAnimationを複製します。
var animator = AvatarGameObject.GetComponent<Animator>();
// AnimatorはOFFにしておく
animator.enabled = false;
// Avatar側にAnimationを追加
var animation = AvatarGameObject.AddComponent<Animation>();
// 作成したAnimationにクリップを追加
foreach (var clip in clips)
{
// ループする場合
clip.wrapMode = WrapMode.Loop;
animation.AddClip(clip, clip.name);
}
// クリップを指定してアニメーションを再生
animation.clip = clips[0];
animation.Play();
Update内でHumanPoseを複製する
アニメーションを適用したいモデルに下記のスクリプトを適用し、srcAnimator
にアバターをロードしたモデルを格納します。
アバターをロードしたモデルでアニメーションを再生すると、このモデル上でも一緒にアニメーションが動作します。
public class HumanPoseCopier : MonoBehaviour
{
//
[SerializeField]
private Animator srcAnimator;
private Animator animator;
private HumanPoseHandler handler;
private HumanPoseHandler srcHandler;
private HumanPose humanPose;
private void Start()
{
animator = GetComponent<Animator>();
handler = new HumanPoseHandler(animator.avatar, transform);
srcHandler = new HumanPoseHandler(srcAnimator.avatar, srcAnimator.transform);
}
private void Update()
{
if (srcAnimator == null) return;
srcHandler.GetHumanPose(ref humanPose);
handler.SetHumanPose(ref humanPose);
}
}
後記
他のモデルへのアニメーションの適用は、とりあえず動く……という程度なので、もう少しマシな方法を模索したいところです。
Discussion