Unityに関連する記事です

 2Dゲームにおいて、プレイヤーを軸にして公転する弾の機能の実装例です。

 特にこのケースは、公転の処理もですが、弾を円周上に等間隔で配置する方法が重要な機能になります。

 例えば、プレイヤーの周囲に2つの弾が公転する場合と3つの弾が公転する場合では、等間隔で配置するための座標や角度が異なります。
公転する弾をプレイヤーの周囲の円周上に等間隔で配置する処理をしっかりと行わないと、すべて同じ位置に弾が配置されたり等間隔で配置できない状態が発生します。


<公転する弾 2つ>



<確認動画 ー公転する弾 2つの場合ー>
動画ファイルへのリンク


<確認動画 ー公転する弾 3つの場合ー>
動画ファイルへのリンク


 このように、弾の数に応じて、等間隔で配置する必要があります。

 また公転している弾自体も自転する形になっています。この例であれば、手裏剣字体も回転しています。



 下記の動画は応用例です。こちらは次の手順で学習します。


<応用例 ーボタンを押すとプレイヤーの進行方向に弾をまとめて投射するー>
動画ファイルへのリンク



1.ゲームオブジェクトの構成


 あくまでもサンプルの構成ですので、自分のプロジェクトの内容に合わせて変更して利用してください。
すでに自分のプロジェクト内にプレイヤー用のキャラがいる場合、この手順は不要です。
次の【2.公転する弾のプレハブの作成】の手順へ進んでください。



 この教材ではこちらの記事の内容をベースに作成しています。

   => 肥大化したクラス内の処理を、役割に応じたクラスを複数作成して分割する実装例



 ヒエラルキーで Create Empty を行い、Player 用の CharaSet ゲームオブジェクトを作成します。
その子オブジェクトとして、画像を持つ Chara オブジェクトを配置します。

 CharaSet ゲームオブジェクトには Capsule Collider2D コンポーネントと Rigidbody2D コンポーネントをアタッチしておきます。
コライダーのサイズはゲームの環境に合わせて、プレイヤーの当たり判定として利用することを前提に設定してください。
Rigidbody も Constraint の設定を行ってください。

 Chara ゲームオブジェクトの画像などについては、無料のイラスト素材や、アセットストアなどからインポートしたものを利用してください。
2D Character - Astronaut
https://assetstore.unity.com/packages/2d/character...





 下記はサンプルです。この通りである必要はありません。


CharaSet ゲームオブジェクト



CharaSet ゲームオブジェクト




Chara ゲームオブジェクト(画像設定・アニメ用)



 ゲームオブジェクトを作成するときに、親子関係がある場合、それぞれの位置が大切になります。
子オブジェクトを作成したら、まずは (0,0,0) の位置に合わせてから、調整を行うようにしましょう。


2.公転する弾のゲームオブジェクトの作成とプレハブ化


 親子関係を利用してゲームオブジェクトを作成し、プレハブにします。

 親オブジェクトの Transform の設定は初期値(Position と Rotation は両方とも(0,0,0)、Scale は(1,1,1)) に設定してください。
また、ゲームオブジェクトの形状に応じた2D用のコライダーをアタッチしてください。サイズは子オブジェクトのサイズに合うように調整してください

 子オブジェクトには画像を設定するための SpriteRenderer コンポーネントをアタッチし、任意の画像を設定してください。
画像のサイズは子オブジェクトだけで変更してください。

 このようにして制作しておくことで、親オブジェクトの設定はいじらずに、各子オブジェクトのみで修正が可能になり、
融通の利くゲームオブジェクトの制作が行えます。


構成




 下記は各オブジェクトの参考値です。


<親オブジェクト インスペクター画像>



<親オブジェクト プレハブビュー画像>






<子オブジェクト インスペクター画像>



<子オブジェクト プレハブビュー画像>




<完成時のプレハブ画像>



 完成したらプレハブにしてください

 プレハブ後はヒエラルキーから削除してください。


3.<弾を円運動(公転)させるクラスのサンプルコード>


 中心点(公転用の軸)を設定し、それを軸として弾を円運動(公転)させるクラスを作成します。

 先ほど作成したプレハブにアタッチして利用します。
