Unityに関連する記事です

 以下の内容で順番に実装を進めていきます。

 手順4〜8ではプレイヤーの分身となるキャラの作成、キャラの行動とアニメーションの制御について実装を行います。

 この手順では、手順6で作成したジャンプのアニメーションについて、問題点の検証と改善案を考え、ジャンプアニメーションの修正を行います。

手順7 −キャラのジャンプの改善−
10.ジャンプや空中浮遊時の問題点を考えて改善する



新しく学習する内容


・Layer機能
・Physics2D.Linecastメソッド
・Debug.DrawLineメソッド


10.ジャンプや空中浮遊時の問題点を考えて改善する

問題点の検証と改善案を考える


 手順6まででジャンプは出来るようになりましたが、空中浮遊の際、落下の状態にもかかわらず、アニメーションが走るアニメーションに遷移してしまいます。
そのため、空中で歩いているようなアニメになり、これではアニメーションを制御できているとは言えない状態です。


<現在の実行動画>
https://gyazo.com/7ffddb2c86ac207c8f351206162ffef3


 問題点を検証し、その改善案を考えて、正常な制御を行えるようにします。


問題点と改善案


 現在はキャラの状態が分からないまま、キャラが動いています。つまり、キャラは「空中」にいるのか、「地面」にいるのか、という設定がスクリプト内にないため
空中であっても矢印キーのキー入力に反応して、走るアニメーションが再生されている状態になっています。

 今回はこの改善案として、地面にいるかどうか、という判定を追加して、地面にいる場合、地面にいない=空中にいる場合という状態を作りだせるようにします。

 キャラの足元と地面用のゲームをオブジェクトの間でこの地面の接地判定を行うようにし、この接地判定が真ならば地面に接地している、
接地判定が偽ならば地面に接地していない=空中にいるという判定を行う処理を追加します。

 この判定には、Layer機能とPhysics2D.Linecastメソッドを利用することで実装します。

 Layer(レイヤー)とは、ゲームオブジェクトをグループ分けする機能です。今回は地面用のゲームオブジェクトのLayerをGroundというLayerに設定し、
この Ground というLayer とキャラのゲームオブジェクトとが一定の距離で接触している状態を「接地」と判定するようにします。


Layer機能 参考サイト
Unity公式マニュアル
レイヤー
https://docs.unity3d.com/ja/2019.4/Manual/Layers.h...
YTTMWORK様
レイヤー
https://yttm-work.jp/unity/unity_0021.html


 Ground のLayer設定を持つゲームオブジェクトとキャラが接触しているかどうかを判定するメソッドとして、Physics2D.Linecastメソッドを利用します。

 まずは、スタート地点のゲームオブジェクトの Layer の設定を変更します。


Ground_Start ゲームオブジェクトの Layer を Default から Ground に変更する

 ヒエラルキーで Ground_Start ゲームオブジェクトを選択し、インスペクターの右上部にある Layer の設定を Default から Ground に変更します。


Ground_Start ゲームオブジェクト インスペクター画像(右上のLayerを設定する)



 設定を変更した際に、次のような警告文が表示されたら、Yes,Change Children を選択し、子オブジェクトの Layer の設定も Ground に変更します。
これは、子オブジェクトについても、同じLayerの設定を反映するかどうかの確認です。誤って No を選択した場合には、子オブジェクトの Layer を個別で Ground に設定してください。


Layer変更時の警告文



 念のため、子オブジェクトのLayer の設定も確認しておいてください。すべて Ground になっていれば問題ありません。


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



接地判定をどのように利用するか考える

 では、この接地判定の結果をどのように利用して、落下と歩くアニメーションを制御するかですが
「キャラが空中にいる状態であり、かつ、落下中である」という2つの状態を満たしている限り、歩くアニメーションではなく、落下のアニメーションを行うようにします。
こういった条件の考え方は、現実的な考えを元に作成した方が条件としてもわかりやすくなります。

 キャラが空中にいる状態とは、すなわち接地していない状態ですので、isGrounded = false の状態です。

 そして、落下中というのは、キャラのRigidbody2Dコンポーネントの管理している、Velocityの値で判断できます。
