Unityに関連する記事です

ー高度計用のアイコンの実装ー


 この手順では、UIとして高度計用のゲームオブジェクトの作成と制御を行います。


Sceneビュー画像



Gameビュー画像



 ・高度計用のアイコンのゲームオブジェクトの作成と制御

<実装動画 キャラの落下に合わせて高度計用のアイコンが移動する>
https://gyazo.com/49ebecb4bd2ba1887228c83502f93cee


<実装動画 着水するとアイコンの移動も止まる>
https://gyazo.com/fd2ab04a42d05f54ad3a31f0749d29ec



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

 ・DOValue メソッド


1.設計


 今回は、UIの部品として、高度を表すアイコンを作成し、それをキャラの落下位置と同期させて、アイコンを上から下方向へ移動させる制御を行います。

 この制御を Slider コンポーネントを活用して実装します。

 Slider コンポーネントには Value という値があり、この値によって、Slider が移動するようになっています。
Value の最小値 0 をゴール地点最大値 1 をキャラのスタート地点とし、現在値を現在のキャラの位置とすることによって
現在のキャラの位置とスタート地点とを割合を計算することで、高度とアイコンの移動とを同期させることが出来ます。


完成後のヒエラルキー画像


 
 まずは UI の部品になりますので、Canvas ゲームオブジェクト内に Slider のゲームオブジェクトを作成します。
その後、その Slider の値を操作して制御するための処理を GameManager スクリプトに追加します。


2.Canvas ゲームオブジェクトの子オブジェクトとして Altimeters ゲームオブジェクトを作成する


 最初にフォルダ用のゲームオブジェクトを作成します。
すでに Canvas ゲームオブジェクトがありますので、こちらをそのまま利用しましょう。

 Canvas ゲームオブジェクトの上で右クリックをしてメニューを開き、Create Empty を選択します。
新しく空のゲームオブジェクトが作成されますので、名前を Altimeters に変更します。
Altimeters ゲームオブジェクトは、高度計の表示に関するゲームオブジェクト群をまとめておくための、フォルダ役のゲームオブジェクトです。


ヒエラルキー画像




 Altimeters ゲームオブジェクトを選択して、RectTransform コンポーネントがアタッチされているか確認します。
Canvas ゲームオブジェクトに含まれるオブジェクトは Transform コンポーネントではなく、RectTransform コンポーネントによって位置情報を管理しています。
もしも通常の Transform コンポーネントがアタッチされている場合には、再度作り直してください。


 Altimeters ゲームオブジェクトの位置とアンカーを変更します。
RectTransform コンポーネント内にある Anchor(アンカー)をクリックして、Alt キーを押しながら、Middle Right の位置をクリックしてください
Altimeters ゲームオブジェクトが画面の右側中央の位置に移動するとともに、アンカーの位置も同じ位置に設定されます。


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



Altimeters ゲームオブジェクト Sceneビュー画像



 以上で Altimeters ゲームオブジェクトの設定は完成です。
続いて、Slider ゲームオブジェクトを作成して設定を行います。


3.Altimeters ゲームオブジェクトの子オブジェクトとして、Slider ゲームオブジェクトを作成する


 Altimeters ゲームオブジェクトの上で右クリックをしてメニューを開き、UI => Slider を選択します。
Slider コンポーネントがアタッチされたゲームオブジェクトと、それに関連するゲームオブジェクト群が新しく作成されます。
名前はそのままでもいいですし、SliderAltimeter のように変更していただいても構いません。


Slider ゲームオブジェクトと関連するゲームオブジェクト群 ヒエラルキー画像



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



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



 この Slider コンポーネントの管理している Value の値を操作することで Slider(ゲージ)が動きます。
ここをスクリプトから変更するように、あとで紐づけを行います。

 Valueの値の初期値は 0 - 1 の間です。0 のときはゲージは空の状態、1 が満タンの状態です。
実際に Value のゲージを移動させてみて、どのように動くかを確認しておいてください。


Slider ゲームオブジェクト Sceneビュー画像



 続いて、Slider ゲームオブジェクト群の設定を順番に行っていきます。