親オブジェクトと子オブジェクトの両方にアタッチします。



OrbitingBullet.cs

<= クリックしたら開きます。



4.<Transform.RotateAround(Vector3 point, Vector3 axis, float angle) メソッド>


 ゲームオブジェクトを、指定したゲームオブジェクトを中心軸として円運動(公転)させます。
例えると、地球に対しての月の公転のような回転を行う機能を持つメソッドです。


<公式スクリプトリファレンスより>
 ワールド座標の point を中心とした軸( axis )で angle 度回転させます。
これは Transform の位置と回転が同時に変更されます。



 今回はこちらの円運動(公転)の機能を活用し、プレイヤーを地球として考えたとき、弾を周囲に配置して、月のように公転させています。
RotateAround メソッドの引数は (中心点となるワールド座標用の位置、回転する軸、度数法による回転角度) の順番で指定します。

 // 中心点を元に円運動(公転)
 transform.RotateAround(target.transform.position, Vector3.forward, rotationSpeedClockwise * rotateSpeed * Time.deltaTime);

 第1引数には target.transform.position を指定していますので、target 変数に代入されているゲームオブジェクトを中心点とします。

 第2引数には Vector3.forward を指定していますので、Z 軸を利用した回転軸になります。2Dのルーレットのような回転軸です。

 第3引数には rotationSpeedClockwise * rotateSpeed * Time.deltaTime を指定してます。
最初の rotationSpeedClockwise 変数では回転の方向(時計回りか反時計周り)を設定しています。
rotateSpeed 変数では回転の速度を指定し、Time.deltaTime 変数を用いることで、フレームレートに依存しない速度調整が行われます。

 今回の公転処理は Update メソッド内で実行されることになっているので、
そのままの計算値(rotationSpeedClockwise * rotateSpeed のみ)を利用すると非常に高速で回転してしまいます。

 かといって rotateSpeed 変数自体を細かい値(0.004)といった形で指定するのは調整が大変難しくなります。

 そこで Time.deltaTime 変数を利用して計算結果を小さな値にすることで速度調整し、フレームごとの時間を考慮した滑らかな動きが実現されます
また計算値自体が小さくなるので、rotateSpeed 変数の微調整が容易(0.004 などの細かい値ではなく、3 や 10 といった指定)になり、自然な公転回転を実現できます。


<参考サイト>
Unity公式スクリプトリファレンス
Transform.RotateAround
MRが楽しい 様
指定のトランスフォームを中心にオブジェクトを回転させる
ねこじゃらシティ 様
【Unity】任意軸周りでオブジェクトを円運動させる


5.弾のプレハブに OrbitingBullet スクリプトをアタッチする


 親オブジェクトと子オブジェクトの両方に OrbitingBullet スクリプトをアタッチします。

 親オブジェクトはプレイヤーを軸とし、公転します。

 子オブジェクトは、親オブジェクトを軸とし、公転します。

 それぞれが軸となる対象先が異なることで、
親オブジェクトはプレイヤーの周囲を公転し、子オブジェクトは親オブジェクトの周囲を公転します。
このとき、子オブジェクトの Position は (0,0,0) に設定してあるため、
親オブジェクトの位置で公転しますので、さながら自転しているように見せることが出来ます。

 1つのスクリプトを効率的に利用した機能の実装になっています。



親オブジェクト


 rotateSpeed 変数は、プレイヤーの周囲を公転する際の速度です。

 target 変数には、プレイヤーの情報をアサインするのですが、プレハブの仕様として、ヒエラルキーにある別のオブジェクトは事前アサイン出来ません
そのため、この時点では None の状態のままにしておきます。

 こういったケースでは、プレハブが生成されたタイミングで変数に情報を代入します。

 今回であれば、OrbitingBullet スクリプト内に SetUp メソッドを用意し、引数でプレイヤーの情報を受け取れるようにしています。
次に作成する弾を生成するスクリプトにおいて、この SetUp メソッドを実行してもらい、プレイヤーの情報を引数で受け取って自動的に設定します。



