Files
back_cantanBuilding/Assets/Scripts/EventWashing/Tools/CameraFollowPathMoveController.cs
2026-05-26 16:15:54 +08:00

359 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Cinemachine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
namespace game
{
[ExecuteAlways]
[DisallowMultipleComponent]
public class CameraFollowPathMoveController : MonoBehaviour
{
/// <summary>The path to follow</summary>
[Tooltip("The path to follow")]
public CinemachinePath Path;
[Tooltip("路径停歇点索引,循环执行。eg:5个点执行到最后一个位置会从移动到初始位置开始。")]
public List<int> m_RestIndexList = new List<int>();
[Tooltip("磁性距离,距离目标点一定距离,即认为到达目标点。")]
public float m_MagneticDistance = 0.01f;
[Tooltip("一直移动,可以查看整个移动过程,主要用于本地测试。发包时关闭。")]
public bool IsAlwaysMoving = false;
[Tooltip("是否开启测试停歇点配合TestRestIndex使用主要用于本地测试。发包时关闭。")]
public bool m_IsTestRest = false;
[Tooltip("测试用停歇点索引配合IsTestRest使用默认为-1,在0-停歇点索引位之间生效。")]
public int m_TestRestIndex = -1;
/// <summary>This enum defines the options available for the update method.</summary>
public enum UpdateMethod
{
/// <summary>Updated in normal MonoBehaviour Update.</summary>
Update,
/// <summary>Updated in sync with the Physics module, in FixedUpdate</summary>
FixedUpdate,
/// <summary>Updated in normal MonoBehaviour LateUpdate</summary>
LateUpdate
};
/// <summary>When to move the cart, if Velocity is non-zero</summary>
[Tooltip("When to move the cart, if Velocity is non-zero")]
public UpdateMethod m_UpdateMethod = UpdateMethod.Update;
/// <summary>How to interpret the Path Position</summary>
[Tooltip("How to interpret the Path Position. If set to Path Units, values are as follows: 0 represents the first waypoint on the path, 1 is the second, and so on. Values in-between are points on the path in between the waypoints. If set to Distance, then Path Position represents distance along the path.")]
[HideInInspector] public CinemachinePathBase.PositionUnits m_PositionUnits = CinemachinePathBase.PositionUnits.Distance;
/// <summary>Move the cart with this speed</summary>
[Tooltip("Move the cart with this speed along the path. The value is interpreted according to the Position Units setting.")]
[FormerlySerializedAs("m_Velocity")]
public float Speed;
/// <summary>The cart's current position on the path, in distance units</summary>
[Tooltip("The position along the path at which the cart will be placed. This can be animated directly or, if the velocity is non-zero, will be updated automatically. The value is interpreted according to the Position Units setting.")]
[FormerlySerializedAs("m_CurrentDistance")]
[HideInInspector] public float m_Position;
private enum MoveState
{
Stationary,
Moving
}
private MoveState m_State = MoveState.Stationary;
private int m_MoveIndex = 0;
private int m_CurPathIndex = 0;
//private int m_MoveDirection = 0;
void Awake()
{
#if UNITY_EDITOR
if (Path != null)
{
ResamplePath();
JumpToRestIndex(0);
SetCartPosition(0f);
}
#endif
}
void FixedUpdate()
{
if (m_State == MoveState.Stationary && !IsAlwaysMoving) return;
if (m_UpdateMethod == UpdateMethod.FixedUpdate)
SetCartPosition(m_Position + Speed * Time.deltaTime);
}
void Update()
{
CheckTestRest();
if (m_State == MoveState.Stationary && !IsAlwaysMoving) return;
float speed = Application.isPlaying ? Speed : 0;
if (m_UpdateMethod == UpdateMethod.Update)
SetCartPosition(m_Position + speed * Time.deltaTime);
}
void LateUpdate()
{
if (m_State == MoveState.Stationary && !IsAlwaysMoving) return;
if (!Application.isPlaying)
SetCartPosition(m_Position);
else if (m_UpdateMethod == UpdateMethod.LateUpdate)
SetCartPosition(m_Position + Speed * Time.deltaTime);
}
public void ResetAndInit(CinemachinePath followPath, List<int> restIndexList, float magneticDistance)
{
if (followPath == null || restIndexList == null) return;
if (Path)
{
Path = null;
}
if (m_RestIndexList != null)
{
m_RestIndexList = null;
}
m_MagneticDistance = magneticDistance;
Path = followPath;
m_RestIndexList = restIndexList;
ResamplePath();
}
void SetCartPosition(float distanceAlongPath)
{
if (Path != null)
{
m_Position = Path.StandardizeUnit(distanceAlongPath, m_PositionUnits);
if (!IsAlwaysMoving) m_Position = CheckPosition(distanceAlongPath, m_Position);
transform.position = Path.EvaluatePositionAtUnit(m_Position, m_PositionUnits);
transform.rotation = Path.EvaluateOrientationAtUnit(m_Position, m_PositionUnits);
}
}
private void CheckTestRest()
{
if (m_IsTestRest)
{
if (m_TestRestIndex >= 0 && m_TestRestIndex < m_RestIndexList.Count)
{
m_MoveIndex = m_TestRestIndex;
if (!IsEffective()) return;
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
}
}
}
List<Vector3[]> m_RestPointDistance = new List<Vector3[]>();
private void ResamplePath()
{
int stepsPerSegment = Path.DistanceCacheSampleStepsPerSegment;
float minPos = Path.MinPos;
float maxPos = Path.MaxPos;
float stepSize = 1f / Mathf.Max(1, stepsPerSegment);
// Sample the positions
int numKeys = Mathf.RoundToInt((maxPos - minPos) / stepSize) + 1;
float[] m_PosToDistance = new float[numKeys];
m_RestPointDistance.Clear();
Vector3[] firstRestDistance = new Vector3[2];
Vector3 firstDest = new Vector3(-m_MagneticDistance, 0f, m_MagneticDistance);
firstRestDistance[0] = firstDest;
m_RestPointDistance.Add(firstRestDistance);
int index = 0;
float m_PathLength = 0f;
Vector3 p0 = Path.EvaluatePosition(0);
m_PosToDistance[0] = 0;
float pos = minPos;
for (int i = 1; i < numKeys; ++i)
{
pos += stepSize;
Vector3 p = Path.EvaluatePosition(pos);
float d = Vector3.Distance(p0, p);
m_PathLength += d;
p0 = p;
m_PosToDistance[i] = m_PathLength;
if (i % stepsPerSegment == 0)
{
Vector3[] tmpArr = new Vector3[1];
Vector3 tmp = new Vector3(m_PathLength - m_MagneticDistance, m_PathLength, m_PathLength + m_MagneticDistance);
tmpArr[0] = tmp;
m_RestPointDistance.Add(tmpArr);
++index;
}
}
if (Path.Looped)
m_RestPointDistance.RemoveAt(index);
Vector3 lastDest = new Vector3(m_PathLength - m_MagneticDistance, m_PathLength, m_PathLength + m_MagneticDistance);
firstRestDistance[1] = lastDest;
}
private bool IsEffective()
{
return (m_MoveIndex >= 0 && m_MoveIndex < m_RestIndexList.Count && m_RestIndexList.Count > 0) ? true : false;
}
public int RestCount
{
get
{
if (m_RestIndexList == null) return 0;
return m_RestIndexList.Count;
}
}
public int MoveIndex
{
get => m_MoveIndex;
}
public int ForwardToNextRest()
{
m_MoveIndex++;
if (m_MoveIndex > m_RestIndexList.Count - 1)
{
if (Path.Looped)
m_MoveIndex = 0;
else
m_MoveIndex = m_RestIndexList.Count - 1;
}
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
if (Speed < 0)
{
Speed = -Speed;
}
return m_MoveIndex;
}
public int BackwardToNextRest()
{
m_MoveIndex--;
if (m_MoveIndex < 0)
{
if (Path.Looped)
m_MoveIndex = m_RestIndexList.Count - 1;
else
m_MoveIndex = 0;
}
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
if (Speed > 0)
{
Speed = -Speed;
}
return m_MoveIndex;
}
public int JumpToNextRestForward()
{
JumpToRestIndex(++m_MoveIndex);
return m_MoveIndex;
}
public int JumpToNextRestBackward()
{
JumpToRestIndex(--m_MoveIndex);
return m_MoveIndex;
}
public int JumpToRestIndex(int index)
{
m_MoveIndex = index;
if (m_MoveIndex < 0)
{
if (Path.Looped)
m_MoveIndex = m_RestIndexList.Count - 1;
else
m_MoveIndex = 0;
}
else if (m_MoveIndex > m_RestIndexList.Count - 1)
{
if (Path.Looped)
m_MoveIndex = 0;
else
m_MoveIndex = m_RestIndexList.Count - 1;
}
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
var tmpArr = m_RestPointDistance[m_CurPathIndex];
Vector3 boundary = tmpArr[0];
float distanceAlongPath = boundary.y;
m_Position = Path.StandardizeUnit(distanceAlongPath, m_PositionUnits);
SetCartPosition(m_Position);
m_State = MoveState.Stationary;
return m_MoveIndex;
}
public void GoToPositionIndex(int index)
{
m_CurPathIndex = index;
m_State = MoveState.Moving;
}
float CheckPosition(float distanceAlongPath, float distance)
{
if (m_CurPathIndex < 0 || m_CurPathIndex >= m_RestPointDistance.Count) return distance;
var tmpArr = m_RestPointDistance[m_CurPathIndex];
int count = tmpArr.Length;
if (count == 0) return distance;
if (m_CurPathIndex == 0)
{
if (Speed > 0f)
{
if (distanceAlongPath >= Path.PathLength)
{
m_State = MoveState.Stationary;
m_IsTestRest = false;
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
return tmpArr[0].y;
}
}
else if (Speed < 0f)
{
if (distanceAlongPath <= 0f)
{
m_State = MoveState.Stationary;
m_IsTestRest = false;
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
return tmpArr[0].y;
}
}
}
else
{
if (Speed > 0f)
{
if (distance >= tmpArr[0].x)
{
m_State = MoveState.Stationary;
m_IsTestRest = false;
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
return tmpArr[0].y;
}
}
else if (Speed <= 0f)
{
if (distance <= tmpArr[0].z)
{
m_State = MoveState.Stationary;
m_IsTestRest = false;
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
return tmpArr[0].y;
}
}
}
return distance;
}
}
}