バケツを左クリックすると中に入って隠れます。隠れている間、蓋を少し開けて隙間から外を見れるようにします。
一人称視点でロッカーの中に入って隠れるのと同じ方法で、バケツの方を向くようにFPSコントローラーを移動させて、蓋を開け締めしたりプレイヤーが中に入るアニメーションを再生します。
ロッカーのときと違って今回はプレイヤーが中に入ると、バケツの中心に来るようにワープさせます。その後、もう一度左クリックするとアニメーションを使って外に出ます。
まずFPSコントローラーのUpdateでレイキャストを投げて、タグでバケツを見分けて手の画像を表示します。
// FirstPersonController
// Update()
// レイキャスト
//...
else if (hitTag == "Bucket")
{
hand.SetActive(true); // 手のマークを出す
if (Input.GetMouseButtonDown(0))
{
hitTransform = hit.transform;
hitTransform = hitTransform.parent ? hitTransform.root : hitTransform;
hitAnimator = hitTransform.GetComponent();
hitAnimator.SetBool("Open", true); // バケツを開けるアニメーション
hitObj = hitTransform.gameObject;
AudioManager.PlayWashingMachineSound(hitObj, 0); // バケツを開ける音
state = 5; // アニメーション状態にする
Quaternion warpQ; // ワープする回転値
// ワープする位置
Vector3 warpP = GetBucketWarpPosition(hitTransform, transform, 210, 2.5f, out warpQ);
Warp(warpP, warpQ, false); // バケツの前へワープ
hand.SetActive(false); // 手のマークを消す
}
}
そこで左クリックするとバケツのトランスフォームを調べます。バケツは蓋との間にピボットが付いていて、これを支点に蓋が開きます。アニメーターコンポーネントはルートのバケツに付いています。


なので、ヒットしたトランスフォームに親オブジェクトがあれば、ルートのオブジェクトのトランスフォームを使うようにします。
hitTransform = hit.transform;
hitTransform = hitTransform.parent ? hitTransform.root : hitTransform;
バケツが開くアニメーションと音を再生して、プレイヤーの状態を変えた後に、ワープする位置と回転を調べます。
位置は、バケツのTransform.forwardを中心に角度の範囲を設定して、プレイヤーがその内側にいれば、設定した距離まで近づいた位置、外側なら範囲の境界に設定します。これは角度の範囲を指定して円周上に配置するの赤いCubeと同じ位置です。
回転値は、プレイヤーの今の回転と、設定した位置に来たときにそこからバケツをまっすぐ見るための回転を足したものをQuaternion.FromToRotationを使って計算します。
バケツを真後ろからクリックしても、プレイヤーはバケツの横に移動して、バケツの方をまっすぐ向きます。バケツを回転させても問題ありません。


ワープが終わると、プレイヤーを乗せたオブジェクトをアニメーションさせてバケツの中に移動させます。


アニメーションが終わると、蓋が閉まるアニメーションを開始して、念の為、プレイヤーをバケツの中央にワープさせています。それが終わると、MouseLookクラスに新しく作ったメソッドを呼びます。
m_MouseLook.ChangeLimite(true, m_Camera.transform.rotation, 50,-20,105,-105); // 回転制限
FPSコントローラーの頭には元々上下の回転に制限がかかっていますが、デフォルトの値を別の変数に保存しておいてこの制限を変更します。
また、第一引数がtrueなら、FPSキャラの回転を制限すると同じ方法で水平な方向にも制限がかかるようにします。そのときに使う、現在のカメラの回転値も渡しています。
制限がかかるときには、プレイヤーはバケツと同じ方向を向いていて、ここを中心に回転に制限がかかります。蓋のピボットがバケツの正面の反対側に付いているので、回転の制限の中心は蓋を少し開けたときに最も隙間が空いているところと同じです。そこから隙間が細くなって見にくくなるくらいまでの範囲を見回すことができます。
バケツから少しのぞくには、バケツに入っているときに右クリックを押して、バケツのアニメーションで蓋を少し開きつつ、プレイヤーの頭を少し上にアニメーションで動かします。
// FirstPersonController
// Update()
// ...
// バケツに隠れている状態
else if (state == 6)
{
// バケツから出る
if (Input.GetMouseButtonDown(0)) // 左クリックを押した時
{
pivotAnimator.SetBool("Peep", false); // プレイヤーの頭のアニメーションをオフ
PlayMotion(true, 0, 3); // プレイヤーのアニメーション
hitAnimator.SetBool("Open", true); // バケツを開けるアニメーション
hitAnimator.SetBool("Peep", false); // バケツを少し開けるアニメーションをオフ
}
else if (Input.GetMouseButtonDown(1)) // 右クリックを押した時
{
hitAnimator.SetBool("Peep", true); // 蓋を少し開ける
pivotAnimator.SetBool("Peep", true); // プレイヤーの頭を持ち上げる
}
else if (Input.GetMouseButtonUp(1)) // 右クリックを話した時
{
hitAnimator.SetBool("Peep", false); // 蓋をそっと閉める
pivotAnimator.SetBool("Peep", false); // プレイヤーの頭を戻す
}
}
プレイヤーの頭をアニメーションで動かすために、プレイヤーの頭にもピボットを付けています。アニメーターコントローラーはピボットに付けました。


蓋は少し上下に揺らしています。

バケツから出るときはワープせずに、すぐにアニメーションさせます。音声もロッカーの開け閉めと同じ方法で再生させています。これでFPSコントローラーでバケツに隠れられるようになりました。