179 lines
9.8 KiB
C#
179 lines
9.8 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.EventSystems;
|
|
|
|
namespace Passer {
|
|
using Humanoid;
|
|
|
|
/// <summary> The Teleport Target provides control to where a player can teleport and can be used in combination with a generic Interaction Pointer. </summary>
|
|
/// The Teleport Target can be placed on a static or moving Rigidbody object with a collider.
|
|
/// It has been implemented as a Event Trigger and will teleport when an PointerDown event is received.
|
|
[HelpURLAttribute("https://passervr.com/documentation/humanoid-control/tools/teleport-target/")]
|
|
public class TeleportTarget : EventTrigger {
|
|
public enum TargetPosRot {
|
|
Pointer,
|
|
Transform
|
|
}
|
|
/// <summary>Teleport the root transform instead of the transform itself.</summary>
|
|
/// If this is enabled the root of the transform (the topmost transform)
|
|
/// will be teleported instead of the transform itself.
|
|
public bool teleportRoot = false;
|
|
|
|
/// <summary>Check the target location for collisions.</summary>
|
|
/// if enabled this will check if the location to which the pointer is pointing contains a collider.
|
|
/// Teleporting will only take place if no collider has been found.
|
|
/// The check is executed using a capsule of 2 meters/units high and 0.2 meters/units radius.
|
|
public bool checkCollision = true;
|
|
|
|
/// <summary>The type of movement used to reacht the teleport target.</summary>
|
|
/// determines how the Transform is moved to the Target Point.
|
|
/// Teleport = direct placement a the target point.
|
|
/// Dash = a quick movement is a short time from the originating point to the target point.
|
|
public MovementType movementType;
|
|
|
|
/// <summary>Determines the target position and rotation.</summary>
|
|
/// TargetPosRot.Pointer = The interaction pointer location is the target position and rotation.
|
|
/// TargetPosRot.Transform = The targetTransform determines the target position and rototation.
|
|
public TargetPosRot targetPosRot = TargetPosRot.Pointer;
|
|
|
|
/// <summary>The target transform for the teleport.</summary>
|
|
/// If targetPosRot is set to TargetPosRot.Transform the targetTransform will determine the
|
|
/// position and rotation of the transform to teleport.
|
|
/// Next to that, the teleported transform will become a child of this teleportTarget after teleporting
|
|
public Transform targetTransform;
|
|
|
|
/// <summary>The pose of a humanoid after it has been teleported.</summary>
|
|
/// This is an optional Pose of the Humanoid after it has been teleported.
|
|
/// This enables you to teleport to a different pose like a seating pose for instance.
|
|
public Pose pose;
|
|
|
|
/// <summary>Enables humanoid animators after teleporting.</summary>
|
|
/// This will enable or disable the hips and foot animator after teleporting.
|
|
/// For poses like seating a walking foot animation is not required.
|
|
/// In such cases the foot animator can be switch off with this setting.
|
|
public bool enableAnimators = true;
|
|
|
|
/// <summary>Teleport the transform to this Teleport Target.</summary>
|
|
/// This function will teleport the given transform to this teleport target using the
|
|
/// teleport target settings.
|
|
/// If the targetPosRot is set to TargetPosRot.Pointer, the transform will be transported
|
|
/// using the transform of the gameObject as there is no pointer information.
|
|
/// <param name="t">The transform to teleport</param>
|
|
public void TeleportToHere(Transform t) {
|
|
if (targetPosRot == TargetPosRot.Transform && targetTransform != null)
|
|
Teleport(t, targetTransform.position, targetTransform.rotation, movementType, targetTransform);
|
|
else
|
|
Teleport(t, gameObject.transform.position, gameObject.transform.rotation, movementType, null);
|
|
}
|
|
|
|
/// <summary>Teleport the Humanoid to this Teleport Target.</summary>
|
|
/// This function will teleport the given humanoid to this teleport target using the
|
|
/// teleport target settings.
|
|
/// If the targetPosRot is set to TargetPosRot.Pointer, the humanoid will be transported
|
|
/// using the transform of the gameObject as there is no pointer information.
|
|
/// <param name="humanoid">The humanoid to teleport</param>
|
|
public void TeleportToHere(HumanoidControl humanoid) {
|
|
if (targetPosRot == TargetPosRot.Transform && targetTransform != null)
|
|
Teleport(humanoid.transform, targetTransform.position, targetTransform.rotation, movementType, targetTransform);
|
|
else
|
|
Teleport(humanoid.transform, gameObject.transform.position, gameObject.transform.rotation, movementType);
|
|
}
|
|
|
|
/// <summary>Teleporting initialized by an Unity UI Event.</summary>
|
|
public override void OnPointerDown(PointerEventData eventData) {
|
|
Vector3 pointingPosition = eventData.pointerCurrentRaycast.worldPosition;
|
|
|
|
if (IsValid(pointingPosition) && eventData.currentInputModule != null) {
|
|
GameObject originator = eventData.currentInputModule.gameObject;
|
|
|
|
Transform teleportingTransform = originator.transform;
|
|
HumanoidControl humanoid = originator.transform.GetComponentInParent<HumanoidControl>();
|
|
if (humanoid != null) {
|
|
teleportingTransform = humanoid.transform;
|
|
|
|
humanoid.hipsTarget.torsoAnimator.enabled = enableAnimators;
|
|
humanoid.leftFootTarget.legAnimator.enabled = enableAnimators;
|
|
humanoid.rightFootTarget.legAnimator.enabled = enableAnimators;
|
|
}
|
|
|
|
if (targetPosRot == TargetPosRot.Pointer)
|
|
Teleport(teleportingTransform, pointingPosition, originator.transform.rotation, movementType, null);
|
|
else if (targetTransform != null)
|
|
Teleport(teleportingTransform, targetTransform.position, targetTransform.rotation, movementType, targetTransform);
|
|
else
|
|
Teleport(teleportingTransform, transform.position, transform.rotation, movementType, targetTransform);
|
|
|
|
if (humanoid != null) {
|
|
humanoid.pose = pose;
|
|
if (pose != null) {
|
|
float oldNeckHeight = humanoid.headTarget.head.target.transform.position.y;
|
|
humanoid.pose.Show(humanoid);
|
|
float deltaNeckHeight = humanoid.headTarget.head.target.transform.position.y - oldNeckHeight;
|
|
humanoid.AdjustTracking(new Vector3(0, deltaNeckHeight, 0));
|
|
humanoid.CopyRigToTargets();
|
|
}
|
|
}
|
|
}
|
|
|
|
base.OnPointerDown(eventData);
|
|
}
|
|
|
|
/// <summary>Teleport the transform to a position and rotation.</summary>
|
|
/// This function will teleport the given transform to this teleport target using the
|
|
/// teleport target settings.
|
|
/// If the targetPosRot is set to TargetPosRot.Pointer, the transform will be transported
|
|
/// using the transform of the gameObject as there is no pointer information.
|
|
/// <param name="transform">The transform to teleport</param>
|
|
/// <param name="position">The new world position of the transform after teleporting</param>
|
|
/// <param name="rotation">The new world rotation of the transform after teleporting</param>
|
|
/// <param name="movementType">The movement type to use to get to the target</param>
|
|
/// <param name="newParent">The new parent of the transform after teleporting</param>
|
|
protected virtual void Teleport(Transform transform, Vector3 position, Quaternion rotation, MovementType movementType = MovementType.Teleport, Transform newParent = null) {
|
|
if (newParent != null && transform.parent == newParent)
|
|
// The transform is already at the teleport target, do not teleport again
|
|
return;
|
|
|
|
Vector3 originPosition = transform.position;
|
|
|
|
Quaternion humanoidRotation = Quaternion.identity;
|
|
HumanoidControl humanoid = transform.GetComponent<HumanoidControl>();
|
|
if (humanoid != null) {
|
|
Vector3 humanoidPosition = humanoid.GetHumanoidPosition();
|
|
Vector3 deltaHumanoid = humanoidPosition - transform.position;
|
|
|
|
Vector3 humanoidForward = humanoid.hipsTarget.transform.forward;
|
|
humanoidForward.y = 0;
|
|
humanoidRotation = Quaternion.LookRotation(humanoidForward, humanoid.up);
|
|
|
|
GameObject realWorld = HumanoidControl.GetRealWorld(humanoid.transform);
|
|
realWorld.transform.position -= deltaHumanoid;
|
|
realWorld.transform.rotation *= Quaternion.Inverse(humanoidRotation);
|
|
}
|
|
|
|
if (teleportRoot) {
|
|
Vector3 translation = position - originPosition; // World coordinates
|
|
|
|
transform = transform.root;
|
|
|
|
position = transform.position + translation;
|
|
}
|
|
Debug.Log("TeleportRoot: " + teleportRoot + ", teleporting " + transform.name);
|
|
transform.MoveTo(position, movementType);
|
|
transform.rotation = rotation;
|
|
transform.SetParent(newParent, true);
|
|
}
|
|
|
|
/// <summary>Check is the target position is valid.</summary>
|
|
protected virtual bool IsValid(Vector3 position) {
|
|
if (!checkCollision)
|
|
return true;
|
|
|
|
Vector3 start = position + new Vector3(0, 0.3F, 0);
|
|
Vector3 end = position + new Vector3(0, 1.8F, 0);
|
|
bool isOccupied = Physics.CheckCapsule(start, end, 0.2F);
|
|
return (!isOccupied);
|
|
}
|
|
|
|
public UnityEvent unityEvents;
|
|
}
|
|
} |