Unityに関連する記事です

 この手順ではキャラのジャンプ処理の実装していきます。

 まずはボタン操作に合わせてキャラをジャンプさせるようにします。このときはボタンを押すたびに空中でも続けてジャンプをする状態です。
その後、斜面に接地中にのみ1回だけジャンプが行えるように制御を行います。


<実装動画 斜面の判定を行って、斜面にいる間に1回だけジャンプできるようにする>
https://gyazo.com/8276d22805cc14fdedf426fa5a7fbb7d


手順15 −ジャンプの実装−

25.キャラをジャンプさせる
26.キャラのジャンプの制御をする


新しく学習する内容


 ・Rigidbody.AddForce メソッド
 ・Physics.Linecast メソッド
 ・Debug.DrawLine メソッド


25.キャラをジャンプさせる

1.設計


 ジャンプの設計について考えながら、実装方法を考えていきましょう。

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

 ジャンプとは、どのようにすれば実装できるのでしょうか。
プレイヤーの移動は、位置情報を更新していくことで実装が可能でした。
ジャンプも同じ考え方でよいと思います。

 ゲームオブジェクトのY軸(高さ)の位置情報を更新することができれば、ジャンプしているように見えるでしょう。
つまり、プレイヤーの位置が地面の位置よりも高くなれば、ジャンプしている状態になります。
そのまま地面まで落下が出来、プレイヤーと地面が前と同じ位置になれば着地となり、ジャンプしていない状態になります。
 そのY軸の位置情報を更新するのに合わせてジャンプのアニメーションも再生できれば、上手く同期が出来そうです。



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

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

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

 また、位置情報を変化させる方法はいくつかありますが、「勢いよく」移動するのか、「一瞬でその位置まで」移動するのかでは位置情報を変更させる処理を行う機能が異なります。
一瞬で移動してしまってはジャンプの軌道が見えないため、地面から空中に勢いよく滑らかに飛び上がる方法が、よりジャンプに見えます。

 そのため、RigidbodyのAddforce関数を使ってY軸の位置情報の更新を実装すればジャンプのように見える、期待する挙動になります。
 ユーザーの考えるゲーム内の見た目の動きを、どのような機能を使ってプログラムをすれば期待している挙動になるのか、これを念頭に置いて設計を考えていくとよいと思います。

 また、位置情報の更新方法も何種類かありますが、それらの特徴を理解することにより、どの処理が最も実装に適しているのか、判断をすることが大切です。
そのためにも色々な処理を試して、どのような挙動をするのかを知っておくことが必要になります。


2.PlayerController スクリプトを修正する


 上記の設計方法をふまえて、ジャンプの制御処理を実装します。
まずは、接地の判定は考えずに、特定のボタンを押したらジャンプをする、という処理を考えて実装してみてください。


PlayerController.cs

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



 スクリプトを修正したらセーブを行い、PlayerController スクリプトがアタッチされている Penguin ゲームオブジェクトのインスペクターを確認します。
新しく宣言した変数が表示されているか、確認しておきます。


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



3.<Rigidbody.AddForce メソッド>


 ゲームオブジェクトに物理的な力を加えるメソッドです。
力を与えることによって、物理演算にのっとってゲームオブジェクトを移動させる処理が行えます。
Rigidbody.AddForce (Vector2 force, ForceMode2D mode= ForceMode2D.Force)

 // キャラに上方向の力を加える
  rb.AddForce(transform.up * jumpPower);

 第1引数に、ゲームオブジェクトに与える力の値を設定します。第2引数は力の与え方に対するオプション値です。初期値で Force が設定されています。
Rigidbodyの場合には、ForceModeは4種類あります。力の値を変更するとどうなるか、第2引数の設定を変更するとどうなるかなど、
自分で調べて、スクリプトに代入し、違いを確認してみましょう。


 第1引数で利用している transform.up 変数は、Unity が用意している変数の1つです。
ゲームオブジェクトの、ワールド空間でみたローカル Y座標でのベクトル(向き)の長さが1の単位ベクトルの情報(0, 1, 0)を示しています。
つまり、ゲームの世界全体での Y軸の情報ではなく、そのゲームオブジェクト自体の Y軸の情報を参照するという変数になります。

Unity スクリプト・リファレンス
Transform.up
https://docs.unity3d.com/ja/current/ScriptReferenc...
ねこじゃらシティ 様
【Unity】オブジェクトの向きを取得する
https://nekojara.city/unity-object-direction


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

SamuraiBlog様
【Unity入門】Rigidbodyで自在に移動!addforceやpositionを極めよう!
https://www.sejuku.net/blog/54896


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


 新しく追加されている JumpPower 変数に設定を行います。200 前後にしておいて調整をしていくようにしましょう。

インスペクター画像



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


 ジャンプできるか確認してみてください。

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


 以上でこの手順は完成です。いまはボタンを押した分だけジャンプをしてしまいますので、次はこのジャンプの制御を行います。


