UnityのJoint機能を使って敵にゲームオブジェクトが付くようにする

記事内に広告が含まれています。

今回はUnityのJoint機能を使ってゲーム内の敵にゲームオブジェクトが付くようにしたいと思います。

具体的には動いている敵に主人公がヤリを投げて敵に当たったら敵にヤリがささったままになるようにしたいと思います。

この機能を作成するにはヤリが敵に当たった時にヤリを敵キャラクターのボーンの子要素にするという方法もありますが、

今回はUnityのジョイント機能を使ってヤリを敵に付くようにしたいと思います。

Joint機能でくっつくようにすれば外部から力を加えた時に自然に取れるようにすることも出来ます。

ジョイント機能を使うにはヤリにJointコンポーネント、敵にRigidbodyが取り付けられている必要があります。

Jointコンポーネントは用途に応じていくつかの種類がありますが、今回は一番シンプルなFixedJointコンポーネントを使用します。

スポンサーリンク

主人公が飛ばすヤリを作成する

まずは主人公が飛ばすヤリを作成していきましょう。

今回はUnityの3D ObjectのCubeで疑似的なヤリを作成します。

ヒエラルキー上で右クリック→3D Object→Cubeを選択し、名前をSpearとします。

Spearのインスペクタの設定

SpearのScaleを調整しヤリっぽい形にします。

Box ColliderのIs Triggerのチェックが入っていますが、これは後でスクリプトから操作できるようにする為、
現時点では無視してください。

Add Componentを押してPhysics→Rigidbodyを取りつけます。

Use Gravityにチェックを入れヤリに重力が働くようにします。

Collision DetectionをContinuous Dynamicにし、速い移動で他のゲームオブジェクトをすり抜けないようにします。

ヤリが敵と接触した時の処理を行うCollisionEnemyを作成する

Collision Enemyという新しいスクリプトを作成し取りつけます。

↑のようにCollisionとTriggerのモード状態を作成し、ヤリを他のオブジェクトと衝突させるか、侵入だけを行うかを指定出来るようにします。

モードをインスペクタで設定できるようにし、それによってコライダのIs Triggerの設定を変更するようにします。

CollisionであればIs Triggerのチェックを外し、TriggerであればIs Triggerのチェックを入れます。

衝突ありとなしはほぼ同じ処理なので衝突ありの処理だけ見ていきます。

衝突ありの場合ですでにヤリが敵に刺さっていない状態であればJudgeEnemyメソッドにコライダを引数として渡し呼び出します。

JudgeEnemyメソッドはコライダを引数として受け取るメソッドで、

衝突した相手がEnemyタグを持つゲームオブジェクトだった時にヤリにfixedJointが設定されていなければ
FixedJointコンポーネントをヤリに取りつけます。

そのあとconnectedBodyに衝突した敵のRigidbodyを設定します。

Joint系のコンポーネントはconnectedBodyに相手方のRigidbodyを設定すると相手方に付くようになります。

このくっついている状態を解除する為に設定するのが

breakForce(力)とbreakTorque(回転)です。

今回のスクリプトではインスペクタでこれらの値を設定することが出来ます。

インスペクタでInfinityと設定すればどんだけ力や回転が加わってもヤリが敵から外れることはありません。

また、スクリプトでInfinityを設定したい時は

Mathf.Infinity

と設定します。

インスペクタでは

Infinity

と書きます。

またヤリが敵以外と衝突した時にfixedJointがヤリに取り付けられていない、つまりヤリを投げたけど敵じゃない他のゲームオブジェクトに接触した時は
ヤリを削除しています。

ヤリが敵に付いている時はfixedJointがnullではないはずなのでここで削除はされません。

敵にヤリが当たった時は与えていた力を無効化したいのでRigidbodyのvelocityを0にし、Sleepメソッドを呼び出してスリープ状態にします。

これでヤリのゲームオブジェクトの作成が終わったので、ゲームオブジェクトをAssetsフォルダにドラッグ&ドロップしてプレハブ化しておきます。

ヒエラルキー上のSpearは削除するか非表示にしておいてください。

主人公がヤリを投げる場所を作成する

次に主人公キャラがヤリを出現させる場所を作成しましょう。

ヤリを出現させる場所

