// Hip Tracking|Presence|70050
namespace VRTK
{
using UnityEngine;
///
/// Attempts to provide the relative position of a hip without the need for additional hardware sensors.
///
///
/// **Script Usage:**
/// * Place the `VRTK_HipTracking` script on any active scene GameObject and this GameObject will then track to the estimated hip position.
///
[AddComponentMenu("VRTK/Scripts/Presence/VRTK_HipTracking")]
public class VRTK_HipTracking : MonoBehaviour
{
[Tooltip("Distance underneath Player Head for hips to reside.")]
public float HeadOffset = -0.35f;
[Header("Optional")]
[Tooltip("Optional Transform to use as the Head Object for calculating hip position. If none is given one will try to be found in the scene.")]
public Transform headOverride;
[Tooltip("Optional Transform to use for calculating which way is 'Up' relative to the player for hip positioning.")]
public Transform ReferenceUp;
protected Transform playerHead;
protected virtual void Awake()
{
VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
}
protected virtual void OnEnable()
{
playerHead = (headOverride != null ? headOverride : VRTK_DeviceFinder.HeadsetTransform());
}
protected virtual void OnDestroy()
{
VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
}
protected virtual void LateUpdate()
{
if (playerHead == null)
{
return;
}
Vector3 up = Vector3.up;
if (ReferenceUp != null)
{
up = ReferenceUp.up;
}
transform.position = playerHead.position + (HeadOffset * up);
Vector3 forward = playerHead.forward;
Vector3 forwardLeveld1 = forward;
forwardLeveld1.y = 0;
forwardLeveld1.Normalize();
Vector3 mixedInLocalForward = playerHead.up;
if (forward.y > 0)
{
mixedInLocalForward = -playerHead.up;
}
mixedInLocalForward.y = 0;
mixedInLocalForward.Normalize();
float dot = Mathf.Clamp(Vector3.Dot(forwardLeveld1, forward), 0f, 1f);
Vector3 finalForward = Vector3.Lerp(mixedInLocalForward, forwardLeveld1, dot * dot);
transform.rotation = Quaternion.LookRotation(finalForward, up);
}
}
}