4.Slider ゲームオブジェクトと子オブジェクトの設定をそれぞれ行う


 ヒエラルキーでも確認していただいたように、Slider ゲームオブジェクトには始めから複数のゲームオブジェクトが子、孫として不随しています。
順番に1つずつ設定を確認していきます。


 
Slider ゲームオブジェクト ヒエラルキー画像



1.Slider ゲームオブジェクトの設定

 Slider ゲームオブジェクトは、RectTransform コンポーネントのみ変更を行います。

 最初に Rotation の Z 軸の値を 90 に変更してください。これで水平方向であったゲームオブジェクトが垂直方向に向きが変わります


<Rotation Z = 0 の場合>



<Rotation Z = 90 の場合>



 その後、Width と Height の値を操作して、ゲームオブジェクトの大きさを変更します。
下記のインスペクター画像や、ゲーム画面を見ながら適宜な大きさに調整してください。
このゲームオブジェクトの大きさが、キャラのアイコンが移動する範囲になります。
 
 調整を行いながら、ゲームオブジェクトの位置も設定します。
ボタンよりも内側に、Handle のゲームオブジェクトが高度の数字を表示している部分の近くになるように設置します。


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



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



Slider ゲームオブジェクト Sceneビュー画像



 以上で設定は終了です。 Value の値を操作して、可動範囲を確認しておきます。この範囲がキャラが落下する際に同期する範囲になります。


2.Background ゲームオブジェクトの設定

 Backgroundゲームオブジェクトには、RectTransformコンポーネント、Canvas Renderer コンポーネント、Imageコンポーネントがアタッチされています。

 RectTransformコンポーネントは変更箇所はありません。

 Canvas Renderer コンポーネントの Cull Transparent Mesh のスイッチにチェックを入れてオンにします

 Imageコンポーネントは、Raycast Target のチェックを外してください
また Color の Alpha の値を 0 に変更して、画像を透明にしてください
そのため、Source Image の設定は変更の必要ありません。


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



Background ゲームオブジェクト Sceneビュー画像



 以上で設定は完了です。


3.FillArea ゲームオブジェクトの設定

 Fill Areaゲームオブジェクトのインスペクターを確認します。

 RectTransform コンポーネントのみになっていますので、left と Right の値をどちらも 0 に設定してください
この値が 0 になっていないとゲージが完全に隠れません


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



FillArea ゲームオブジェクト Sceneビュー画像



 以上で設定は完了です。


4.Fill ゲームオブジェクトの設定

 Fillゲームオブジェクトのインスペクターを確認します。
RectTransform コンポーネント、Canvas Renderer コンポーネント、Image コンポーネントがアタッチされています。

 RectTransform コンポーネントの Left と Right の値を 0 に設定してください。これは Fill Area ゲームオブジェクトと同じ理由です。

 Canvas Renderer コンポーネントの Cull Transparent Mesh のスイッチにチェックを入れてオンにします

 Imageコンポーネントは、Raycast Target のチェックを外してください
また Color の Alpha の値を 0 に変更して、画像を透明にしてください
そのため、Source Image の設定は変更の必要ありません。


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



Fill ゲームオブジェクト Sceneビュー画像



 以上で設定は完了です。


5.Handle Slide Area ゲームオブジェクトの設定

 Handle Slide Area ゲームオブジェクトのインスペクターを確認します。

 RectTransform コンポーネントのみになっていますので、left と Right の値をどちらも 0 に設定してください
この値が 0 になっていないとゲージが完全に隠れません


Handle Slide Area ゲームオブジェクト インスペクター画像



Handle Slide Area ゲームオブジェクト Sceneビュー画像




6.Handle ゲームオブジェクトの設定

 Handle ゲームオブジェクトのインスペクターを確認します。
RectTransform コンポーネント、Canvas Renderer コンポーネント、Image コンポーネントがアタッチされています。

 RectTransform コンポーネントの Width の値を 100 に設定してください
この値がアイコンの大きさになりますので、適宜調整をおこなってください。

 Imageコンポーネントは、Raycast Target のチェックを外してください

 また Source Image の画像には、ボタンにも使用しているペンギンのアイコン画像を設定してください。


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



Handle ゲームオブジェクト Sceneビュー画像




 これで Slider に関連するすべての設定が完成しました。

 最後に、Slider ゲームオブジェクトの Slider コンポーネント の Value の値を 1 に変更してください


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



