MRが楽しい

MRやVRについて学習したことを書き残す

次元の狭間に落ちたキャラクタをリカバリする

おいかけっこアプリの追加機能枠です。

今回はhololensのSpatialMapping上にキャラクタを設置するときの問題を解決します。
環境マッピングが完了する前に、オブジェクトに重力属性を与えると、床がないため、キャラクタが奈落の底に落ちていきます。
2ヶ月ほど前の記事で発生した問題ですね。
bluebirdofoz.hatenablog.com

このときは、SpatialMappingのポリゴンがある程度生成されるまで待つという対処を取りました。
しかし、hololensの死角により、ポリゴンの隙間はやはり発生するため、キャラクタが奈落の底に落ちる自体は発生します。
そのたび、アプリを再起動するのは非常に面倒です。

という訳で、キャラクタのマネージャクラスにリカバリ処理を実装しました。
キャラクタとカメラの位置関係を定期的にチェックし、キャラクタがカメラから5m以下の位置になると、落下したと判断します。
・MainCharactor.cs

  /// <summary>
  /// 定期実行関数(Update)
  /// </summary>
  private void Update()
  {
    if (p_EMainCharactorMode != EMainCharactorMode.Standby)
    {
      // 待機状態でないとき、キャラクタのリカバリ監視を行う
      Vector3 cameraPositon = Camera.main.transform.position;
      Vector3 rootPostion = this.gameObject.transform.root.position;
      // キャラクタのY座標がカメラと比較して5m以下の位置ならば落下と判断してリカバリを行う
      float cameraPosY = cameraPositon.y;
      float rootPosY = rootPostion.y;
      if ((cameraPosY - rootPosY) > 5.0f)
      {
        // キャラクタのリスタート処理
        RestartMainCharactor();
      }
    }
  }
(略)
  /// <summary>
  /// キャラクタのリスタート処理
  /// </summary>
  private void RestartMainCharactor()
  {
    // コントロールロジックの停止
    ExecuteControlLogicMode(EControlLogicMode.ManualLogic);

    // キャラクタ状態を待機状態に変更
    p_EMainCharactorMode = EMainCharactorMode.Standby;

    // 加速度をゼロにする
    p_Rigidbody.velocity = Vector3.zero;

    // 重力の無効化
    p_Rigidbody.useGravity = false;

    // 開始効果処理のロールバック
    p_EffectManager.ExecuteStartEffect(false);

     // リスタートアクションの実行
    p_ModelManager.NotificationModelAction(EModelAction.Restart);

    // 座標の初期化
    this.gameObject.transform.root.position = new Vector3(0.0f, -1.0f, 3.0f);
    this.gameObject.transform.root.rotation = Quaternion.Euler(0.0f, 180.0f, 0.0f);
  }

このとき、キャラクタのリカバリ処理で以下の加速度ゼロの処理を行うことがミソです。
・p_Rigidbody.velocity = Vector3.zero;
これを行わないと、重力を切っても落下が止まらず、戻ると同時に再落下していきます。私は見事に引っ掛かりました。

アプリをテストしてみます。
f:id:bluebirdofoz:20170704030014j:plain
ユニティちゃんが次元の底へとダイブすると……。
f:id:bluebirdofoz:20170704030022j:plain
初期位置に復帰しました。
これでアプリの再起動を行ずともゲームの再開が行えるようになりました。