Space-Smash-Out/Assets/FishNet/Runtime/Object/Prediction/MoveRates.cs

414 lines
15 KiB
C#

using GameKit.Dependencies.Utilities;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace FishNet.Object.Prediction
{
/// <summary>
/// Data to be used to configure smoothing for an owned predicted object.
/// </summary>
internal struct MoveRates
{
public float Position;
public float Rotation;
public float Scale;
public MoveRates(float value)
{
Position = value;
Rotation = value;
Scale = value;
}
public MoveRates(float position, float rotation)
{
Position = position;
Rotation = rotation;
Scale = MoveRatesCls.INSTANT_VALUE;
}
public MoveRates(float position, float rotation, float scale)
{
Position = position;
Rotation = rotation;
Scale = scale;
}
/// <summary>
/// True if a positional move rate is set.
/// </summary>
public bool PositionSet => (Position != MoveRatesCls.UNSET_VALUE);
/// <summary>
/// True if rotation move rate is set.
/// </summary>
public bool RotationSet => (Rotation != MoveRatesCls.UNSET_VALUE);
/// <summary>
/// True if a scale move rate is set.
/// </summary>
public bool ScaleSet => (Scale != MoveRatesCls.UNSET_VALUE);
/// <summary>
/// True if any move rate is set.
/// </summary>
public bool AnySet => (PositionSet || RotationSet || ScaleSet);
/// <summary>
/// True if position move rate should be instant.
/// </summary>
public bool InstantPosition => (Position == MoveRatesCls.INSTANT_VALUE);
/// <summary>
/// True if rotation move rate should be instant.
/// </summary>
public bool InstantRotation => (Rotation == MoveRatesCls.INSTANT_VALUE);
/// <summary>
/// True if scale move rate should be instant.
/// </summary>
public bool InstantScale => (Scale == MoveRatesCls.INSTANT_VALUE);
/// <summary>
/// Sets all rates to instant.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetInstantRates()
{
Update(MoveRatesCls.INSTANT_VALUE);
}
/// <summary>
/// Sets all rates to the same value.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(float value)
{
Update(value, value, value);
}
/// <summary>
/// Sets rates for each property.
/// </summary>
public void Update(float position, float rotation, float scale)
{
Position = position;
Rotation = rotation;
Scale = scale;
}
/// <summary>
/// Returns a new MoveRates based on previous values, and a transforms current position.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MoveRates GetWorldMoveRates(Transform from, Transform to, float duration, float teleportThreshold)
{
return GetMoveRates(from.position, to.position, from.rotation, to.rotation, from.localScale, to.localScale, duration, teleportThreshold);
}
/// <summary>
/// Returns a new MoveRates based on previous values, and a transforms current position.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MoveRates GetLocalMoveRates(Transform from, Transform to, float duration, float teleportThreshold)
{
return GetMoveRates(from.localPosition, to.localPosition, from.localRotation, to.localRotation, from.localScale, to.localScale, duration, teleportThreshold);
}
/// <summary>
/// Returns a new MoveRates based on previous values, and a transforms current position.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MoveRates GetWorldMoveRates(TransformProperties prevValues, Transform t, float duration, float teleportThreshold)
{
return GetMoveRates(prevValues.Position, t.position, prevValues.Rotation, t.rotation, prevValues.LocalScale, t.localScale, duration, teleportThreshold);
}
/// <summary>
/// Returns a new MoveRates based on previous values, and a transforms current position.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MoveRates GetLocalMoveRates(TransformProperties prevValues, Transform t, float duration, float teleportThreshold)
{
return GetMoveRates(prevValues.Position, t.localPosition, prevValues.Rotation, t.localRotation, prevValues.LocalScale, t.localScale, duration, teleportThreshold);
}
/// <summary>
/// Returns a new MoveRates based on previous values, and a transforms current position.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MoveRates GetMoveRates(Vector3 fromPosition, Vector3 toPosition, Quaternion fromRotation, Quaternion toRotation, Vector3 fromScale, Vector3 toScale, float duration, float teleportThreshold)
{
float rate;
float distance;
/* Position. */
rate = toPosition.GetRate(fromPosition, duration, out distance);
//Basic teleport check.
if (teleportThreshold != MoveRatesCls.UNSET_VALUE && distance > teleportThreshold)
{
return new MoveRates(MoveRatesCls.INSTANT_VALUE);
}
//Smoothing.
else
{
float positionRate = rate.SetIfUnderTolerance(0.0001f, MoveRatesCls.INSTANT_VALUE);
rate = toRotation.GetRate(fromRotation, duration, out _);
float rotationRate = rate.SetIfUnderTolerance(0.2f, MoveRatesCls.INSTANT_VALUE);
rate = toScale.GetRate(fromScale, duration, out _);
float scaleRate = rate.SetIfUnderTolerance(0.0001f, MoveRatesCls.INSTANT_VALUE);
return new MoveRates(positionRate, rotationRate, scaleRate);
}
}
/// <summary>
/// Gets a move rate for two Vector3s.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float GetMoveRate(Vector3 fromPosition, Vector3 toPosition, float duration, float teleportThreshold)
{
float rate;
float distance;
/* Position. */
rate = toPosition.GetRate(fromPosition, duration, out distance);
//Basic teleport check.
if (teleportThreshold != MoveRatesCls.UNSET_VALUE && distance > teleportThreshold)
{
return MoveRatesCls.INSTANT_VALUE;
}
//Smoothing.
else
{
float positionRate = rate.SetIfUnderTolerance(0.0001f, MoveRatesCls.INSTANT_VALUE);
return positionRate;
}
}
/// <summary>
/// Gets a move rate for two Quaternions.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float GetMoveRate(Quaternion fromRotation, Quaternion toRotation, float duration)
{
float rate = toRotation.GetRate(fromRotation, duration, out _);
float rotationRate = rate.SetIfUnderTolerance(0.2f, MoveRatesCls.INSTANT_VALUE);
return rotationRate;
}
/// <summary>
/// Moves transform to target values.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MoveLocalToTarget(Transform movingTransform, TransformProperties goalProperties, float delta)
{
//No rates are set.
if (!AnySet)
return;
MoveRatesCls.MoveLocalToTarget(movingTransform, goalProperties.Position, Position, goalProperties.Rotation, Rotation, goalProperties.LocalScale, Scale, delta);
}
/// <summary>
/// Moves transform to target values.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MoveWorldToTarget(Transform movingTransform, TransformProperties goalProperties, float delta)
{
//No rates are set.
if (!AnySet)
return;
MoveRatesCls.MoveWorldToTarget(movingTransform, goalProperties.Position, Position, goalProperties.Rotation, Rotation, goalProperties.LocalScale, Scale, delta);
}
}
/// <summary>
/// Data to be used to configure smoothing for an owned predicted object.
/// </summary>
internal class MoveRatesCls : IResettable
{
public float Position;
public float Rotation;
public float Scale;
public MoveRatesCls(float value)
{
Position = value;
Rotation = value;
Scale = value;
}
public MoveRatesCls(float position, float rotation)
{
Position = position;
Rotation = rotation;
Scale = INSTANT_VALUE;
}
public MoveRatesCls(float position, float rotation, float scale)
{
Position = position;
Rotation = rotation;
Scale = scale;
}
/// <summary>
/// True if a positional move rate is set.
/// </summary>
public bool PositionSet => (Position != UNSET_VALUE);
/// <summary>
/// True if rotation move rate is set.
/// </summary>
public bool RotationSet => (Rotation != UNSET_VALUE);
/// <summary>
/// True if a scale move rate is set.
/// </summary>
public bool ScaleSet => (Scale != UNSET_VALUE);
/// <summary>
/// True if any move rate is set.
/// </summary>
public bool AnySet => (PositionSet || RotationSet || ScaleSet);
/// <summary>
/// True if position move rate should be instant.
/// </summary>
public bool InstantPosition => (Position == INSTANT_VALUE);
/// <summary>
/// True if rotation move rate should be instant.
/// </summary>
public bool InstantRotation => (Rotation == INSTANT_VALUE);
/// <summary>
/// True if scale move rate should be instant.
/// </summary>
public bool InstantScale => (Scale == INSTANT_VALUE);
public MoveRatesCls()
{
Update(UNSET_VALUE, UNSET_VALUE, UNSET_VALUE);
}
/// <summary>
/// Sets all rates to instant.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetInstantRates()
{
Update(INSTANT_VALUE);
}
/// <summary>
/// Sets all rates to the same value.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(float value)
{
Update(value, value, value);
}
/// <summary>
/// Updaes values.
/// </summary>
public void Update(float position, float rotation, float scale)
{
Position = position;
Rotation = rotation;
Scale = scale;
}
/// <summary>
/// Updaes values.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(MoveRatesCls mr)
{
Update(mr.Position, mr.Rotation, mr.Scale);
}
public void ResetState()
{
Position = UNSET_VALUE;
Rotation = UNSET_VALUE;
Scale = UNSET_VALUE;
}
public void InitializeState() { }
/// <summary>
/// Value used when data is not set.
/// </summary>
public const float UNSET_VALUE = float.NegativeInfinity;
/// <summary>
/// Value used when move rate should be instant.
/// </summary>
public const float INSTANT_VALUE = float.PositiveInfinity;
/// <summary>
/// Moves transform to target values.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MoveLocalToTarget(Transform movingTransform, TransformPropertiesCls goalProperties, float delta)
{
//No rates are set.
if (!AnySet)
return;
MoveRatesCls.MoveLocalToTarget(movingTransform, goalProperties.Position, Position, goalProperties.Rotation, Rotation, goalProperties.LocalScale, Scale, delta);
}
/// <summary>
/// Moves transform to target values.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MoveLocalToTarget(Transform movingTransform, Vector3 posGoal, float posRate, Quaternion rotGoal, float rotRate, Vector3 scaleGoal, float scaleRate, float delta)
{
Transform t = movingTransform;
float rate;
rate = posRate;
if (rate == MoveRatesCls.INSTANT_VALUE)
t.localPosition = posGoal;
else
t.localPosition = Vector3.MoveTowards(t.localPosition, posGoal, rate * delta);
rate = rotRate;
if (rate == MoveRatesCls.INSTANT_VALUE)
t.localRotation = rotGoal;
else
t.localRotation = Quaternion.RotateTowards(t.localRotation, rotGoal, rate * delta);
rate = scaleRate;
if (rate == MoveRatesCls.INSTANT_VALUE)
t.localScale = scaleGoal;
else
t.localScale = Vector3.MoveTowards(t.localScale, scaleGoal, rate * delta);
}
/// <summary>
/// Moves transform to target values.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void MoveWorldToTarget(Transform movingTransform, Vector3 posGoal, float posRate, Quaternion rotGoal, float rotRate, Vector3 scaleGoal, float scaleRate, float delta)
{
Transform t = movingTransform;
float rate;
rate = posRate;
if (rate == MoveRatesCls.INSTANT_VALUE)
t.position = posGoal;
else if (rate == MoveRatesCls.UNSET_VALUE) { }
else
t.position = Vector3.MoveTowards(t.position, posGoal, rate * delta);
rate = rotRate;
if (rate == MoveRatesCls.INSTANT_VALUE)
t.rotation = rotGoal;
else if (rate == MoveRatesCls.UNSET_VALUE) { }
else
t.rotation = Quaternion.RotateTowards(t.rotation, rotGoal, rate * delta);
rate = scaleRate;
if (rate == MoveRatesCls.INSTANT_VALUE)
t.localScale = scaleGoal;
else if (rate == MoveRatesCls.UNSET_VALUE) { }
else
t.localScale = Vector3.MoveTowards(t.localScale, scaleGoal, rate * delta);
}
}
}