RoboticArms/Library/PackageCache/com.unity.splines@d3e1e500c9a0/Samples~/Runtime/AnimateCarAlongSpline.cs
2025-11-17 15:16:36 +07:00

160 lines
5.4 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Splines;
using Unity.Mathematics;
using UnityEngine.Serialization;
using Interpolators = UnityEngine.Splines.Interpolators;
using Quaternion = UnityEngine.Quaternion;
namespace Unity.Splines.Examples
{
public class AnimateCarAlongSpline : MonoBehaviour
{
[SerializeField]
SplineContainer m_SplineContainer;
[Obsolete("Use Container instead.", false)]
public SplineContainer splineContainer => Container;
public SplineContainer Container => m_SplineContainer;
[SerializeField]
Car m_CarToAnimate;
[HideInInspector]
[Obsolete("No longer used.", false)]
public float m_DefaultSpeed;
[HideInInspector]
[Obsolete("No longer used.", false)]
public Vector3 m_DefaultTilt;
[HideInInspector]
[Obsolete("Use MaxSpeed instead.", false)]
public float m_MaxSpeed = 40f;
[FormerlySerializedAs("m_MaxSpeed")]
[Min(0f)]
public float MaxSpeed = 40f;
[SerializeField]
SplineData<float> m_Speed = new SplineData<float>();
[Obsolete("Use Speed instead.", false)]
public SplineData<float> speed => Speed;
public SplineData<float> Speed => m_Speed;
[SerializeField]
SplineData<float3> m_Tilt = new SplineData<float3>();
[Obsolete("Use Tilt instead.", false)]
public SplineData<float3> tilt => Tilt;
public SplineData<float3> Tilt => m_Tilt;
[SerializeField]
DriftSplineData m_Drift;
[Obsolete("Use DriftData instead.", false)]
public DriftSplineData driftData => DriftData;
public DriftSplineData DriftData
{
get
{
if (m_Drift == null)
m_Drift = GetComponent<DriftSplineData>();
return m_Drift;
}
}
float m_CurrentOffset;
float m_CurrentSpeed;
float m_SplineLength;
Spline m_Spline;
public void Initialize()
{
//Trying to initialize either the spline container or the car
if (m_SplineContainer == null && !TryGetComponent<SplineContainer>(out m_SplineContainer))
if (m_CarToAnimate == null)
TryGetComponent<Car>(out m_CarToAnimate);
}
void Start()
{
Assert.IsNotNull(m_SplineContainer);
m_Spline = m_SplineContainer.Spline;
m_SplineLength = m_Spline.GetLength();
m_CurrentOffset = 0f;
}
void OnValidate()
{
if (m_Speed != null)
{
for (int index = 0; index < m_Speed.Count; index++)
{
var data = m_Speed[index];
//We don't want to have a value that is negative or null as it might block the simulation
if (data.Value <= 0)
{
data.Value = Mathf.Max(0f, m_Speed.DefaultValue);
m_Speed[index] = data;
}
}
}
if (m_Tilt != null)
{
for (int index = 0; index < m_Tilt.Count; index++)
{
var data = m_Tilt[index];
//We don't want to have a up vector of magnitude 0
if (math.length(data.Value) == 0)
{
data.Value = m_Tilt.DefaultValue;
m_Tilt[index] = data;
}
}
}
if (DriftData != null)
DriftData.Container = Container;
}
void Update()
{
if (m_SplineContainer == null || m_CarToAnimate == null)
return;
m_CurrentOffset = (m_CurrentOffset + m_CurrentSpeed * Time.deltaTime / m_SplineLength) % 1f;
if (m_Speed.Count > 0)
m_CurrentSpeed = m_Speed.Evaluate(m_Spline, m_CurrentOffset, PathIndexUnit.Normalized, new Interpolators.LerpFloat());
else
m_CurrentSpeed = m_Speed.DefaultValue;
var posOnSplineLocal = SplineUtility.EvaluatePosition(m_Spline, m_CurrentOffset);
var direction = SplineUtility.EvaluateTangent(m_Spline, m_CurrentOffset);
var upSplineDirection = SplineUtility.EvaluateUpVector(m_Spline, m_CurrentOffset);
var right = math.normalize(math.cross(upSplineDirection, direction));
var driftOffset = 0f;
if (DriftData != null)
{
driftOffset = DriftData.Drift.Count == 0 ?
DriftData.Drift.DefaultValue :
DriftData.Drift.Evaluate(m_Spline, m_CurrentOffset, PathIndexUnit.Normalized, new Interpolators.LerpFloat());
}
m_CarToAnimate.transform.position = m_SplineContainer.transform.TransformPoint(posOnSplineLocal + driftOffset * right);
var up =
(m_Tilt.Count == 0) ?
m_Tilt.DefaultValue :
m_Tilt.Evaluate(m_Spline, m_CurrentOffset, PathIndexUnit.Normalized, new Interpolators.LerpFloat3());
var rot = Quaternion.LookRotation(direction, upSplineDirection);
m_CarToAnimate.transform.rotation = Quaternion.LookRotation(direction, rot * up);
}
}
}