Unityで弾が当たったゲームオブジェクトの周りにも力を加える

以前の記事で銃から物理的な弾を飛ばす機能を作成しました。

Unityのアクションゲームで物理的な弾を飛ばして敵との当たり判定をする
Unityのガンシューティングゲームなどで銃から弾を飛ばす場合にスクリプトで敵と接触したか判断するのではなく、物理的な弾を飛ばしその弾が当たったかどうかで判断させます

物理的な弾を他の物理的なゲームオブジェクトに衝突させた場合、

周りに力を加えないサンプル

↑のように個別のゲームオブジェクトとそれに接触している物体に力が加わりますが、その周りのゲームオブジェクトには影響を与えません。

今回の記事ではさきほど紹介した記事のように銃から物理的な弾を飛ばし、弾がゲームオブジェクトに当たった時に周りのゲームオブジェクトにも力を加えるようにしたいと思います。

例えば手榴弾を投げた時に爆発でその周りの敵にも力を加えて飛ばすという時に使用します。

スポンサーリンク

的になるブロックを配置する

まずはゲームオブジェクトを作成していきます。

ヒエラルキーで右クリック→Create Emptyを選択し、名前をCubeFolderとします。
その子要素に右クリック→3D Object→Cubeを作成します。

また新しくTagを作成し名前をBlockとします。

Tagの作成方法はゲームオブジェクトのインスペクタ名の下にあるTagの部分をクリックし、Add Tagで追加する事が出来ます。

追加したらTagをBlockに設定します。

Cubeを作成したらAdd Component→RigidbodyをしてRigidbodyを追加します。

物理的な力を加えたい場合はRigidbodyが取り付けられている必要があります。

CubeにRigidbodyを付けたインスペクタ

↑がCubeのインスペクタになります。

ここまで出来たらCubeをCtrl+Dで複製し、少しづつ位置をずらして設置します。

Cubeを並べて配置した画像

↑のように横に4列とその上に4列並べました。

また通常のCharacterControllerで動くキャラクターも一人配置しておきました。

キャラクターのTagにはEnemyを設定してください、ない場合は追加して設定してください。

今回はサンプルなのでキャラクターにはCharacterControllerを取りつけ、コライダの調整が済ませておきます。

特別なスクリプトやAnimatorの設定等はしていません。

さきほどCubeにはRigidbodyコンポーネントを追加しましたが、キャラクターには追加しません。

キャラクターにはスクリプトからRigidbodyを追加するようにしてみます。

Rigidbodyについて

さて、ここで少しRigidbodyについて触れておきます。

rigidbodyコンポーネントについて

Massは物体の質量です。

わたくしはあまりRigidbodyを使わないので常にデフォルトの1のまま使っていますが、質量を考えた処理をしたい場合、このMassの値を変更する必要があります。

Dragは空気抵抗です。

Angular Dragは力が加えられた時の回転の空気抵抗です。力によって回転が起きた時にこの値を大きくしておくと回転がすぐに止まります。

Use Gravityは重力を働かせるかどうかです。Rigidbodyが取りつけられたゲームオブジェクトはこのチェックを入れると重力が勝手に働いてくれる為スクリプトで重力値を計算する必要がありません。

Is KinematicはスクリプトでRigidbodyを操作したい時にチェックを入れるのだと思う・・・(^_^;)

ここにチェックを入れると物理的な処理がされません。

Interpolateは動きの補間についての設定です。

Collision Detectionは高速に移動するゲームオブジェクトの衝突でゲームオブジェクト同士が食い込んでしまう、すり抜けてしまうといった場合に設定します。

問題が出ない時は特に設定しなくていいかも?

ConstraintsはRigidbodyを設定したゲームオブジェクトの位置の移動や回転をさせるかどうかの設定です。

キャラクターをRigidbodyで動かす場合FreezePositionのYとFreezeRotationのX、Zはチェックを入れた方がいいかもしれません。

ただし、外部からの力でキャラクターを飛ばしたい場合位置の移動や回転をしない設定にしていると飛ばないので、
力を加える時にこれらの設定を変更するというやり方が必要になると思います。

Rigidbodyの項目については詳しく見るつもりはなかったんですが・・・(^_^;)
まぁ・・・自分の勉強になっていいかも(^。^)

それでは、さきほど作った最初のCubeだけMassを100に設定してください。

あとで力を加えた時に他とどう変わるかがわかります。

飛ばす弾が何かに当たった時の処理BulletAttackスクリプトを作成

次に物理的な弾がCubeやキャラクターに当たった時に力を加えるスクリプトBulletAttackを記述していきましょう。

↑のようにインスペクタで設定出来る変数を宣言します。
ForceModeは力の加え方で

