Unityでキャラクターが乗ったらシーソーする床を作成する

今回はキャラクターが乗ったらシーソーする床を作成してみます。

CharacterControllerコンポーネントでキャラクターを操作している場合はそのままでは物理的な影響を受けない代わりに影響を与える事も出来ません。

また相手方でOnTriggerEnterやOnCollisionEnter等でキャラクターを検知する事も出来ません(IsTriggerにチェックが入っている場合OnTriggerEnterは使えます)。

しかし、CharacterControllerでは他のコライダと接触している時にOnControllerColliderHitという関数が呼ばれるのでそれを使って他のコライダに力を加える事が出来ます。

今回はOnControllerColliderHitを使い床を検知して床に力を加え、床がシーソーするようにしていきます。

スポンサーリンク

シーソーする床を作成する

まずはシーソーする床を作成します。

床は

UnityのPhysic Materialを使って衝突や跳ね返りを設定する
UnityのPhysic Materialを使って衝突や跳ね返りを設定します。衝突したらそのまま勢いを無くしたり、スーパーボールのように反発して跳ね返るというような処理を作りたい時にPhysic Materialは便利です。

で作った物とほぼ同じですが、物理的な影響を与える為Rigidbodyを追加しています。

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

シーソーする床のインスペクタ

↑のようにAdd Component→Physic→Rigidbodyを追加し、ConstraintsのFreeze RotationZ以外をすべてチェックします。

これでゲームオブジェクトは位置が変わらずZ軸を基点に回転するだけになります。

ゲームオブジェクトの向きによってFreeze Rotationのチェックする位置が変わりますので、ご自分の環境に合わせて変更してください。

Use Gravityのチェックはしてもしなくても構いません(Freeze Positionにチェックを入れている為位置は変わらない)。

床には力を加えるのでIs Kinematicのチェックは外しておきます。

また床がシーソーした後に回転の空気抵抗を与える為にAngular Dragに1を設定しています。

この値を大きくすると抵抗が強くなる為に回転が早く止まるようになります。
あまり大きくしすぎると力がかかっていないように見えます。

FrictionCube1にはBlockタグ、Blockレイヤーを設定してください。
Blockタグ、レイヤーがない場合は作成し設定するようにしてください。

作成したシーソーする床

↑のような感じでシーソーする床が出来上がりました。

キャラクターが床に乗った時に下向きに力を加える

後はキャラクターがこの床に乗った時に下向きに力を加えればいい事になります。

キャラクターが床に力を加えるスクリプトAddForceOtherObjectスクリプトを作成します。

private var onSeeSaw : boolean = false; // シーソー床に乗っているかどうか
private var seeSawObject : GameObject; // シーソーする床オブジェクト
public var rayPosition : Transform; // レイを飛ばす位置
public var power : float = 20; // 床に与える力

onSeeSawは床に乗っているかどうかの判定をし、seeSawObjectは床に乗っている時のその床オブジェクトを参照する変数です。

キャラクターが床に乗っているのではなくただ接触している時(シーソーの横に接触している時)は力を加えないようにする為、

キャラクターの体の一部から下向きにレイを飛ばして床があるかどうかを判定します。

その時にレイを飛ばす位置をrayPositionに設定します。

powerはそのまま床に加える力になります。

キャラクターが他のコライダと接触していたらOnControllerColliderHit関数が呼ばれるので、接触しているコライダのゲームオブジェクトにBlockタグが設定されていたら、

キャラクターの体からレイを下に1m飛ばし、接触しているのがBlockレイヤーが設定されているゲームオブジェクトならば力を加えます。

接触した相手のゲームオブジェクトをseeSawObjectに入れ、onSeeSawにtrueを入れます。

力を加える時はUpdate関数よりFixedUpdate関数内で行った方がいい為、実際に力を加えているのはFixedUpdate関数内になります。

seeSawObject.GetComponent.<Rigidbody>().AddForceAtPosition(Vector3.down * power, transform.position);

シーソーする床のゲームオブジェクトに設定しているRigidbodyを取得し、AddForceAtPositionでキャラクターの位置から下向きに力を加えています。

AddForceはゲームオブジェクト自体に力を加える事が出来ますが、今回の場合ゲームオブジェクトのある一点に力を加える必要があります。

AddForceはゲームオブジェクト全体、AddForceAtPositionはゲームオブジェクトの一定の位置に力を加えます。

その為AddForceAtPositionを使い、キャラクターがいる位置から下に力を加えることによって床がシーソーするようにします。

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

床がシーソーするか確認する

キャラクターにAddForceOtherObjectスクリプトを取りつけて、

rayPositionにキャラクターのボーンの一部を設定してください。
キャラクターにEthanを使用している場合はEthanHipsを指定します。

それではUnityの実行ボタンを押して確認してみましょう。

キャラクターが乗った時に床がシーソーするか確認する

↑のようにキャラクターがシーソー床に乗った時にその位置から下に力が働くようになりました。

動画を見るとわかりますが、CharacterControllerを使用している為シーソー床の下からジャンプしても床を突き抜け床の上に飛び乗る事が出来てしまいます。

これが嫌な方はRigidbody+コライダで移動するキャラクターを使った方がいいかもしれませんね。

これでUnityでキャラクターが乗ったらシーソーする床の作成が出来ました。

床がシーソーするステージを飛んで移動するようなアクションゲームとか面白そうですね!

最近段々とRigidbody+コライダで動かすキャラクターの方がいいんじゃないかと思えてきました・・・(^_^;)

CharacterControllerをRigidbody+Capsuleコライダを使ったキャラクターの移動方法は

キャラ操作をCharacterControllerからRigidbody+コライダに変更する
Unityでキャラクターを操作する時CharacterControllerを使ってきましたが、物理的な影響を得る為にRigidbody+CapsuleColliderでキャラクターの移動、ジャンプ、坂や段差を登れるようにしてみます。

を参照してください。