「Parent Constraint」コンポーネントを使って、右手に持っている武器を左手に持ち替えてみました。
アニメーションを作る
まず、Blenderでバットを左手から右手に持ち替えるアニメーションを作りました。バットは右手のボーンの子にしています。
インポート設定
このメッシュとアニメーションをFBX形式でUnityにインポートしました。インポート設定のAnimationタブで、今作ったアニメーションを選択して、プレビューでバットを持ち替える瞬間にシークバーを合わせます。
すると、Eventsセクションのシークバーも同じ位置に移動するので、Add Eventボタンをクリックしてイベントを追加し、「Function」に適当なメソッド名を入れて「Apply」で適用します。
キャラクターをシーンに配置する
インポートしたときにバットは右手のボーンの子でしたが、FBXファイルをシーンに置いてアンパックしてから、バットのペアレントを解除しました。バットの位置は移動しないようにします。
キャラクターにはアニメーターコンポーネントを付けて、新しいアニメーターコントローラーをアタッチします。
アニメーターコントローラーには、上のアニメーションをドラッグアンドドロップしてデフォルトステートを作りました。
バットにコンストレイントコンポーネントを付ける
バットのオブジェクトに、「Parent Constraint」コンポーネントを追加しました。
+ボタンを2回押して、ソースゲームオブジェクトを2つ設定します。1つ目には右手のボーン、2つ目には左手のボーンをドラッグアンドドロップします。
各ソースゲームオブジェクトには、個別にウェイトを設定できます。デフォルトで、右手は1、左手は0にしておきます。Activateボタンを押して有効化します。
スクリプトを付ける
キャラクターにスクリプトを付けて、持ち替えるタイミングでコンストレイントのウェイトを変更します。
using UnityEngine;
using UnityEngine.Animations;
public class ConstraintTest : MonoBehaviour
{
[SerializeField] ParentConstraint bat;
Animator animator;
[SerializeField] Vector3 positionOffsetAtLeft;
Vector3 defaultOffset;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
defaultOffset = bat.GetTranslationOffset(1);
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0))
{
// 1つ目のソースを取得(右手)
var right = bat.GetSource(0);
// ウェイトを1にする
right.weight = 1f;
// 1つ目のソースを設定
bat.SetSource(0, right);
// 2つ目のソースを取得(左手)
var left = bat.GetSource(1);
// ウェイトを0にする
left.weight = 0f;
// 2つ目のソースを設定
bat.SetSource(1, left);
// ステートを指定して再生
animator.Play("Default",0,0);
}
}
void Pass()
{
// 右手のウェイトを0、左手を1にする
var right = bat.GetSource(0);
right.weight = 0f;
bat.SetSource(0, right);
var left = bat.GetSource(1);
left.weight = 1f;
bat.SetSource(1, left);
// 左手での位置を調整
var offset = defaultOffset + positionOffsetAtLeft;
bat.SetTranslationOffset(1, offset);
}
}
Eventsセクションで設定したものと同名のメソッドを作ると、イベントによって呼ばれるので、ここでウェイトを変えてバットを持ち替えます。
コンストレイントコンポーネントでは、各ソースゲームオブジェクトからの影響をウェイトで変えられるので、ウェイトを0にすると、そのゲームオブジェクトとの関連を切ることができます。
そこで、はじめに左手のウェイトを1、右手を0にしてバットが左手だけについていくようにしておき、バットを持ち替えるときは値を逆にします。
しかし、ウェイトを変えるだけでは、持ち替えたときにバットの位置がずれてしまいました。
そこで、スクリプトで位置を調整できるようにしました。