Velocityは速度ベクトルの値ですので、ゲーム画面に対して落下中というのは、上から下にゲームオブジェクト(キャラ)が移動している状態の値です。
つまり、VelocityのY軸の値がマイナス方向になっている状態が、キャラが落下中という状態であると言えます。

 この2つの満たしている間は、キャラは空中にいて、落下している状態であると判断できますので、その間は落下アニメーションを再生するように制御します。


PlayerController スクリプトを修正して、地面に着地するまで落下のアニメーションを再生する処理を追加する


 キャラがどのLayerと接地の判定を行うか指定するために、新しく LayerMask型の groundLayer変数を用意します。
public 修飾子ですので、スクリプト完成後にインスペクターから接地の対象とするLayerを設定します。

 また、その接地の判定した情報を扱うために、bool型の isGrounded 変数を用意します。Layerによる判定結果をこの変数に代入し、
キャラの現在の状態に合わせて、接地しているか、接地していないかを常に(Upadateメソッドを利用して)、 true(接地中)、false(空中)で結果を代入できるようにします。


PlayerController.cs

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



Yuko_Player ゲームオブジェクトの PlayerController を設定する


 スクリプトを修正してセーブします。Yuko_Player ゲームオブジェクトを選択して、インスペクターの PlayerController を確認します。
新しく追加した変数の情報が追加されていますので、こちらを設定します。


Yuko_Player ゲームオブジェクトの PlayerController インスペクター画像 設定前



 isGrounded 変数の値は変更せずに問題ありません。この値はゲーム実行中に地面との接地の状態に合わせて true、 false が切り替わります。
設定があることだけ確認をしておきます。

 groundLayer 変数の部分はプルダウンメニューになっており、初期値は Nothing に設定されています。
この部分に、Linecastメソッドによって判定を行いたい Layer を指定しますので、地面役のゲームオブジェクトに設定した Layer と同じ Ground を設定します。
これでLinecastメソッドは、この Ground のLayer に対して判定を行うように設定が出来ました。


Yuko_Player ゲームオブジェクトの PlayerController インスペクター画像 設定後



ゲームを実行して確認する


 ゲームを実行してジャンプ後、落下のアニメーションが継続的に再生されるかを確認してみます。

 空中を移動中でも歩くアニメーションがなくなり、地面に着地するまでは、ずっと落下のアニメーションが再生されれば成功です。


<実行動画>
https://gyazo.com/8b9926f3d4750329ede8c0f75adb5400


<Physics2D.Linecast>


 指定した地点から別の地点までの間に見えない線を引いて、その線の中に他のゲームオブジェクトのコライダーが接触したかどうかを判定するメソッドです。
コライダーを持つゲームオブジェクトに接触した場合には true、接触しない場合には false を戻します。


参考サイト
Unity公式スクリプトリファレンス
Physics2D.Linecast
https://docs.unity3d.com/ja/current/ScriptReferenc...


 サイトを確認するとわかりますが、このメソッドには引数の指定の仕方が2種類あります。
このように、同じメソッドでも異なる引数を持つことを、オーバーロードを持つメソッド、あるいは、オーバーロード・メソッドといいます。

 今回は、サイトの上段にある引数のオーバーロードを利用したメソッドを利用しています。
RaycastHit2D Linecast (Vector2 start, Vector2 end, int layerMask= DefaultRaycastLayers, float minDepth= -Mathf.Infinity, float maxDepth= Mathf.Infinity)


  // 地面接地  Physics2D.Linecastメソッドを実行して、Ground Layerとキャラのコライダーとが接地している距離かどうかを確認し、接地しているなら true、接地していないなら false を戻す
  isGrounded = Physics2D.Linecast(transform.position + transform.up * 1f, transform.position - transform.up * 0.8f, groundLayer);


 このLinecastメソッドを利用し、キャラの位置から、キャラの足元に向けて見えない線を引きます。
そして、その線と Ground の設定を持つゲームオブジェクトが接触した場合には trueを戻りますので、接地している状態であると設定します。


参考サイト
ゲームを作成しよう様
Linecastの利点と問題点
http://gamemakerlearning.blog.fc2.com/blog-entry-5...
Unity不定期便様
Unityの2Dゲームで「当たり判定」の基本を30分で理解するコツ!(後編)
https://0310unity.hateblo.jp/entry/collision_detec...


