経緯
乗り物系のVRでプレイヤーのコクピットにHeadの位置を固定したい、ただしある程度の自由度( 移動 )は入れておきたい...というワガママな要求を実現するために色々調べた。
スクリプト
ほぼ参考資料のコピペ
using UnityEngine;
namespace sample
{
public class CameraController : MonoBehaviour
{
[SerializeField] Transform offset;
[SerializeField] Transform head;
[SerializeField] float movableRadius = 0.3f;
void LateUpdate()
{
if (movableRadius < Vector3.Distance(offset.position, head.position))
{
Vector3 trackingPos = head.localPosition;
Vector3 scale = transform.localScale;
trackingPos = new Vector3(
trackingPos.x * scale.x,
trackingPos.y * scale.y,
trackingPos.z * scale.z
);
// 回転.
trackingPos = transform.rotation * trackingPos;
// 固定したい位置から hmd の位置を.
// 差し引いて実質 hmd の移動を無効化する.
transform.position = Vector3.Lerp(transform.position,offset.position - trackingPos, 0.05f);
}
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(offset.position, movableRadius);
}
}
}
スクリプト修正
コクピットが移動した後にカメラ位置を調整する必要があるため Update()での処理をLateUpdate()での処理に修正
あるいは ProjectSettings > ScriptExecutionOrder で呼び出し順を通常のUpdate()の後に呼ばれるようにしてもいいかも...
パラメータ解説
offset : 基準となる座標
head : 実際にHeadのトラッキングを取得するオブジェクト
movableRadius : 移動可能な距離
SteamVRのサンプルの中にあるPlayerプレハブを流用、SteamVRObjects( CameraRig )に上記スクリプトをアタッチ
offset はPlayerをセット、headはVRCameraをセットしてのテストは問題なく動いている。
offsetは親オブジェクトでなくても問題はない、状況に応じて適切なオブジェクトをoffsetとして設定すべし。