Unityに関連する記事です

 プレイヤーをジャンプさせる機能を実装します。

<実装動画 ジャンプアニメなし>
動画ファイルへのリンク



 なお、この手順の時点ではジャンプアニメの同期はありませんが、いずれは、下記のような状態にすることを念頭に置いておいてください。

<実装動画 ジャンプアニメあり(この手順では、ここまでいかない)>
動画ファイルへのリンク



手順8 ージャンプ機能の実装ー

<新しく学習する内容>
 ・機能実装のためのロジックの考え方



プレイヤーをジャンプさせるための設計を考える


 移動の処理が実装されたので、今度はジャンプの処理をプレイヤーに実装していきます。
ジャンプの設計について考えながら、実装方法を考えていきましょう。



 アクションゲームですので、ジャンプボタンを押したら、それに合わせてプレイヤーがジャンプし
さらにジャンプと同時にジャンプのアニメーションが再生される、という流れが自然かと思れます。

 では、ジャンプとは、どのようにすれば実装できるのでしょうか。
ゲームの動きをプログラムに置き換えて、どういった処理を作ればジャンプしているようになるのかを考えることが大切です。

 プレイヤーの移動は、ゲームオブジェクトの位置情報(座標)を更新していくことで実装が可能でした。
ジャンプも同じ考え方でよいと思います。

 2Dの場合、プレイヤーの左右移動については、ゲームオブジェクトの Position の X 軸の値を制御することで実装できました。
3Dの場合、左右移動のみではなく、奥行きの移動も追加になるため、ゲームオブジェクトの Position の X 軸と Z 軸の値を制御することで、実装を行っています。
移動のプログラムを読み返してみてください。



 2D・3Dのいずれの場合であっても、ゲームオブジェクトの Y 軸(高さ)の位置情報を更新することができれば、
ゲームオブジェクトが上下に移動するため、ゲーム画面においてはジャンプしているように見えるでしょう。

 つまり、プレイヤーの位置が地面のゲームオブジェクトの位置よりも高くなれば、ジャンプしている状態になります。
そのまま地面まで落下が出来、プレイヤーと地面が前と同じ位置になれば着地となり、落下し、ジャンプしていない状態になります。

 まずはこの Y 軸の位置情報を更新することを考えます。



 気を付けるべきは、Y軸の位置情報をどのように更新するか、です。

 例えばゆっくりとした位置情報の更新では、ゲーム画面のゲームオブジェクトもゆっくりと移動してしまうため
そのままではジャンプという挙動には見えなくなってしまいます。

 ジャンプということを画面で表現するためには、ある程度の高さまで勢いよく移動をし、
その後、落下してくるという挙動がユーザーの期待するジャンプになると思います。

 また、位置情報を変化させる方法はいくつかありますが、「勢いよく」移動するのか、
「一瞬でその位置まで」移動するのかでは、位置情報を変更させる処理を行う機能が異なります。

 一瞬で移動ではなく、地面から空中に勢いよく滑らかに飛び上がる方法が、よりジャンプに見えます。
そのため、ここでも移動の時と同じように、Rigidbody の機能を使って、Y 軸の位置情報の更新を実装すれば、ジャンプのように見える挙動になります。



 ユーザーの考えるゲーム内の見た目の動きを、どのような機能を使ってプログラムをすれば期待している挙動になるのか
これを念頭に置いて設計を考えていくとよいと思います。また、位置情報の更新方法も何種類かありますが
それらの特徴を理解することにより、どの処理が最も実装に適しているのか、判断をすることが大切です。
そのためにも色々な処理を試して、どのような挙動をするのかを知っておくことが必要になります。


ジャンプのプログラム制御の方法を考える


 では次に、ジャンプする際には、どのような順番の制御処理が必要になるか、考えていきましょう。
期待する挙動と、そのために考えられる制御方法です。


 .廛譽ぅ筺爾地面にいる際にジャンプボタンを押すことでジャンプが出来る。
    => 地面とプレイヤーとの接地判定が必要

 ▲献礇鵐彙罎忘禿戰献礇鵐廛椒織鵑魏,靴討癲二段ジャンプなどはしない。
    => ジャンプ中であるという判定、あるいは、それに見合う状態が必要

 0榮庵罎縫献礇鵐廚靴疹豺隋移動先に着地する。
    => その場でジャンプした場合は、その場に着地し、移動中であった場合には、移動先の位置で着地する

 っ綯呂靴燭藝禿戰献礇鵐廛椒織鵑妊献礇鵐廚出来る。
    => ,寮榁枠縦蠅汎韻現萢 判定の結果により、地面にいるのか、いないのか(空中なのか)が判定される


 順番立てて考えていきましょう。


