#やりたかったこと
動的に読み込んだVRMに対して、カメラに顔の向きと視線を追従させたい。
視線追従はVRMLookAtHeadを利用し、顔向きの追従はLookAtIKを利用。
(両方ともLookAtIKで行うこともできそうだったが、視線追従は目の可動域が考慮されるVRMLookAtHeadを利用したかった)
また、アニメーションを上書きして追従させたかったので、両方ともLateUpdateのタイミングで実行する必要がある。
#ハマったポイント
実行順が、視線の追従→顔向きの追従(それに伴い視線も移動)となり、視線があさっての方向に向いてしまう。
tsubaki_t1氏のブログによると、コンポーネントやオブジェクトを動的に追加した場合は、生成順になる
とのことらしいので、以下のようなLateUpdateで視線追従の関数を呼ぶだけの関数を作り、
[RequireComponent(typeof(VRMLookAtHead))]
public class DelayUpdateVRMLookAtHead : MonoBehaviour
{
private VRMLookAtHead vrmLookAtHead;
// Start is called before the first frame update
void Start()
{
vrmLookAtHead = GetComponent<VRMLookAtHead>();
vrmLookAtHead.UpdateType = UpdateType.None; // 視線追従の関数を自動で呼ばれないようにしておく
}
// Update is called once per frame
void LateUpdate()
{
vrmLookAtHead.LookWorldPosition();
}
}
LookAtIKの生成後にAddComponentしても実行順は変わらない。
念の為[DefaultExecutionOrder(1)]とかしてもダメ。
#解決方法
LookAtIKの機能として、姿勢変更後に実行するイベントの登録ができました…。
var lookAtIk = model.AddComponent<LookAtIK>();
var vrmLookAtHead = GetComponent<VRMLookAtHead>();
vrmLookAtHead.UpdateType = UpdateType.None; // 視線追従の関数を自動で呼ばれないようにしておく
lookAtIk.solver.OnPostUpdate += vrmLookAtHead.LookWorldPosition;
#更新履歴
2019/12/12
・解決方法において端折っていたVRMLookAtHeadの取得、設定処理を明記
2019/9/8
・サイトの管理者を明記
・VRMLookAtHead自身でのアップデートを処理を切る必要があることを明記