using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// Keeps its position at the same as a given transform, and it's Y rotation too, both with deadzones.
/// Movements aren't instant, to avoid motion sickness and add realism.
/// Used to make the 'belly menu' near the user in the MR calibration scene, which is enabled if they
/// only have one controller available (because the other is used to anchor the ZED).
///
[RequireComponent(typeof(Rigidbody))]
public class BellyMenu : MonoBehaviour
{
///
/// Transform that this object will follow. Should be set to the main VR camera.
///
[Tooltip("Transform that this object will follow. Should be set to the main VR camera. ")]
public Transform followTransform;
///
/// How far the follow transform has to be before this transform starts moving toward it.
///
[Tooltip("How far the follow transform has to be before this transform starts moving toward it.")]
public float moveDeadzoneMeters = 0.2f;
///
/// How much of an angle the follow transform has to be before this transform starts rotating toward it.
///
[Tooltip("How much of an angle the follow transform has to be before this transform starts rotating toward it.")]
public float turnDeadzoneDegrees = 40f;
///
/// Maximum force used to translate this object, when using physics.
///
[Tooltip("Maximum force used to translate this object, when using physics. ")]
public float maxMoveForce = 0.3f;
///
/// The fastest this transform will rotate to keep up with the follow transform.
///
[Tooltip("The fastest this transform will rotate to keep up with the follow transform. ")]
public float maxDegreesPerSecond = 60f;
///
/// If true, translates gradually to keep up with the follow transform. Otherwise, movement is instant.
///
[Tooltip("If true, translates gradually to keep up with the follow transform. Otherwise, movement is instant. ")]
public bool gradualMove = false;
///
/// If true, rotates gradually to keep up with the follow transform. Otherwise, rotation is instant.
///
[Tooltip("If true, rotates gradually to keep up with the follow transform. Otherwise, rotation is instant. ")]
public bool gradualTurn = true;
///
/// What multiple of the HMD's height should the object move toward. For instance, 0.5 will go to 100cm on a 200cm person.
/// This is designed for following a Camera for a person in a VR headset.
///
[Tooltip("What multiple of the HMD's height should the object move toward. For instance, 0.5 will go to 100cm on a 200cm person. " +
"This is designed for following a Camera for a person in a VR headset.")]
public float waistHeightMultiple = 0.65f;
private Rigidbody _rb;
// Use this for initialization
void Awake ()
{
_rb = GetComponent();
_rb.useGravity = false;
if(!followTransform)
{
followTransform = Camera.main.transform;
}
}
// Update is called once per frame
void FixedUpdate ()
{
//First, position.
if (gradualMove)
{
Vector3 targetarea = followTransform.position;
targetarea.y = followTransform.position.y * waistHeightMultiple; //So it'll be around their waste.
Vector3 posdiff = targetarea - transform.position;
if (posdiff.magnitude > moveDeadzoneMeters) //Too far away.
{
_rb.AddForce(posdiff.normalized * maxMoveForce);
}
else if (posdiff.magnitude < moveDeadzoneMeters / 2f) //Too close. Slow down extra fast.
{
_rb.velocity *= 0.9f;
if (_rb.velocity.magnitude < 0.05f) _rb.velocity = Vector3.zero;
}
}
else //Not gradual move.
{
Vector3 targetarea = followTransform.position;
targetarea.y = followTransform.position.y * waistHeightMultiple; //So it'll be around their waste.
transform.position = targetarea;
}
//Now rotation.
if (gradualTurn)
{
Vector3 thisforward = transform.forward;
thisforward.y = 0f;
Vector3 followforward = followTransform.forward;
followforward.y = 0f;
float angle = Vector3.SignedAngle(thisforward, followforward, Vector3.up);
if (Mathf.Abs(angle) > turnDeadzoneDegrees / 2f)
{
float speed = Mathf.InverseLerp(turnDeadzoneDegrees / 2f, turnDeadzoneDegrees, Mathf.Abs(angle));
Vector3 newforward = Vector3.RotateTowards(thisforward, followforward, maxDegreesPerSecond * speed * Time.fixedDeltaTime * Mathf.Deg2Rad, 0f);
transform.rotation = Quaternion.LookRotation(newforward, Vector3.up);
}
}
else
{
//Vector3 targetrot = new Vector3(0, followTransform.eulerAngles.y, 0);
transform.eulerAngles = new Vector3(0, followTransform.eulerAngles.y, 0);
}
}
}