2023年5月7日日曜日

Unityでドアの開閉はAnimatorそれともiTween?


Mac Mini M2 の Unity で Sketchup のデータを復元したつづき。
以前、苦労して作成したドアの開閉が動作しないので修復する。
どうやって動かしていたのか、また忘れそうなので記録しておく。            



Animator


  1. 左右のドア PlaneL, PlaneR に Animator : PlaneL2, PlaneR2 を設定
  2. Animator はそれぞれ OpenDoor, CloseDoor, idleDoor の3つの Animation を制御
    Parameter : openDoor (Bool) を設定
  3. Animation には Transitions とその動作条件 Parameter : openDoor を設定
    Animation Window(cmd+6) で時間による動作を設定
  4. C# からの実行: "openDoor" の値を設定
 public Animator animatorBoschDoorRight;
 public Animator animatorBoschDoorLeft;

 public void animatorDoor(){
   SoundManager.Instance.PlaySE(23);  // ドアの開閉開始時の効果音
   animatorBoschDoorRight.SetBool("openDoor", !animatorBoschDoorRight.GetBool("openDoor"));
   animatorBoschDoorLeft.SetBool("openDoor", !animatorBoschDoorLeft.GetBool("openDoor"));
 }
 public void OnAnimationCompleted(string doorObj){
   SoundManager.Instance.PlaySE(24);  // ドアの開閉終了時の効果音
 }
ドアの開閉開始時の効果音は簡単だが、開閉終了時の実行はタイミングを測るのが難しい。
  1. Animation Windows でイベントを追加(OpenDoorR2, CloseDoorR)
  2. イベントの実行タイミングを指定
  3. 実行する Function を設定
  4. このとき Object はイベントを追加した Animation を含むものを指定しなければならないので注意。( OpenDoorR2 でも PlaneR2 でもOK)

    Function が設定済みの Object があるからといって、Animation に関係ないものを指定すると「AnimationEvent 'OnAnimationCompleted' has no receiver!のエラー」になる。


iTween

そもそも「ヘントの祭壇画」の開くのをやりたくてドアの開閉を始めたのだった。
iTween で実装したが、Cluster ではスクリプトが使えないため、Animator を学習しながら動かした。これが上手くいたので、絵だけ差し替えてヒエロムニス・ボスの「快楽の園」の扉を動かしたのだった。 


画像を回転させながら、横移動していたが、画像の横幅が2倍のObject を作成して、これの片側に寄せて画像を置けば回転だけで済むことにいまさら気がついた。


上下動を加えたが、基本は左右のドアを iTween.RateTo するだけ。

public void doorOpenClose(){
Debug.Log("L31 doorControl.cs right rot: " + doorRight.transform.localEulerAngles.z);
SoundManager.Instance.PlaySE(23); // ドアの開閉動時のギーーという音
float z = 180f;
float t = 5f;
float zz = 10f; // ドアの上下動の量
if(doorRight.transform.localEulerAngles.z == 180f){ // 開く
iTween.RotateTo(doorLeft, iTween.Hash("time", t, "z", -z,
"oncomplete", "onDoorRotateComplete", "oncompletetarget", this.gameObject));
iTween.MoveBy (doorLeft, iTween.Hash("time", t, "z", -zz));
iTween.RotateTo(doorRight, iTween.Hash("time", t, "z", z));
iTween.MoveBy (doorRight, iTween.Hash("time", t, "z", -zz));
}else if(doorRight.transform.localEulerAngles.z < 1f ){ // 閉じる
iTween.RotateTo(doorLeft, iTween.Hash("time", t, "z", z,"oncomplete",
"onDoorRotateComplete", "oncompletetarget", this.gameObject));
iTween.MoveBy (doorLeft, iTween.Hash("time", t, "z", -zz));
iTween.RotateTo(doorRight, iTween.Hash("time", t, "z", -z));
iTween.MoveBy (doorRight, iTween.Hash("time", t, "z", -zz));
}
}

void onDoorRotateComplete(){
SoundManager.Instance.PlaySE(24); // ドアが開閉終了時のバッタンという音
float t = 0.75f;
float zz = 10f;
iTween.MoveBy (doorLeft, iTween.Hash("time", t, "z", zz));
iTween.MoveBy (doorRight, iTween.Hash("time", t, "z", zz));
}











参考
【Unity】アニメーション終了時にメソッドを呼び出す
https://takap-tech.com/entry/2021/04/13/013635


Swift UI チュートリアル Loading watchOS が終わらない?

Loading watchOS が終わらない? ディスク容量の残量が少ないので不要なシュミレーターを削除したとこころ watchOSのものが全部なくなってしまっていた。 WatchOS を削除して再度インストールしても復活せず。 Create a new simulator で ...