.廛譽ぅ筺爾地面にいる際にジャンプボタンを押すことでジャンプが出来る


 地面となるゲームオブジェクトと、プレイヤーとの間に接地しているかどうかの判定を盛り込むことで
「プレイヤーが地面にいる」という条件を分岐することが可能であると考えられます。

 この接地判定の方法にはいくつかやり方があります。ここでは今まで利用していないLayer(レイヤー)の機能と
それを利用するLinecast(ラインキャスト)の機能を利用して、判定を行っていきます。

 Layerにはあらかじめ何種類か登録されており、Groundというレイヤーがあります。
地面役のゲームオブジェクトを選択し、LayerをDefaultからGroundに変更しましょう。
これにより、より地面としての役割を担うことが出来ます。
 
 Linecastは、Unityの持つPhysics(フィジクス)によって利用可能な機能の1つです。
if文と組み合わせることで、指定されたゲームオブジェクト(ここではPlayer)から見えない光線を発射し、
その光線と指定したレイヤー(ここではGroundのレイヤーを持つゲームオブジェクト)とがぶつかっているかどうかを
Bool型の戻り値として返してくれます。
 このBoolの値を接地状態として読み替えることにより、接地判定として実装を行います。
Linecastの結果がTrueならば、Playerから発射された見えない光線がGroundレイヤーを持つ地面のゲームオブジェクトとぶつかったことになります。
つまり、ゲームオブジェクト同士がくっついている状態であると考えることが出来ますので、「地面にいる」状態であると言えます。
 逆にFalseの場合は、先ほどの光線がレイヤーとぶつかっていない状態になりますので、ゲームオブジェクト同士がくっついていない状態であり
「地面にいない」状態であると言えます。

 判定方法は他にもいくつかありますが、このLinecastによるBool型による処理が接地判定に有用であるため、
この機能を接地判定として実装することにします。

 ジャンプ用のボタンを押した際の条件に「地面にいる状態で」ジャンプボタンを押したらジャンプできるとすれば、1つ条件を盛り込めばよいでしょう。


▲献礇鵐彙罎忘禿戰献礇鵐廛椒織鵑魏,靴討癲二段ジャンプなどはしない


 上記,亮汰と同時に、この△僚萢も自動的に実装されます。

 ジャンプ中、つまり「地面にいない」状態のときにはジャンプボタンを押しても反応をしないようにするのが、一番実装しやすい条件となりますが
,離献礇鵐廚任る条件としてすでに「地面にいる状態でジャンプボタンを押したらジャンプできる」という条件がありますので
これはそのまま「地面にいない状態ならジャンプボタンを押してもジャンプできない」というように逆に読む解くことが可能です。
 ,亮汰と同時に、この制御も実装されていることになりますね。


0榮庵罎縫献礇鵐廚靴疹豺隋移動先に着地する


 移動とは、位置情報を更新することで実装していますので、ジャンプした際に移動する位置を0にするという処理がない限りは
この状態も自動的に実装されることになります。
 移動していない状態であれば、位置情報も更新がありませんので、ジャンプした位置に着地することになります。


っ綯呂靴燭藝禿戰献礇鵐廛椒織鵑妊献礇鵐廚出来る


 これも,亮汰と同時に制御が実装されます。
LinecastによるBool型での戻り値はUpdateにて処理されていますので、このif文によるBool型は常時監視されている状態です。
 ですのでジャンプが終わって地面との接地判定が取れればLinecastはTrueを返すようになりますので、
結果、またジャンプができる状態が成立するようになります。


 以上のように、発生するであろう問題点や疑問点は、それらにつきすべての処理を実装しなければならない訳ではなくて