子オブジェクト


 rotateSpeed 変数は、親オブジェクトの周囲を公転(自転のように見える)際の速度です。

 target 変数には、親オブジェクトをドラッグアンドドロップしてアサインしてください。


6.<弾を生成するクラスのサンプルコード>


 OrbitingBulletGenerator をスクリプトし、プレイヤー用のゲームオブジェクトにアタッチします。

 公転する弾を1つ、あるいは複数生成する機能です。
このクラスをプレイヤー用のゲームオブジェクトにアタッチした場合、本スクリプト内の transform.position はプレイヤーの位置になります。

 公転自体は OrbitingBullet クラス内で実装していますので、このクラスでは弾の生成、および弾の配置を行っています。
Start メソッドの代わりに SetUpBulletGenerator メソッドを実行することで初期設定を行います。
自分のプロジェクトに応じて、メソッドを実行するクラスを検討してください。



 複数の弾を配置する処理は、プレイヤーを中心点とした円周上で等間隔の位置に配置するようにしています。
円の角度は時計の3時方向が 0 度の位置です。例えば2つの弾を配置する場合、0 度の位置(3時)と 180 度の位置(9時)に配置する等間隔で配置出来ます。

 この配置機能については、弾の数による分岐を作って対処する方法もありますが、今回はそのアプローチは行いません。
なぜなら、弾の増減に合わせて分岐を追加・削除する必要が生じてしまい、保守が大変になるためです。

 今回は配置機能を計算式を作成することで、弾の数に応じて自動的に等間隔で配置できるように仕組みを作ります
このようにすることで、弾の数が増減しても、分岐処理を修正する必要がありませんので、完成したソースコードの修正が不要になるためです。



 プログラムはこういった計算が得意です。

 そのため、最初のうちは分岐処理を作成して弾の数に応じて配置する場所を固定値で指定してもよいですが、
処理の効率化を図るためには、少しずつでよいので「この処理とこの処理をまとめることはできないか」という視点と考え方を持つように認識を改めていきましょう。



OrbitingBulletGenerator.cs

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




インスペクター画像



 bulletPrefab 変数には発射する弾をアサインします。
今回は OrbitingBullet プレハブをドラッグアンドドロップしてアサインしてください。

 debugNumberOfBullets 変数は発射する弾の数です。デバッグ用ですので、実際には自分のプロジェクトに合わせて修正してください。
この数だけ弾が発射されます。

 下記は参考値です。


インスペクター画像



6.攻撃処理用のスクリプトを修正する


 弾の生成処理を動かすため、攻撃処理用のスクリプトと oribitingBulletGenerator スクリプトとをつなぎます

 ここでは両スクリプトが同じゲームオブジェクトにアタッチされている前提で処理を作成してます。
また、Start メソッドを利用し、テスト用に1回だけ生成命令を実行しています。

 抜粋しますので、自分のプロジェクトに合わせて実装してください。
例えば、ボタンを押したら生成する、一定時間おきに生成するなど、自分の作っているゲーム内容に即した処理を作成してください。



 ここでは仮に CharaController としています。


CharaController.cs


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


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


 ゲームを実行して動作を確認しましょう。

 漠然と動かすのではなく、自分が作成したスクリプトの内容を確認し、処理が正常に動作しているかを見極める力をつけていってください。

 インスペクターで生成する弾の数を指定できますので、値を変更しながらデバッグして確認する必要があります
弾の数に応じて等間隔で配置されるかを確認しましょう。


<確認動画 ー公転する弾 2つの場合ー>
動画ファイルへのリンク


<確認動画 ー公転する弾 3つの場合ー>
動画ファイルへのリンク


 上手く動かない場合には、Unity 内の設定や、スクリプトの内容を見直してください。


9.<ー親子関係における衝突判定のテクニックと活用法ー>


 ゲーム開発において、親子関係は非常に重要な役割を果たします。
特に、親子関係を活用した衝突判定のテクニックは、ゲームの中でキャラクターやオブジェクトの相互作用を実現する上で欠かせない要素です。
ここでは、親子関係における衝突判定の基本原理とその活用法について詳しく説明します。


