using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace Passer {
using Humanoid;
/// The Teleport Target provides control to where a player can teleport and can be used in combination with a generic Interaction Pointer.
/// 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
}
/// Teleport the root transform instead of the transform itself.
/// If this is enabled the root of the transform (the topmost transform)
/// will be teleported instead of the transform itself.
public bool teleportRoot = false;
/// Check the target location for collisions.
/// 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;
/// The type of movement used to reacht the teleport target.
/// 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;
/// Determines the target position and rotation.
/// 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;
/// The target transform for the teleport.
/// 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;
/// The pose of a humanoid after it has been teleported.
/// 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;
/// Enables humanoid animators after teleporting.
/// 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;
/// Teleport the transform to this Teleport Target.
/// 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.
/// The transform to teleport
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);
}
/// Teleport the Humanoid to this Teleport Target.
/// 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.
/// The humanoid to teleport
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);
}
/// Teleporting initialized by an Unity UI Event.
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();
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);
}
/// Teleport the transform to a position and rotation.
/// 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.
/// The transform to teleport
/// The new world position of the transform after teleporting
/// The new world rotation of the transform after teleporting
/// The movement type to use to get to the target
/// The new parent of the transform after teleporting
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();
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);
}
/// Check is the target position is valid.
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;
}
}