Slider ゲームオブジェクト Sceneビュー画像



完成したGameビュー画像



5.GameManager スクリプトの修正を行い、高度表示用のキャラのアイコンとキャラの位置とを同期させる


 新しいメソッドの追加はありませんが、Start メソッドと Update メソッドに制御処理を追加します。
なぜその制御処理が必要なのかを、読み解きながら処理を実装してみてください。


GameManager.cs(自分で作成しているスクリプトがある場合には、そのスクリプトを修正する)

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



 スクリプトの修正が終了したら、GameManager ゲームオブジェクトのインスペクターより、GameManager スクリプトを確認してください。
新しく宣言して追加した変数群が表示されていれば問題ありません。


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



6.<DOValue メソッド>


 DOValue メソッドは DOTween の扱えるメソッドの1つです。
Slider コンポーネントに対して使用することが出来るもので、その名前の通り、Slider コンポーネントの持つ Value の値の補間処理を行ってくれます。

 第1引数には最終的な Value の値を入れます。この値に対して、第2引数の時間をかけて値を変更します。
そのため、今回の実装では、Value の計算結果の値になるまでに 0.1 秒かけて Value の値を変更しています。

 // 高度計用のキャラのアイコンの位置を更新
 sliderAltimeter.DOValue(distance / startPos, 0.1f);

 第1引数については計算結果が 0 - 1.0f になりますので、そちらを Value の値とすることにより、徐々に Value の値を減少させることが出来ています。


7.GameManager ゲームオブジェクトの設定を行う


 ヒエラルキーにある Slider ゲームオブジェクトをドラッグアンドドロップして sliderAltimeter 変数にアサインしてください。
自動的に Slider コンポーネントが登録されます。


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



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


 すべての手順が終了しましたので、ゲームを実行して、キャラの落下している位置情報と、高度計用のアイコンの位置が同期するかを確認します。
また、着水した際にはちょうど高度数の表示の上で停止したままになるかも確認します。

 DOValue メソッドの処理によって、Slider コンポーネントの Value の値が制御されています。
どの処理が、どのコンポーネントを操作しているのかの理解を深めるため、ゲームを実行した際には、処理されているコンポーネントを毎回ヒエラルキーで確認をしてください


<実装動画 キャラの落下に合わせて高度計用のアイコンが移動する>
https://gyazo.com/6d049286b2ea4d59cfd2f7d897696b51


<実装動画 着水すると止まる>
https://gyazo.com/fd2ab04a42d05f54ad3a31f0749d29ec


 もしも実行時にエラーが発生する場合には、次の手順を参考にしてください。


9.ゲーム実行時に Null Reference Exception エラーが発生する場合の対処方法


 ゲーム実行時に Null Reference Exception エラーが発生し、PlayerController スクリプト内の StopMove メソッド内の処理が原因でゲームが停止してしまう場合があります。
処理が止まってしまうのは、StopMove メソッドにある rb 変数を利用した処理を行うときに、rb 変数の値が null(空) であるためです。

 ですが、rb 変数は、PlayerController スクリプトの Start メソッドにおいて GetComponent メソッドにより代入処理が行われているはずです。
何故このようなエラーが発生するのでしょうか。



 これは、GameManager スクリプト内の Start メソッドと、PlayerController スクリプト内の Start メソッドの実行される順番が原因です。
 
 Unity では複数の Start メソッドが実行される場合、どのスクリプトの Start メソッドから実行されるかの保証はなく、その都度実行される順番が変わる可能性があります
PlayerController スクリプト内の Start メソッドの処理が実行されてからでないと、rb 変数が null のままになっているため、
先に GameManager スクリプト内の Start メソッドの処理を行ったときには、上記のエラーが発生してしまいます。

 そのため、今回のように、Start メソッドの処理の順番によってエラーが発生するような恐れがある場合には、Start メソッドを片方のスクリプトだけにしておき、