1.親子関係と衝突判定の基本

 親オブジェクトと子オブジェクトの関係性を活用することで、衝突判定を効果的に扱うことができます。
子オブジェクトにコライダーを設定することで、親オブジェクトにも衝突判定が影響するようになります

 ただし、この際、親オブジェクトに Rigidbodyがアタッチされている場合、子オブジェクトにはRigidbodyをアタッチしないことが重要です。
なぜなら、子オブジェクトにもRigidbodyを持たせると、親オブジェクトと子オブジェクトの物理演算が影響しあい(競合)、正常な動作を行わない可能性があるためです。


2.親子関係のメリット

 親子関係を利用することで、コライダーの回転角度の設定を別々に行うことができます。
これにより、1つのゲームオブジェクト内での異なる配置が柔軟に行えます。

 さらに、親オブジェクトにコライダーを持たせることで、子オブジェクトも衝突判定が有効になります。

 これにより、プレイヤーや他のオブジェクトとの相互作用を簡単に実現できる点が大きなメリットです。


3.親子関係の応用例

 具体的な応用例として、今回利用しているケースを紹介します。

 プレイヤーキャラクター(CharaSet)を親オブジェクトに、その周囲に存在する公転している弾(OrbitingBullet)を子オブジェクトに設定しています。
親オブジェクトにはRigidbodyをアタッチし、物理演算を用いた移動を行います。
一方、子オブジェクトにはコライダーのみを設定し、敵との衝突判定を実現します。



 今回、OrbitingBullet ゲームオブジェクトにはコライダーの設定はありますが、Rigidbody コンポーネントはアタッチされていません。
これは、CharaSet ゲームオブジェクトの子オブジェクトとして配置する前提で設計されているためです。

 Rigidbody コンポーネントは、親オブジェクトにアタッチされていると、親オブジェクトと、その子オブジェクトすべてに対して衝突判定が有効になります
つまり、物理演算自体はおこないませんが、衝突判定は利用できる状態が発生します。

 この情報を正確に理解していることが、今回の親子関係のポイントです。

 親オブジェクトに CharaSet ゲームオブジェクト、子オブジェクトに OrbitingBullet ゲームオブジェクトを配置します。
このとき、親オブジェクトには Rigidbody コンポーネントがすでにアタッチされています。
よって、OrbitingBullet ゲームオブジェクトのコライダーの衝突判定も有効になります。

 このような親子関係になることを前提に、OrbitingBullet ゲームオブジェクトには Rigidbody コンポーネントをアタッチしていません。
ゲームオブジェクトを設計する段階から、どういったケースが想定されるかを考えておくことで、衝突判定を上手く表現できます。

 例えば、敵側のスクリプト内に OnTriggerEnter メソッド書かれている場合、OrbitingBullet ゲームオブジェクトのコライダーに反応するようになります。

 これにより、プレイヤーキャラクターと周囲の環境との相互作用をスムーズに行うことができます。



 以上のように、親子関係を活用した衝突判定のテクニックは、ゲーム開発において非常に有用です。
親オブジェクトと子オブジェクトの関係性を理解し、適切に設定することで、キャラクターやオブジェクトの相互作用を効果的に実現できます。

 親子関係を利用すると、コライダーの回転角度の設定を別々に作ることもできますが、
それと合わせてこの衝突判定の機能も今後活用できるテクニックですので、この機会に覚えておきましょう。

 今回の知識を活かしてさまざまなシーンで親子関係を活用してみてください。



 以上で完成です。

 続いては応用編です。公転する弾があるとき、ボタンを押したら公転する弾をプレイヤーの向いている方向に投射する機能を学習します。

   => 【2D】プレイヤーを軸にして公転する弾の機能

コメントをかく


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

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

Menu



技術/知識(実装例)

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

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

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

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

レースゲーム(抜粋)

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

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

3D脱出ゲーム(抜粋)

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

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

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

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

VideoPlayer イベント連動の実装例

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

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

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

private



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

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