今回は Rigidbody と Hinge Joint コンポーネントを組み合わせ、オブジェクトをマウスクリックで叩くサンドバッグのようなものを作ってみました。
Hinge Joint コンポーネントとは?
まずはマニュアルで Hinge Joint コンポーネントについて調べてみます。
Hinge Joint は、2 つの リジッドボディ をグループ化し、互いにヒンジで連結されているかのように動くよう制約します。ドアに最適ですが、鎖や振り子などをモデル化するのにも使用できます。
シーンの作成
新しいシーンに Sphere オブジェクトを垂直に3つ並べて配置。それぞれに Hinge Joint コンポーネントをアタッチ。自動的に Rigidbody コンポーネントも追加されます。

さらに Empty オブジェクトを作成して名前を Hanger に変更。このオブジェクトにもHinge Joint コンポーネントをアタッチ。このオブジェクトを親にして先ほど作成した Sphere オブジェクトを子階層にします。

オブジェクト Hanger と一番上の Sphere オブジェクトは0.5 離しています。

Hinge Joint コンポーネントの設定
[Inspector]ウィンドウ > Hinge Joint > Connected Body フィールドには親の階層のオブジェクトをドラッグ&ドロップで登録します。それぞれのオブジェクトの Connected Body フィールドはこのようになります。オブジェクト:Hanger
オブジェクト:上のSphere

オブジェクト:真ん中のSphere (1)

オブジェクト:下のSphere (2)

ゲームを再生してから一番下のオブジェクト Sphere (2) を選択し、[Inspector]ウィンドウ > Transform の Z 値を変更するとオブジェクト階層全体が揺れて Hinge Joint コンポーネントの動きを確認できます。

スクリプトの作成
マウスクリックでオブジェクトに力を加える処理を考えます。
- カメラ座標からマウスクリック座標に向けてレイキャスト
- レイキャストにヒットしたコライダーのRigidbody にAddForce で力を加える
- レイキャストにコライダーがヒットしたらオーディオクリップを再生
- レイキャストにコライダーがヒットした位置にパーティクルを発生
作成したスクリプト Punch のコードはこのようになりました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Punch : MonoBehaviour
{
// Rigidbody コンポーネントに加える力を格納する変数
public float hitForce;
// マウスクリックのインターバル時間を格納する変数
public float timeInterval;
// マウスクリックのインターバル時間のタイマーを格納する変数
private float timer;
// レイキャストヒットで再生する AudioSource コンポーネントを格納する変数
public AudioSource audioSource;
// レイキャストヒットで発生させるパーティクルコンポーネントを格納する変数
public ParticleSystem hitEffect;
// ゲーム実行中に毎フレーム実行する処理
void Update()
{
// タイマーカウント処理
timer += Time.deltaTime;
// マウス左クリック入力があれば
// かつインターバル時間のタイマー変数 timer がインターバル時間の変数 timeInterval より大きければ
if (Input.GetMouseButtonDown(0) && (timer > timeInterval))
{
// レイキャストによる情報を得るための構造体 hit を作成
RaycastHit hit;
// カメラからマウスカーソル座標までレイキャストしたベクトルを ray に格納
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// レイキャストにヒットしたコライダーがあれば
if (Physics.Raycast(ray, out hit))
{
// レイキャストにヒットしたオブジェクトに Rigidbody コンポーネントがあれば
if (hit.rigidbody != null)
{
// レイキャストにヒットした位置の Rigidbody コンポーネントに力を加える
hit.rigidbody.AddForce(ray.direction * hitForce, ForceMode.Impulse);
// AudioSource からオーディオクリップを再生する
audioSource.Play();
// 変数 hit の座標を パーティクルコンポーネントの座標に渡す
hitEffect.transform.position = hit.point;
// パーティクルを発生させる
hitEffect.Play();
}
}
// インターバル時間のカウントをリセット。
timer = 0f;
}
}
}
シーンに Empty オブジェクトを作成して名前を HitPoint に変更。作成したスクリプト Punch をアタッチ。[Inspector]ウィンドウでこのように表示されます。

AudioSource と Particle コンポーネントの追加
オブジェクト HitPoint に AudioSource と Particle コンポーネントを追加。スクリプト Punch (Script)コンポーネントの それぞれのフィールドにドラッグ&ドロップで割り当てます。

オーディオクリップの追加
オブジェクト HitPoint に 追加した AudioSource コンポーネントに再生するオーディオクリップを割り当てます。Unity アセットストアでパンチの効果音の無料アセットがみつからなかったので、今回はフリーの音声ファイルポータルサイト Freesound からお借りしました。

今回使用したオーディオクリップはこちら。
オーディオクリップの加工
ダウンロードしたファイルは前後に無音部分があるのでトリミングします。今回はWebブラウザで音声ファイルの編集ができるサービス Bearオーディオオンラインツール を使用しました。

トリミング後にファイルをダウンロード。Unityの[Project]ウィンドウにドラッグ&ドロップでインポート。そして、
オブジェクト HitPoint の AudioSource コンポーネントの Audio Clip フィールドにドラッグ&ドロップで割り当て。Play On Awake のチェックボックスは外します。

パーティクルコンポーネントの設定
パーティクルコンポーネントのパラメータを色々触っていたら丁度マンガのスピード線のような効果ができました。

スクリプト Punch コンポーネントの設定
マウスクリックで叩く力の強さとマウスクリックのインターバル時間を設定します。[Inspector]ウィンドウ > Punch (Script) コンポーネント > Hit Force と Time Interval の値をこのように設定しました。

Hinge Joint コンポーネントの アンカーの向きの調整
マウスクリックで叩いたときにオブジェクト全体が前後左右に揺れるように、親オブジェクトの Hunger の Hinge Joint コンポーネントの アンカーをZ軸に回転するように変更。Hunger と子オブジェクトSphere の Hinge Joint コンポーネントの アンカーを同じ位置に調整しました。

WebGL
今回の内容をWebGLでビルドしてみました。画像クリックでファイルがダウンロード、再生されます。マウスクリックでパンチ。画面右下のスライダーでボリューム調整できます。(ダウンロードサイズ:約7MB)
コメント
[…] Rigidbody と Hinge Joint を組み合わせてマウスクリックで叩いて揺らす | COREVALE […]