using Unity.XR.CoreUtils;
namespace UnityEngine.XR.Interaction.Toolkit.Locomotion
{
///
/// Scriptable object that can perform constrained movement of an by using a
/// that follows the user's body. Each time this object is about to call
/// on the , it first ensures that the
/// and are set such that the
/// bottom of the capsule matches the position determined by
/// and the height of the capsule matches .
///
[CreateAssetMenu(fileName = "CharacterControllerBodyManipulator", menuName = "XR/Locomotion/Character Controller Body Manipulator")]
[HelpURL(XRHelpURLConstants.k_CharacterControllerBodyManipulator)]
public class CharacterControllerBodyManipulator : ScriptableConstrainedBodyManipulator
{
///
public override CollisionFlags lastCollisionFlags => characterController != null ? characterController.collisionFlags : CollisionFlags.None;
///
public override bool isGrounded => characterController == null || characterController.isGrounded;
///
/// The character controller attached to the of the
/// . This is if
/// is .
///
public CharacterController characterController { get; private set; }
///
public override void OnLinkedToBody(XRMovableBody body)
{
base.OnLinkedToBody(body);
var xrOrigin = body.xrOrigin;
var origin = xrOrigin.Origin;
// Try on the Origin GameObject first, and then fallback to the XR Origin GameObject (if different)
if (!origin.TryGetComponent(out CharacterController foundController) && origin != xrOrigin.gameObject)
xrOrigin.TryGetComponent(out foundController);
if (foundController != null)
{
characterController = foundController;
return;
}
Debug.LogWarning($"No CharacterController found. Adding one to Origin GameObject '{origin.name}'.", this);
characterController = origin.AddComponent();
}
///
public override void OnUnlinkedFromBody()
{
base.OnUnlinkedFromBody();
characterController = null;
}
///
public override CollisionFlags MoveBody(Vector3 motion)
{
if (linkedBody == null || characterController == null)
return CollisionFlags.None;
var xrOrigin = linkedBody.xrOrigin;
var bodyGroundPosition = linkedBody.GetBodyGroundLocalPosition();
var capsuleHeight = xrOrigin.CameraInOriginSpaceHeight - bodyGroundPosition.y;
characterController.height = capsuleHeight;
characterController.center = new Vector3(bodyGroundPosition.x,
bodyGroundPosition.y + capsuleHeight * 0.5f + characterController.skinWidth, bodyGroundPosition.z);
return characterController.Move(motion);
}
}
}