Files
BABA_YAGA/Assets/Third Parties/Opsive/UltimateCharacterController/Scripts/Objects/CharacterAssist/MoveTowardsLocation.cs
2026-06-09 09:18:17 +07:00

116 lines
6.0 KiB
C#

/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Objects.CharacterAssist
{
using Opsive.UltimateCharacterController.Utility;
using UnityEngine;
/// <summary>
/// Specifies the location that the character should move to when the Move Towards ability is started.
/// </summary>
public class MoveTowardsLocation : MonoBehaviour
{
[Tooltip("The offset relative to the transform that the character should move towards.")]
[SerializeField] protected Vector3 m_Offset = new Vector3(0, 0, 1);
[Tooltip("The yaw offset relative to the transform that the character should rotate towards.")]
[SerializeField] protected float m_YawOffset = 180;
[Tooltip("The size of the area that the character can start the ability at. A zero value indicates that the character must land on the exact offset.")]
[SerializeField] protected Vector3 m_Size;
[Tooltip("The ability can start when the distance between the start location and character is less than the specified value.")]
[Range(0.0001f, 100)] [SerializeField] protected float m_Distance = 0.01f;
[Tooltip("The ability can start when the angle threshold between the start location and character is less than the specified value.")]
[Range(0, 360)] [SerializeField] protected float m_Angle = 0.5f;
[Tooltip("Is the character required to be on the ground?")]
[SerializeField] protected bool m_RequireGrounded = true;
[Tooltip("Should the ability wait to start until all transitions are complete?")]
[SerializeField] protected bool m_PrecisionStart = true;
[Tooltip("The multiplier to apply to the character's speed when moving to the start location.")]
[SerializeField] protected float m_MovementMultiplier = 1;
public Vector3 Offset { get { return m_Offset; } set { m_Offset = value; } }
public float YawOffset { get { return m_YawOffset; } set { m_YawOffset = value; } }
public Vector3 Size { get { return m_Size; } set { m_Size = value; } }
public float Distance { get { return m_Distance; } set { m_Distance = value; } }
public float Angle { get { return m_Angle; } set { m_Angle = value; } }
public bool RequireGrounded { get { return m_RequireGrounded; } set { m_RequireGrounded = value; } }
public bool PrecisionStart { get { return m_PrecisionStart; } set { m_PrecisionStart = value; } }
public float MovementMultiplier { get { return m_MovementMultiplier; } set { m_MovementMultiplier = value; } }
private Transform m_Transform;
private float m_StartYawOffset;
private Vector3 m_StartOffset;
public Vector3 TargetPosition { get { return m_Transform.TransformPoint(m_Offset); } }
public Quaternion TargetRotation { get { return m_Transform.rotation * Quaternion.Euler(0, m_YawOffset, 0); } }
public float StartYawOffset { get { return m_StartYawOffset; } }
public Vector3 StartOffset { get { return m_StartOffset; } }
/// <summary>
/// Initialize the default values.
/// </summary>
private void Awake()
{
m_Transform = transform;
m_StartYawOffset = m_YawOffset;
m_StartOffset = m_Offset;
}
/// <summary>
/// Returns the direction that the character should move towards.
/// </summary>
/// <param name="position">The position of the character.</param>
/// <param name="rotation">The rotation of the character.</param>
/// <returns>The direction that the character should move towards.</returns>
public Vector3 GetTargetDirection(Vector3 position, Quaternion rotation)
{
var direction = m_Transform.TransformPoint(m_Offset) - position;
if (m_Size.sqrMagnitude == 0) {
return MathUtility.InverseTransformDirection(direction, rotation);
}
var size = m_Transform.TransformDirection(m_Size);
if (Mathf.Abs(direction.x) < Mathf.Abs(size.x / 2)) { direction.x = 0; }
if (Mathf.Abs(direction.y) < Mathf.Abs(size.y / 2)) { direction.y = 0; }
if (Mathf.Abs(direction.z) < Mathf.Abs(size.z / 2)) { direction.z = 0; }
return MathUtility.InverseTransformDirection(direction, rotation);
}
/// <summary>
/// Is the character in a valid position?
/// </summary>
/// <param name="position">The position of the character.</param>
/// <param name="rotation">The rotation of the character.</param>
/// <param name="grounded">Is the character grounded?</param>
/// <returns>True if the position is valid.</returns>
public bool IsPositionValid(Vector3 position, Quaternion rotation, bool grounded)
{
var direction = GetTargetDirection(position, rotation);
if (Mathf.Abs(direction.x) <= m_Distance &&
((m_RequireGrounded && grounded) || (!m_RequireGrounded && (Mathf.Abs(direction.y) <= m_Distance))) &&
Mathf.Abs(direction.z) <= m_Distance) {
return true;
}
return false;
}
/// <summary>
/// Is the character in a valid rotation?
/// </summary>
/// <param name="rotation">The rotation of the character.</param>
/// <returns>True if the rotation is valid.</returns>
public bool IsRotationValid(Quaternion rotation)
{
Vector3 forwardDirection;
if (m_RequireGrounded) {
forwardDirection = Vector3.ProjectOnPlane(m_Transform.forward, rotation * Vector3.up);
} else {
forwardDirection = m_Transform.forward;
}
return Vector3.Angle(Quaternion.Euler(0, m_YawOffset, 0) * forwardDirection, rotation * Vector3.forward) <= m_Angle / 2 + 0.001f;
}
}
}