いずれかの処理によって問題がクリアされるもの、あるいは逆に問題となってしまうものなど、様々な結果を生じさせます。
大切なのは、1つの処理をいれることで多くの場所に影響が出る(少なくとも今回ジャンプを入れるだけでも 銑い量簑蠹世鮃洋犬靴覆い箸覆蕕覆ぁ砲箸いΔ海箸覆里任后

 これをイメージすることにより、設計の段階で多くの疑問点が露呈できれば、実装する前にそれを見越したプログラムを考えていくことが出来ます。
今回の場合は 銑い泙覇段未閉媛箪萢を加えずともジャンプの処理を追加すればすべて問題なく実装されますので、安心してプログラムを組んでいくことが出来ます。

 またジャンプの制御に合わせてジャンプのアニメーションも再生できれば、上手く同期が出来そうです。


ジャンプの処理の実装例


 スクリプトについては、記述する処理はほとんど同じですが、2つのスクリプトの書き方を用意しています。
新しくジャンプ専用のスクリプトを作成する方法をお勧めしますが、すでにある PlayerController スクリプトに処理を追加しても良いです。

 新しくスクリプトを作る方法をお勧めする理由は、オブジェクト指向型プログラムにおける SOLID原則に起因しています。
この原則内に「単一責任の原則」があり、クラスの責務を考えたとき、
ジャンプの処理は、ジャンプの処理だけを持つクラスを作成した方がこの原則に則ったクラスとなるためです。


地面用のゲームオブジェクトに Layer の設定を行う


 地面用のゲームオブジェクトに Layer の設定を行います。

 設定したいゲームオブジェクトをヒエラルキーで選択し、インスペクターの右上の Layer を選択します。
設定可能な Layer が表示されますので、一番下の Add Layer... を選択します。
インスペクターの表示が Tags & Layers に切り替わりますので、新しい Layer の登録を行います。

 User Layer 6 の部分に Ground を追加してください。

すでに登録されている場合には、この手順はスキップし、次の手順へ進んでください。


<インスペクター画像>





 再度、Layer の設定を行うゲームオブジェクトをヒエラルキーで選択し、同じように Layer の部分をクリックします。
登録した Ground の Layer が選択できるようになっていますので、そちらを設定します。


<インスペクター画像>



 複数の地面用のゲームオブジェクトがある場合には、それぞれの Layer に Ground を設定を行ってください。

 この設定を行うことで、次に作成するスクリプトの接地判定用の Linecast 処理と連動させることが出来ます。


PlayerJump クラスを作成する


 新しいスクリプトを作成して、 PlayerJump クラスを作成します。こちらの方法を採用する場合、次の PlayerController スクリプトへの修正は不要です。
作成後、プレイヤー用のゲームオブジェクトにスクリプトを PlayerJump スクリプトをアタッチします。


PlayerJump.cs

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



プレイヤー用のゲームオブジェクトに PlayerJump スクリプトをアタッチして設定を行う


 プレイヤー用のゲームオブジェクトに PlayerJump スクリプトをアタッチして設定を行います。

 PlayerJump スクリプトのインスペクター上に、ジャンプ力の数値を入力する JumpPower 変数が表示されますので、150 〜 300 位で設定します。
また GroundLayer 変数には、プレイヤーとの接地の判定の対象となるレイヤーを設定できるようになりますので、こちらを Ground に変更します。


<インスペクター画像>



 以上で設定は完了です。


PlayerController クラスを修正する


 こちらはすでに作成済の PlayerController にジャンプ処理を追加した場合の実装例です。
PlayerJump スクリプトを作成していない場合には、こちらの方法を採用してください
作成している場合にはスキップしてください。


PlayerController.cs

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



プレイヤー用のゲームオブジェクトの PlayerController の設定を行う


 PlayerController のインスペクター上にジャンプ力の数値を入力する項目が追加されますので、150〜300位で設定します。
またGroundLayerには、Playerとの接地の判定の対象となるレイヤーを設定できるようになりますので、こちらをGroundに変更しましょう。

 isGroundのBool型は、本来はPrivateの変数で問題ありません。
ですが今回は、Debugの関係上、インスペクター上にて接地状態を確認できるように SerializeField 属性を利用して表示しています。
これはDebug.Logを入れ込む場所がUpdateでの処理が行われるため、非常に多くのDebug.LogがConsoleに流れてしまい
実際に接地判定のBoolの値の動きを追うのが困難になるためです。
接地判定としての動きが問題なく追えたのであれば、あとでPrivateに戻しておきましょう。


PlayerController インスペクター画像



ゲームを実行して動作を確認


 どのような挙動をするのか、プログラムのロジックを理解した上でゲームを実行し、デバッグを行って動作の確認を行います。
動いたら成功ですが、それだけで終わらないように、どうしてそのように動くのか、を考えていくようにしてください。

 isGround 変数の値が true の間は、地面とプレイヤーのゲームオブジェクトが設置している、と判定するようにしています。
そしてその状態のときだけ、ボタンを押すとジャンプするように制御を行っています。

 ジャンプ中は isGround 変数が false になりますので、ジャンプ中に再度ボタンを押しても空中で追加のジャンプ(二段ジャンプ)は行いません。
よってこの動作もこれも接地判定と密接に関連しています。


<実装動画>
動画ファイルへのリンク


 ロジックを考えるためには、まずは日本語で作りたい処理を書いてみましょう。
それを元に、どういった処理を組み立てていけばいいのか、Unity に用意されているメソッドを使うのか、どのような変数を作って利用していけばいいのか、
そういった視点で考えていくと処理が浮かんでくるようになります。



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

 => 次は 手順9 ーキャラクターのアニメーション遷移設定ー です。

コメントをかく


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

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

Menu



技術/知識(実装例)

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

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

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

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

レースゲーム(抜粋)

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

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

3D脱出ゲーム(抜粋)

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

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

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

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

VideoPlayer イベント連動の実装例

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

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

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

private



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

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