↑のように主人公キャラクターの子要素にCreate Emptyで空オブジェクトを作成しSpearPointという名前にします。

Localにして、SpearPointの青矢印が前方を向くように調整します。

ヤリを出現させる場所の位置

↑のように主人公より少し前の位置からヤリを出現させるようにします。

SpearPointのインスペクタ

キャラクターにはThrowSpearという新しいスクリプトを作り取りつけます。

spearを宣言しインスペクタでヤリのプレハブを設定します。

キーボードのTキーが押されたらヤリオブジェクトをSpearPointの位置と角度の場所に生成し、
ヤリオブジェクトのRigidbodyを取得しヤリが向いている方向に力を加えます。

敵キャラクターの作成

次に敵キャラクターを作成します。

敵キャラクターのAnimatorにはIdle(ただ立っている状態)とWalk(歩いている状態)を作り、アニメーションパラメータのSpeedが0.1以上になったらWalk状態に遷移するようにしてあります。

敵のインスペクタの設定

↑が敵キャラクターのインスペクタです。

Rigidbodyを取りつけIs Kinematicにチェックを入れます。

敵キャラクターはCharacterControllerの機能を使って動かしますので、CharacterControllerを取りつけてコライダのサイズを調整してください。

敵キャラクターを移動させるスクリプトJointZombieControllerは以下のようになります。

敵キャラクターの移動に関しては割愛しますが、移動するポイントをいくつか設定しておきその場所を巡回するように移動します。

これでJointZombieControllerの作成が完了したので、さきほどの画像を参考にインスペクタで巡回する位置と敵キャラクターのスピードを設定してください。

敵にヤリが付くかどうか確認する

機能が完成したので主人公キャラクターを動かしてTキーを押してヤリを前方に飛ばし敵に当ててみましょう。

今回のサンプルではヤリのCollisionEnemyスクリプトのmodeをCollisionにしておこなってみました。

ヤリが敵に刺さるか確認するサンプル

↑のように敵にヤリが刺さりましたが、主人公と接触するとヤリが消えたり、ヤリは他のゲームオブジェクトと衝突判定がされる為か敵キャラクターが変な方向に移動してしまっています。

ヤリの登場位置を調整する

ヤリの登場位置SpearPointは主人公よりだいぶ前に設置していました。

これはヤリの中心位置がSpearPointの位置になっている為、主人公の体の近くにするとヤリの中心が主人公の辺りになり主人公を突き抜けて半分の位置で登場するからです。

そこでヤリを少し変更してSpearPointの位置を主人公の体の辺りにしても大丈夫なようにしましょう。

Spearの子要素に空オブジェクトを作成

↑のようにSpearの子要素に空オブジェクトを作成します。

空オブジェクトをドラッグし親子関係を解除

空オブジェクトをドラッグし親子関係を解除し↑のようにします。

GameObjectの位置をSpearの原点に移動

空オブジェクトを移動させSpearの原点に移動させます。

Spearを空オブジェクトの子要素にする

最後にSpearを空オブジェクトの子要素にします。
空オブジェクトGameObjectをProjectタブのAssetsフォルダにドラッグ&ドロップしプレハブ化します。

SpearPointに設定しているThrowSphearのSpearにさきほど作成したGameObjectをドラッグ&ドロップします。

子要素のSpearにはBox Collider、Rigidbody、CollisionEnemyスクリプト等が設定されています。

親のGameObjectには新たにRigidbodyを取り付けます。

Rigidbodyの設定は子要素のSpearと同じ設定にします。

あとはキャラクターのSpearPointの位置をキャラクターの近くに寄せるだけでOKですが、スクリプトで接触した相手がEnemy以外のタグだった時に
ヤリを削除しているので、スクリプトにPlayer以外の時という条件を加えるか、SpearPointをキャラクターと接触しない程度の位置にしておく必要があります。

スクリプトを変更するならCollisionEnemyスクリプトのJudgeEnemyメソッドで、

↑のように修正します。

終わりに

CollisionEnemyのmodeをCollisionにするとBreak ForceとBreak TorqueをInfinityにしないとくっつかないですね・・・・。

ちなみにJointコンポーネントはbreakForceやbreakTorque以上の力が加えられて外れた時はコンポーネント自体が削除されますので、

自分でコンポーネントを削除する必要はありません。

タイトルとURLをコピーしました