もう一方の Start メソッドは、メソッド名を変更して、Public 修飾子を付けて、外部から呼び出して実行をしてもらう設計に変更をします。

 <エラーの原因>
 1.GameManager Start メソッド内の player.StopMove メソッドを実行する => エラー発生
 2.PlayerController Start メソッド内で GetComponent メソッドを実行し、rb 変数に Rigidbody コンポーネントの情報を代入する
 3.1の処理の前に2の処理が終わっておらず、StopMove メソッド内の rb 変数が null であるためエラーが発生する

 以上の流れによって、rb 変数にコンポーネントの代入を行う処理が間に合っていないことが分かります。

 そこで、次のように変更を行います。

 <エラーの解消方法の例>
 1.PlayerController Start メソッドを public void SetUpPlayer メソッドに名前と修飾子を変更し、外部のスクリプトより呼び出せるメソッドに実行する
 2.GameManager Start メソッド内で、player.SetUpPlayer メソッドの呼び出しを行う
 3.PlayerController SetUpPlayer メソッド内で GetComponent メソッドを実行し、rb 変数に Rigidbody コンポーネントの情報を代入する
 4.GameManager Start メソッド内の player.StopMove メソッドを実行する => StopMove メソッド内の rb 変数が代入されているので、エラーは発生しない


PlayerController.cs
    public void SetUpPlayer {     // Start()を書き換えて、外部から呼び出せる別のメソッドに作り替える
        rb = GetComponent<Rigidbody>();

        // 初期の姿勢を設定
        transform.eulerAngles = straightRotation;

        // 現在の姿勢を「直滑降」に変更(いままでの姿勢)
        attitudeType = AttitudeType.Straight;

        btnChangeAttitude.onClick.AddListener(ChangeAttitude);

        btnChangeAttitude.interactable = false;

        anim = GetComponent<Animator>();

    }


GameManager.cs
  IEnumerator Start()
    {
        // スタート地点取得
        startPos = player.transform.position.y;

        // Startメソッドの処理を別のメソッド化して、外部から実行する
        player.SetUpPlayer();    // <= ☆ 追加する

        player.StopMove();

        // 省略



 このように、複数の処理が競合してしまって上手く実行されない場合には、こちらで、実行する順番を順序立ててスクリプト内に記入し、その通りに実行させる設計に変更することで
実行順位によるエラーを防ぐとともに、Unity 内の処理に依存せずに、設計している順番通りの処理を実行していくことが出来ます

 スクリプトが増えてきて、Start メソッドと Awake メソッドが複数のスクリプトにある場合には、実行される順番によってはエラーを引き起こすことになりますので、
例えば複数の Start メソッドがある場合で、別のスクリプトの情報を参照している場合には、1つのスクリプト内に他のスクリプトの Start 内の処理を順序立てて実行する処理を記述し、
イメージしている順番通りに動く設計を組み立ててください。


10.Slider コンポーネントの MaxValue の値を調整する


 ゲームを実行した際に、アイコンの動作にちょっとした違和感があるのに気が付いたでしょうか。

 本来ならスムースにスタート地点から下方向に移動するはずですが、最初だけ少し、移動距離が大きくなっています。
こちらを解消するには、Slider コンポーネントの MaxValue の設定値を 1 から 0.95 に修正して、再度ゲームを実行してみてください。
違和感なく、スムースにアイコンが下方向に移動を始めます。


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



<実行動画 スムースにアイコンの移動が始まる>
https://gyazo.com/49ebecb4bd2ba1887228c83502f93cee


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

 => 次は 発展4 ーSkyboxの自動変更処理の実装ー です。


10.<応用 姿勢の変更に合わせてアイコンの向きを変える>


 姿勢変更ボタンを押すと、ボタンのアイコンが回転して姿勢と同期するようになっています。
おなじように、姿勢を「伏せ」状態に変更している間、高度用のアイコンも回転させるようにしてみましょう。
また、「直滑降」状態の姿勢に戻った場合には、元のアイコンの状態に戻るように制御をしてみましょう。


<実装動画>
https://gyazo.com/5c23fc2ce87b69272d25ae0f24148f8b

コメントをかく


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

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

Menu



技術/知識(実装例)

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

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

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

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

レースゲーム(抜粋)

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

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

3D脱出ゲーム(抜粋)

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

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

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

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

VideoPlayer イベント連動の実装例

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

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

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

private



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

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