142 lines
4.6 KiB
C#
142 lines
4.6 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
[RequireComponent(typeof(CharacterController))]
|
|
[RequireComponent(typeof(OVRPlayerController))]
|
|
public class CharacterCameraConstraint : MonoBehaviour
|
|
{
|
|
[Tooltip("This should be a reference to the OVRCameraRig that is usually a child of the PlayerController.")]
|
|
public OVRCameraRig CameraRig;
|
|
|
|
[Tooltip("This value represents the character capsule's distance from the HMD's position. When the player is moving in legal space without collisions, this will be zero.")]
|
|
public float CurrentDistance;
|
|
|
|
[Tooltip("When true, the camera will fade to black when the HMD is moved into collidable geometry.")]
|
|
public bool EnableFadeout;
|
|
|
|
[Tooltip("When true, the camera will be prevented from passing through collidable geometry. This is usually considered uncomfortable for users.")]
|
|
public bool EnableCollision;
|
|
|
|
[Tooltip("When true, adjust the character controller height on the fly to match the HMD's offset from the ground which will allow ducking to go through smaller spaces.")]
|
|
public bool DynamicHeight;
|
|
|
|
[Tooltip("This should be set to 1 to make the screen completely fade out when the HMD is inside world geometry. Lesser values can be useful for testing.")]
|
|
public float MaxFade = 1f;
|
|
|
|
[Tooltip("This value is used to control how far from the character capsule the HMD must be before the fade to black begins.")]
|
|
public float FadeMinDistance = 0.25f;
|
|
|
|
[Tooltip("This value is used to control how far from the character capsule the HMD must be before the fade to black is complete. This should be tuned so that it is fully faded in before the camera will clip geometry that the player should not be able see beyond.")]
|
|
public float FadeMaxDistance = 0.35f;
|
|
|
|
private readonly Action _cameraUpdateAction;
|
|
|
|
private readonly Action _preCharacterMovementAction;
|
|
|
|
private CharacterController _character;
|
|
|
|
private OVRPlayerController _playerController;
|
|
|
|
private CharacterCameraConstraint()
|
|
{
|
|
_cameraUpdateAction = CameraUpdate;
|
|
_preCharacterMovementAction = PreCharacterMovement;
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
_character = GetComponent<CharacterController>();
|
|
_playerController = GetComponent<OVRPlayerController>();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
_playerController.CameraUpdated += _cameraUpdateAction;
|
|
_playerController.PreCharacterMove += _preCharacterMovementAction;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
_playerController.PreCharacterMove -= _preCharacterMovementAction;
|
|
_playerController.CameraUpdated -= _cameraUpdateAction;
|
|
}
|
|
|
|
private void CameraUpdate()
|
|
{
|
|
if (!DynamicHeight)
|
|
{
|
|
return;
|
|
}
|
|
float cameraHeight = _playerController.CameraHeight;
|
|
if (cameraHeight <= _character.height)
|
|
{
|
|
_character.height = cameraHeight - _character.skinWidth;
|
|
return;
|
|
}
|
|
Vector3 position = _character.transform.position;
|
|
position += _character.center;
|
|
position.y -= _character.height / 2f + _character.radius;
|
|
float num = _character.radius - _character.skinWidth;
|
|
RaycastHit hitInfo;
|
|
if (EnableCollision && Physics.SphereCast(position, _character.radius, Vector3.up, out hitInfo, cameraHeight + num, _character.gameObject.layer, QueryTriggerInteraction.Ignore))
|
|
{
|
|
_character.height = hitInfo.distance - _character.radius - _character.skinWidth;
|
|
Transform transform = _character.transform;
|
|
Vector3 position2 = transform.position;
|
|
position2.y -= cameraHeight - hitInfo.distance + num;
|
|
transform.position = position2;
|
|
}
|
|
else
|
|
{
|
|
_character.height = cameraHeight - _character.skinWidth;
|
|
}
|
|
}
|
|
|
|
private void PreCharacterMovement()
|
|
{
|
|
if (_playerController.Teleported)
|
|
{
|
|
return;
|
|
}
|
|
Vector3 position = CameraRig.transform.position;
|
|
Vector3 position2 = CameraRig.centerEyeAnchor.position;
|
|
Vector3 vector = position2 - base.transform.position;
|
|
vector.y = 0f;
|
|
float magnitude = vector.magnitude;
|
|
if (magnitude > 0f)
|
|
{
|
|
_character.Move(vector);
|
|
Vector3 vector2 = base.transform.position - position2;
|
|
vector2.y = 0f;
|
|
CurrentDistance = vector2.magnitude;
|
|
CameraRig.transform.position = position;
|
|
if (EnableCollision)
|
|
{
|
|
if (CurrentDistance > 0f)
|
|
{
|
|
CameraRig.transform.position = position - vector;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CurrentDistance = 0f;
|
|
}
|
|
Vector3 position3 = base.transform.position;
|
|
position3 += _character.center;
|
|
position3.y -= _character.height / 2f;
|
|
float cameraHeight = _playerController.CameraHeight;
|
|
RaycastHit hitInfo;
|
|
if (Physics.SphereCast(position3, _character.radius, Vector3.up, out hitInfo, cameraHeight, base.gameObject.layer, QueryTriggerInteraction.Ignore))
|
|
{
|
|
float distance = hitInfo.distance;
|
|
distance = cameraHeight - distance;
|
|
if (distance > CurrentDistance)
|
|
{
|
|
CurrentDistance = distance;
|
|
}
|
|
}
|
|
}
|
|
}
|