26.キャラのジャンプの制御をする

1.設計


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

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

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

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

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

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


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

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

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

 Layerにはあらかじめ何種類か登録されており、Groundというレイヤーがあります。(Unityのバージョンによってはない場合もあります)
地面役のゲームオブジェクトを選択し、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 スクリプトを修正する


  銑い寮御の情報を元に、PlayerController スクリプトを修正して、ジャンプの行動に制限を設けるようにします。
ロジックを考えてみて、自分なりの実装を試してみてください。


PlayerController.cs

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



 スクリプトを修正したらセーブを行い、PlayerController スクリプトがアタッチされている Penguin ゲームオブジェクトのインスペクターを確認します。
新しく宣言した変数が表示されていれば問題ありません。


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



3.<Physics.Linecast メソッド>


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


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


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

 今回は、サイトの上段にある引数のオーバーロードを利用したメソッドを利用しています。
public static bool Linecast (Vector3 start, Vector3 end, int layerMask= DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal);

  // Linecast メソッドを実行してキャラの足元に向けて見えない Line を飛ばし、
  // Line に groundLayer 変数で指定したLayer(Ground)を持つゲームオブジェクトが接触するか判定。対象のLayerのときは true を返す
  isGrounded = Physics.Linecast(transform.position, transform.position - transform.up * 0.3f, groundLayer);


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

 キャラがジャンプして空中に浮かぶと、Line が斜面のゲームオブジェクトのコライダーと接触しなくなりますので、その場合には false が戻り、接地していない状態とします。

 この処理においても、引数の中で transform.up 変数が活用されています。どのような処理を行っているかを読み解いて、説明できるように理解を深めてください。


参考サイト
のっぴの備忘録 様
レイキャストまとめ
https://nopitech.com/2018/07/05/post-725/


4.<Debug.DrawLine メソッド>


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

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


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


SceneビューでのLinecastの可視化



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

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


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


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

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


5.Slope ゲームオブジェクトの Layer の設定を行う


 Unity にはゲームオブジェクトに Layer(レイヤー)を1つ設定することが出来ます。
この機能では、カメラに映るゲームオブジェクトをLayerで制限したり、あるいは、接触判定をLayerで無視したりといったことが出来ます。

参考サイト
Unity公式マニュアル
Layer
https://docs.unity3d.com/ja/current/Manual/Layers....



 今回はゲームオブジェクトのコライダーの判定に利用します。
利用方法は、斜面のゲームオブジェクトに新しく作成する Ground というLayerを設定し、そのLayerを利用して判定を行います。

 まずは新しいLayerを作成します。どのゲームオブジェクトでもよいので、インスペクターのLayerを選択して、一番下にある Add Layer を選択します。
Layerを管理しているウインドウが開きますので、8番目のLayerとして Ground を登録して作成します。


<手順動画 Layerの登録>
https://gyazo.com/fcf7fd43098e177ca24f2bd27fe77405



 登録が終了したので、次はゲームオブジェクトにLayerの設定を行います。

 ヒエラルキーにある Slope ゲームオブジェクトを選択して、インスペクターから Layerを Default から Ground に変更します。


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



 以上で設定は完了です。


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


 最後に、Penguin ゲームオブジェクトの PlayerController スクリプトの設定を行います。

 インスペクターに新しい変数が2つ追加されていますので、groundLayer 変数に、Ground を設定します。
Layer 情報はプルダウンメニューの中から登録されている情報より選択することが出来ます。

 この設定した Layer 情報と、Slope ゲームオブジェクトに設定した Layer の情報とが一致するかを、Linecast メソッドで判定を行います。
その結果が isGrounded 変数に代入されるようになります。そのため、isGrounded 変数は初期値のままで問題ありません。


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



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


 ジャンプの制御が行えるようになったか、ゲームを実行して確認しましょう。

 斜面のゲームオブジェクトに対して、キャラの足元から出ている Line が接触している間は「接地」状態になりますので
ジャンプを行うことが出来ていれば制御成功です。

 ジャンプ中は、この Line が斜面まで届きませんので「非接地」状態になりますので、ジャンプが出来ない状態ならば制御成功です。

 この制御によって、接地中に1回だけジャンプを行えるように制御されます。


<実装動画 斜面の判定を行って、斜面にいる間に1回だけジャンプできるようにする>
https://gyazo.com/8276d22805cc14fdedf426fa5a7fbb7d


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

 次は 手順16 −ジャンプのアニメーションの実装− です。

コメントをかく


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

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

Menu



プログラムの基礎学習

コード練習

技術/知識(実装例)

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

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

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

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

レースゲーム(抜粋)

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

3D脱出ゲーム(抜粋)

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

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

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

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

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

VideoPlayer イベント連動の実装例

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

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

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

private



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

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