Unityに関連する記事です

 ステージを生成した際に、カメラの位置が上手く合わずに、追従する位置が上下してしまうことがあります。

 その場合にはまず、AR Session Origin ゲームオブジェクトの位置を調整して、再度、実機にて確認を行ってみてください。
AR Camera ゲームオブジェクトはこの AR Session Origin ゲームオブジェクトの子オブジェクトであるため、
親である AR Session Origin ゲームオブジェクトの座標が変われば、カメラの位置が変更になるためです。

 それでもうまくいかない場合には、この手順を利用してカメラの位置を調整してみてください。


発展11 ーカメラの位置調整ー

16.AR カメラの位置を調整する



 新しい学習内容は、以下の通りです。

 ・タプル型



16.AR カメラの位置を調整する

1.設計


 以前に学習したように、現在は平面感知に合わせて Stage ゲームオブジェクトを生成するため、Stage ゲームオブジェクトは最初からヒエラルキーには存在していない状態になっています。
そのため、ペンギンのゲームオブジェクトも、ヒエラルキーには最初から存在していません

 また、AR 用のカメラも平面感知に利用はしていますが、生成された Stage 内には存在していないため、スクリプトを利用して
カメラの追従対象であるペンギンを、Stage ゲームオブジェクトの生成後に設定を行っています。ARGameManager クラス内で実行している CameraController クラスの SetPlayer メソッドです。

 ただし、こちらの設定をおこなっても、AR カメラが通常のゲームのようにペンギンを正しい位置で追従することが難しいケースがあります。

 そのような場合の解決策の1つとして、Stage ゲームオブジェクト内に、新しくゲームオブジェクトを配置し、
その位置を AR カメラの設定位置として利用する方法があります。

 今回はこの方法を使って、AR カメラの位置を補正し、今までと同じようなカメラの位置でペンギンを追従させるように修正を行います。

 この方法だけが解決方法ではありませんので、自分でも、どうすればうまくカメラがペンギンを追従してくれるのかを考えてみてください。


2.Stage プレファブ・ゲームオブジェクトに CameraOffsetObj ゲームオブジェクトを追加する


 Prefabs フォルダ内にある Stage ゲームオブジェクトを選択してダブルクリックするか、インスペクターで Open を選択してプレファブ編集モードにします。

 Stage ゲームオブジェクトの上で右クリックをしてメニューを開き、Create Empty を選択して新しいゲームオブジェクトを1つ追加します。
名前は CameraOffsetObj に変更します。

 このゲームオブジェクトの位置にカメラが来るように制御を行うようにしますので、
ペンギンのゲームオブジェクトの後方に適宜な位置を決めて配置してください。

 今回はインスペクター画像も用意しましたが、参考値です。ご自分のプロジェクトの内容で決めてください。


Stage プレファブ ゲームオブジェクトのヒエラルキー



CameraOffsetObj インスペクター画像(値は参考値です)



Scene ビュー画像



Scene ビュー画像



Scene ビュー画像



 以上で完成です。


3.Stage スクリプトを修正する


 Stage プレファブ内に追加した CameraOffsetObj の情報をスクリプトで管理を行うようにし、
ゲーム内でステージを生成した際に、他のスクリプト対してステージの情報として提供できるように、専用のメソッドを作成しておきます。

 今回は学習のため、2つのメソッドを用意しました。どちらを利用しても同じ処理を実装できます。
このうちの1つは、メソッドの戻り値にタプル型の情報を設定しています。


Stage.cs

<= クリックすると開きます。



4.<タプル型>


 タプル(tuple)型は C# の持つ機能の1つです。複数のオブジェクトのデータをひとまとめにして管理することができます。
また、戻り値として利用する場合には、通常の戻り値に指定できる型は1つだけですが、タプル型を利用することにより
複数のオブジェクトのデータを同じようにまとめて戻す機能を実装することが出来ます。

 タプル型の宣言の書式は複数ありますので、それぞれ紹介します。今回は△僚饉阿納汰しています。
 
