rukhankaを利用する際のメモ

## rukhankaを利用する際の注意

UNITY ECSでアニメーションを動作したいとき、rukhankaは大変便利ですが、マニュアルの内容外で困ったときは、現状Discordで確認する必要がありそうです。（rukhankaはUnityアセットストアで購入できます）
※HybridsだとEntityとゲームオブジェクトを重ねて、結局ゲームオブジェクトベースでアニメーションするので、ECSのメリットが減ってしまいますが、rukhankaを使えば直接Shaderとメッシュをコントロールするので、Entityのメリットを享受したまま非常に軽量なアニメーションができます。

そこで、利用する上で気が付いた注意事項のみ簡単に備忘録を残していきます。

### Scriptでアニメーションする場合
サンプルScine21番（21. Scripted Controller）を参考にして、作っていく必要があります。

#### Rig Definition Authoringのアタッチ
-Rig Config　SourceはUser Definedに設定
-Rig ConfigurationのAvatarは、Import Settings（.fbxファイル）の設定次第
    ・fbxファイルにAvaterが紐づく場合、None（Avatar）で良さそう
    ・紐づいていない場合、自分でAbatarを設定する
-AnimationAssetSetAuthoringをアタッチ。Clipsにはアニメーションファイルを設定。複数設定すれば、ScriptedAnimatorSystem内からScriptedAnimatorSampleUsedAnimationsComponent.clips[0]とか、clips[1]のように設定し、Excute内でScriptedAnimator.PlayAnimationを実行すれば、任意のアニメーションを好きなタイミングで実行できる。

#### .fbxファイルの設定
まずどの.fbxファイルを設定するかですが、AvatarをRig Definition Authoringの中で設定しているかどうかで、対応が異なります。
Avatarがfbxファイルに含まれる場合、例えばHierarchyで以下図のような構成になっているとすれば、多くの場合Body05に紐づくMeshが所属するfbxファイルにアクセスし、Model、Rig、Animation、Materialsの各設定を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715582/40c1a0cf-9737-c110-e546-a9e8bfa48f11.png)
Rigの設定は、経験的にはモデルによってかなり変わるので、何とも言えません。
21. Scripted Controllerのサンプルプロジェクトを参考に色々いじってみるのが手っ取り早いと思います。

Avatarがfbxファイルに含まれず、個別に設定している場合は、Avatarが所属するfbxファイルと、Meshが所属するfbxファイルをどちらも設定する必要がありそうです（経験的に）

ともあれ、色々頑張って設定すれば、以下動画のようにEntityのアニメーションができます。

https://x.com/khbowling/status/1835159707922972903



Systemの部分のみですが、以下コードです。
```
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using Hash128 = Unity.Entities.Hash128;
using TMG.UITutorial;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Rukhanka.Samples
{
[WorldSystemFilter(WorldSystemFilterFlags.LocalSimulation | WorldSystemFilterFlags.ClientSimulation)]
[UpdateInGroup(typeof(RukhankaAnimationSystemGroup))]
[UpdateBefore(typeof(AnimationProcessSystem))]
	public partial class ScriptedAnimatorSystem: SystemBase
	{
		private BeginSimulationEntityCommandBufferSystem _ecbSystem;
		protected override void OnCreate()
		{
			// BeginSimulationEntityCommandBufferSystem を取得して保持
			_ecbSystem = World.GetOrCreateSystemManaged<BeginSimulationEntityCommandBufferSystem>();
        }


		[BurstCompile]
		partial struct ScriptedAnimatorSampleJob: IJobEntity
		{
			[ReadOnly]
			public NativeHashMap<Hash128, BlobAssetReference<AnimationClipBlob>> animDB;
			public float weight;
			//public float animTime;
			public float currentTime;
			public int2 animationIndices;
			public bool blending;
			public EntityCommandBuffer.ParallelWriter ecb;
		
			void Execute(Entity entity, ref DynamicBuffer<AnimationToProcessComponent> atps, ScriptedAnimatorSampleUsedAnimationsComponent c, [ChunkIndexInQuery] int sortKey)
			{

				var animTime = currentTime % 2;
				ScriptedAnimator.ResetAnimationState(ref atps);
				animDB.TryGetValue(c.clips[0], out var clip0Blob);
				animDB.TryGetValue(c.clips[0], out var clip1Blob);
				if (blending)
					ScriptedAnimator.BlendTwoAnimations(ref atps, clip0Blob, clip1Blob, animTime, 1);
				else
					ScriptedAnimator.PlayAnimation(ref atps, clip0Blob, animTime, 1);
					
			}
		}
	
	//=================================================================================================================//

		protected override void OnUpdate()
		{
			//var cfg = ScriptedAnimatorSampleConf.Instance;
			//if (cfg == null)
			//	return;
		
			if (!SystemAPI.TryGetSingleton<BlobDatabaseSingleton>(out var blobDB))
			{
				
                return;
            }

            var job = new ScriptedAnimatorSampleJob()
			{
				animDB = blobDB.animations,
				//weight = cfg.weight.value,
				//animTime = cfg.animationTime,
				currentTime = (float)SystemAPI.Time.ElapsedTime,
				//blending = cfg.doBlending,
				//animationIndices = cfg.animationIndices,
                ecb = _ecbSystem.CreateCommandBuffer().AsParallelWriter(),
            };
		
			job.ScheduleParallel();
		}
	}
}
```


### 納得できないエラーが発生

IguanaAttackSystem.csのファイルに、アニメーションを含む攻撃スクリプトを書いたのだが、

```
public partial struct IguanaAttackSystem : ISystem
```
スクリプト全体は問題なく動作するが、にするとアニメーションだけがGamePlay時に反映されない。
```
public partial struct IguanaAttackAnimationSystem : ISystem
```
に変えると、問題なく動く。
どちらもでエラーは出ないし、IguanaAttackSystemは他のどこにも使っていないので、納得がいかない...