Forceは質量を使用して力を加えます。
Accelerationは質量の事は考えず加速度を加えます。
Impulseは質量を使用して力を加えます。Impulseは爆発等をシミュレートする時に使用し飛び散る感じの力が加わります。
VelocityChangeは質量を無視して加速度を加えるImpulseという感じです。

細かい所はわからないので実際に試して確認するしかないですね・・・(^_^;)

Physics.OverlapSphereは中心位置と半径を指定して、その球の範囲にあるコライダを取得します。

transform.positionは弾の位置でそこを中心に半径radiusで仮想の球を作りその範囲内にあるコライダを探します。

最初に拡張for文を使っていますが、通常のfor文で書いても構いません。

拡張for文では配列等の複数の値を持つ変数を一時変数に代入し使用します。配列の最後まで来たら終了になります。

今回の場合はcollidersがある限り、一時変数であるcolliderに値を代入して繰り返しています。

衝突したゲームオブジェクトのタグがBlockの時はそのコライダのゲームオブジェクトに取りつけてあるRigidbodyを取得しAddExplosionForceで力を与えます。

AddExplosionForceは

AddExplosionForce(加える力, 中心位置, 半径, 物体を持ち上げた時の調整値?, 力の加え方);

です。

第4引数がいまいちわかりません・・・・。

衝突したゲームオブジェクトのタグがEnemyだった時はCapsuleColliderとRigidbodyを取りつけます。

// CharacterControllerを無効化、または消してしまう
collider.gameObject.GetComponent.<CharacterController>().enabled = false;
// Destroy(collider.gameObject.GetComponent.<CharacterController>());

↑のようにキャラクターに取りつけてあるCharacterControllerを無効化するか消してしまいます。

飛んだ後にまたCharacterControllerの機能を使いたい場合は無効化にしておいた方がいいですね。

スクリプトでコンポーネントを取りつけるには

ゲームオブジェクト.AddComponent.<取りつけるコンポーネント>()

を使います。

今回はキャラクターはくるくる回るだけにしたいので位置はY座標を固定、回転はX座標とZ座標を固定させます。

rigidbody.constraints = RigidbodyConstraints.FreezePositionY | RigidbodyConstraints.FreezeRotationX| RigidbodyConstraints.FreezeRotationZ;

RigidbodyのConstraintsの設定はそれぞれの項目をtrueやfalseで設定するのではなくビット演算で行うようです。

今回の場合はRigidbodyのConstraintsのFreezePositionYとFreezeRotationX、FreezeRotationZにチェックを入れたい為に
論理和を計算しています。

これでスクリプトが完成しました。

弾であるBulletにBulletAttackスクリプトを取りつけ、

BulletAttackインスペクタの設定値

↑のようにインスペクタでpower、radius、modeを設定してください。

ブロックやキャラクターに弾を当てて機能が完成しているか確認

Unityの実行ボタンを押して、Cubeやキャラクターに弾を当ててみましょう。

ForceModeをForceにして実行

↑が実行結果です。

どれかのブロックに弾を当てると他のブロックやキャラクターにも力が加わっているのがわかります。

キャラクターにはRigidbodyが取り付けられ位置や回転が固定されている為クルクル回る感じになります。

他のブロックと同じように飛ばしたい場合はRigidbodyのConstraintsの設定を削除してください。

左下がRigidbodyのMassを100にしたCubeです。
どれだけ弾を当てても動きが鈍いですね。

BulletAttackのスクリプトでConstraintsの設定部分をコメント化し、インスペクタでmodeをImpulseにして確認してみましょう。

ForceModeをImpulseにして爆発を確認する

↑のように爆発する感じになりました。

キャラクターはあまり飛ばなかったですね・・・・。

今回のようにキャラクターにCapsuleColliderやRigidbodyをスクリプトから取りつけCharacterControllerを無効化したのはサンプルの為で、
すぐにゲームのキャラクターに使える!という感じにはなっていません。

キャラクターを飛ばした後に再度普通に動く敵キャラに戻すにはいろいろやる事がありそうです。

キャラクターをRigidbodyとCapsuleColliderで動かしている場合はそもそもスクリプトからコンポーネントを取りつける必要もありませんし、CharacterControllerの無効化も必要ありません。

CharacterControllerを使ってキャラクターを動かしている場合はRigidbodyを取り付けてないので物理的な力を加える時は必要になります。

今回の内容はFPSゲーム等の手榴弾の爆発とかそういった場面で活躍しそうですね。

さきほど言及した敵キャラの面倒くさそうな処理をしたくない場合は爆発で一発でやられるようにしておくのがいいかもしれません。(^_^;)

今回の記事の作成にはUnityのライブトレーニング

Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web...

を参考にさせて頂きました。