<記述例 
 // 宣言と代入
  (int, bool) damage = (0, false);

 // 宣言
 (Sprite, MoveTimeScale) nextTimeScaleValue;

 // メソッドの戻り値として宣言
 private (int, bool) GetTuple()

 上記の例の場合、damage 変数や nextTimeScaleValue 変数には、2つの型の情報が含まれていることになります。
より丁寧に書く場合には、今回のように、通常の変数のように型に対して宣言も可能です。
出来るだけタプル内のオブジェクトの型にも変数の宣言をつけて利用することをおすすめします。

<記述例◆
 // 宣言と代入
  (int value, bool isWeakness) = (0, false);

 // 宣言
 (Sprite nextSprite, MoveTimeScale nextMoveTimeScaleType);

  // タプル型の場合、メソッドの戻り値にも変数を宣言できる
 (GameObject player, GameObject cameraObj)

<記述例>
  (int value, bool isWeakness) damage = (0, false);

 (Sprite nextSprite, MoveTimeScale nextMoveTimeScaleType) nextTimeScaleValue;



 タプル型の情報を扱う場合、タプル内のオブジェクトに対して変数の宣言を行っているか、いないかによって、参照する場合の記述が変わります

 記述例,里茲Δ法▲織廛詁發之燭里澆靴宣言していない場合には、タプル内の情報は Item1、Item2 というように自動的に採番されます
その場合は、「タプルの変数名.タプル内のオブジェクトの宣言順のItemの番号」の書式で記述できます。

<記述例,両豺腓了仮販磧
  Hoge(damage.Item1);  // int 型の引数を参照して渡しています

  Hpge(nextTimeScaleValue.Item2)

 変数の宣言を行っている場合には、通常の変数のように「タプルの変数名.タプル内のオブジェクトの変数名」の書式で記述できます。
そのため、タプルの変数名から、値の推測が可能です。

<記述例△両豺腓了仮販磧
  Hoge(damage.value);  // int 型の引数を参照して渡しています

  Hoge(nextTimeScaleValue.nextSprite);   // Sprite 型の引数を参照して渡しています

 Item1、Item2 でも処理は動きますが、プログラムは処理を見て、誰でもすぐに内容が理解できる設計が理想です。
なるべく変数名をつけてタプルの宣言をした方がいいというのは、このようにプログラムの可読性に関わるためです。
damage.Item1 よりも、damage.value の方が、変数名だけ見てもどのような値が代入されているか判断がつきやすいので、処理を読み解きやすいということです。



 今回の実装では、メソッドの戻り値としてタプル型を利用し、2つの型の情報を戻す処理を実装しています。
この値を受け取る側では、同じ内容のタプル型を準備しておくことにより、戻り値の情報を2つまとめて受け取れるようにしています。

Stage.cs
/// <summary>
    /// プレイヤーとカメラのオフセット位置の両方の情報を取得
    /// </summary>
    /// <returns></returns>
    public (GameObject player, GameObject cameraObj) GetStageInfo() {
        return (playerObj, cameraOffsetObj);
    }

 以降の手順で、実際にタプル型の戻り値を利用する処理を書きますが、ここで実装している部分を先に記述しておきます。

ARGameManager.cs
<戻り値のあるメソッドを実行する側>
 // タプル型の stageInfo 変数を宣言し、Stage クラスの GetStageInfo メソッドの戻り値として、同じタプル型の情報を取得して代入
 (GameObject player, GameObject cameraOffsetObj) stageInfo = obj.GetComponent<Stage>().GetStageInfo();

 // ペンギンの情報とカメラの位置情報をカメラに設定
  cameraController.SetStageInfo(stageInfo.player, stageInfo.cameraOffsetObj);

 Stage クラスの GetStageInfo() メソッドを実行し、それぞれ異なる型の情報を1つにまとめてあるタプル型の戻りの中から取得しています。
今回は Item1 と Item2 の両方の型が GameObject 型になります。



 なお、タプルも入れ子を作ることができます。通常であれば2つの型ですが、この機能を使えば複数の情報を持たせることが出来ます。

<入れ子になっているタプル>
  (int x, (string a, int b) y) tuple = (0, ("String", 100));


