namespace Zinnia.Tracking.Follow.Modifier.Property.Position
{
using UnityEngine;
using Zinnia.Extension;
///
/// Updates the velocity by moving towards a given source.
///
public class RigidbodyVelocity : DivergablePropertyModifier
{
#region Velocity Settings
[Header("Velocity Settings")]
[Tooltip("The maximum squared magnitude of velocity that can be applied to the source.")]
[SerializeField]
private float velocityLimit = float.PositiveInfinity;
///
/// The maximum squared magnitude of velocity that can be applied to the source.
///
public float VelocityLimit
{
get
{
return velocityLimit;
}
set
{
velocityLimit = value;
}
}
[Tooltip("The maximum difference in distance to the tracked position.")]
[SerializeField]
private float maxDistanceDelta = 10f;
///
/// The maximum difference in distance to the tracked position.
///
public float MaxDistanceDelta
{
get
{
return maxDistanceDelta;
}
set
{
maxDistanceDelta = value;
}
}
#endregion
///
/// A cached version of the target .
///
protected Rigidbody cachedTargetRigidbody;
///
/// A cached version of the target.
///
protected GameObject cachedTarget;
///
/// Modifies the target velocity to move towards the given source.
///
/// The source to utilize in the modification.
/// The target to modify.
/// The offset of the target against the source when modifying.
protected override void DoModify(GameObject source, GameObject target, GameObject offset = null)
{
cachedTargetRigidbody = cachedTargetRigidbody == null || target != cachedTarget ? target.TryGetComponent(true) : cachedTargetRigidbody;
cachedTarget = target;
Vector3 positionDelta = source.transform.position - (offset != null ? offset.transform.position : target.transform.position);
float deltaTime = Time.inFixedTimeStep ? Time.fixedDeltaTime : Time.deltaTime;
Vector3 velocityTarget = positionDelta / deltaTime;
Vector3 calculatedVelocity = Vector3.MoveTowards(cachedTargetRigidbody.velocity, velocityTarget, MaxDistanceDelta / deltaTime);
if (!cachedTargetRigidbody.isKinematic && calculatedVelocity.sqrMagnitude < VelocityLimit)
{
cachedTargetRigidbody.velocity = calculatedVelocity;
}
base.DoModify(source, target, offset);
}
///
/// Gets the source and target positions to check divergence against.
///
/// The source to check against.
/// The target to check with.
/// Any offset applied to the target.
/// The source position.
/// The target position.
protected override void GetCheckPoints(GameObject source, GameObject target, GameObject offset, out Vector3 a, out Vector3 b)
{
a = source.transform.position;
b = target.transform.position;
if (offset != null)
{
a = source.transform.position - (offset.transform.position - target.transform.position);
}
}
}
}