<Debug.DrawLine>


 この機能は、Sceneビューにて機能します。

 上記のLinecastの見えない線を可視化するためのDebug機能です。引数には、Linecastで設定した内容と同じ内容で設定を行うことで
どの位置にラインが引かれているのか、ゲームオブジェクトと接触しているのかを確認することが出来ます。


  // Sceneビューに Physics2D.LinecastメソッドのLineを表示する
  Debug.DrawLine(transform.position + transform.up * 0.4f, transform.position - transform.up * 0.9f, Color.red, 1.0f);


SceneビューでのLinecastの可視化(ここでは可視化をわかりやすくするように、実際のプログラムとは違う数値を入れています)



 キャラの中央から縦に赤い線が見えると思います。これがLinecastメソッドの実行内容であり、それを可視化しています。
赤い線が地面に入りこんでいるのがわかると思いますが、この部分が「接地している」として判定されます。

 キャラがジャンプした場合には、この赤い線が地面から離れていきますので、この場合が「接地していない」として判定されます。


<検証動画 キャラの足元から赤いラインが見える。これがLinecastメソッドの実行結果>
https://gyazo.com/c7741e05c0c227f21fc67241125f5239


 このように処理を可視化することで、どのような処理が実行されているかを確認できます。非常に重要なことですので、積極的に利用してDebugを捗るようにしましょう。

参考サイト
Unity公式スクリプトリファレンス
Debug.DrawLine
https://docs.unity3d.com/ja/current/ScriptReferenc...


問題点の検証と改善案を考える


 地面を歩いていると、突然、落下のアニメーションが再生されることがあります。何故でしょうか。

 落下のアニメーションの再生条件は、以下の通りです。

    // 接地していない(空中にいる)間で、落下中の場合
    if (isGrounded == false && rb.velocity.y < 0.15f) {
        // 落下アニメを繰り返す
        anim.SetTrigger("Fall");
    }


 本来であれば地面と接地している限りは、この条件を満たすことはないはずです。
それにもかかわらず、落下アニメーション再生が再生されてしまうということは、地面との接地判定がない状態かつ、VelocityのYの速度ベクトルに値が規定値よりも大きいということになります。
キャラを移動させているので、Velocityに関しては速度ベクトルの値が大きくなる可能性はありえそうです。
ですが、この条件は「かつ」という条件式ですので、片方の条件を満たしただけでは条件を真であると評価しません。

 ゲームを実行して、ゆっくりとキャラを移動させて、ブロックとブロックの間位を移動させてみてください。
ブロック間のつなぎ目の部分で iSGrounded の値が false になることがあります。これが原因です。


<検証動画 isGrounded の値が変化してしまう位置を見つける>
https://gyazo.com/b0f4a24caa1093df7a9dc4d1dd27120d


 ブロックの外見通りに作ったコライダーは、ブロックのつなぎ目の部分にないため、その隙間の部分で isGrounded による判定が false になってしまい
結果として落下アニメーションの条件を満たしてしまっていたため、地面を歩いているにもかかわらず、落下のアニメーションが再生されていました。

 折角ですが、このブロックに関しては、左右にだけ少しコライダーを広げて、見た目上の隙間があっても、コライダーは存在している状態にしましょう。


Nature_props_15 ゲームオブジェクトのコライダーの左右の幅を少し広げる



 これをスタート地点の4つのブロックすべてで設定し、隙間の部分にもコライダーがある状態にしてください。
その上で、もう一度、キャラを移動させてみましょう。


<検証動画 キャラが移動しても isGrounded の値が変化しないことを確認する => 落下のアニメーションの誤再生がなくなる>
https://gyazo.com/0299052d073520889f6f984d3f195693

 隙間の上を移動しても、isGrounded の値が true のままになりましたので、落下のアニメーションの誤再生が改善されました。

 このように、エラーや不具合は、順番に原因を探していくことで特定できます。そして改善案を考えて修正を行いましょう。


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

 次は 手順8 −キャラの移動範囲の制御− です。

コメントをかく


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

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

Menu



プログラムの基礎学習

コード練習

技術/知識(実装例)

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

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

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

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

レースゲーム(抜粋)

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

3D脱出ゲーム(抜粋)

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

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

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

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

3Dトップビューアクション(白猫風)

VideoPlayer イベント連動の実装例

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

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

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

private



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

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