参考サイト
MicroSoft C#リファレンス
タプル型
https://docs.microsoft.com/ja-jp/dotnet/csharp/lan...
未確認飛行 C 様
タプル
https://ufcpp.net/study/csharp/datatype/tuples/


5.Prefabs フォルダ内の Stage ゲームオブジェクトの設定を行う


 今回はプレファブになっている Stage ゲームオブジェクトのみ、Stage スクリプトの設定を行います。

 CameraOffsetObj 変数が追加されていますので、Stage プレファブ内にある同名のゲームオブジェクトをドラッグアンドドロップしてアサインしてください。


プレファブになっている Stage ゲームオブジェクトのインスペクター画像



 以上で設定は完了です。


6.CameraController スクリプトを修正する


 Update メソッドの処理の一部を修正し、スクリプトがアタッチしているゲームオブジェクト自体を制御するように変更します。
この修正を行っても、通常のゲームには影響はありません。

 逆に考えると、AR 開発の場合には、常に、AR で起動した場合と、Unity エディターで起動した場合の、
双方の挙動を意識して処理を作成したり修正を行っていく必要があります。
この部分をしっかりと対応できていないと、どちらかで実行した際に不具合が発生する可能性が出てくるためです。

 新しい SetStageInfo メソッドを作成して、プレイヤーとカメラの位置情報の、両方を情報を外部のクラスから受け取れるようにしておきます。
そして cameraPos 変数に、外部から提供を受けたカメラの位置情報を設定することで、
AR カメラの位置を、ステージ内に新しく設定した CameraOffsetObj ゲームオブジェクトの座標にセットします。


CameraController.cs

 <= クリックすると開きます。


 スクリプトを修正したらセーブします。


7.ARGameManager スクリプトを修正する


 最後に ARGameManager スクリプトを修正し、ステージ生成後の処理を変更します。

 いままでは CameraController スクリプトの SetPlayer メソッドを実行して、カメラにプレイヤーの情報のみを提供していましたが、
今回は、先ほどの CameraController スクリプトの修正手順で作成しておいた SetStageInfo メソッドを実行するように変更して、
プレイヤーの情報と合わせて、ステージ内にあるカメラの設定位置情報も引数として渡すことで、
AR カメラの位置をステージ内に設定してある CameraOffsetPos ゲームオブジェクトの位置に設定します。

 今回は2つの実装例を提示してあります。どちらの方法で実装しても問題ありません。
実装しない方の内容については、処理の流れを理解しておいてください。
 

ARGameManager.cs

<= クリックすると開きます。



8.AR Session Origin ゲームオブジェクトの設定を変更する


 ヒエラルキーにある AR Session Origin ゲームオブジェクトを選択して、インスペクターより CameraController スクリプトの設定を変更します。

 ''CameraPos 変数を None に設定してください。
こちらも Pengiun ゲームオブジェクトと同様に AR 内でステージを生成後、ステージ内にあるカメラのオフセット位置のゲームオブジェクトの情報を
スクリプトを利用して動的に取得するように変更したためです。

 そのため、現在は None ですが、ステージが生成されたタイミングで CameraPos 変数に、Stage プレファブ内の CameraOffsetObj ゲームオブジェクトの情報が代入されます。


AR Session Origin ゲームオブジェクト インスペクター画像



 以上で設定は完了です。


9.ゲームを実行して動作を確認する


 すべての手順が完成しました。複数のスクリプトを経由する形であるので、処理の流れの把握が難しいため、しっかりと読み解いてください。
ノートなどにメソッドの繋がりなどを書きだして可視化してみると、イメージがつかみやすくなります。

 実機用にビルドを行い、ゲームを実行してステージを生成します。今までとカメラの位置が変更になっているかを確認してください。
位置がまだ上手く合わない場合には、Stage プレファブ内にある CameraOffsetPos ゲームオブジェクトの位置を調整し、何回か、実機にて確認をしながら調整を繰り返してください。



 以上でこの手順は終了です。

 => 次は 学習の振り返り です。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3Dレールガンシューティング(応用編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます