using System.Collections.Generic; using TH1_Renderer.UnitAtomAnim; using TH1Renderer; using UnityEngine; namespace TH1_Anim.UnitAtomAnim { public class UnitAtomAnimMove : IUnitAtomAnim { private UnitAtomAnimMoveData _data; private Vector3 _originPos; private Vector3 _targetPos; public UnitAtomAnimMove(IUnitAtomAnimData data) : base() { _data = data as UnitAtomAnimMoveData; State = UnitAtomAnimState.Prepare; } public override bool OnStart(UnitMono unitMono) { if (_data == null) { return false; } Duration = Table.Instance.AnimDataAssets.AttackAnimTime; if(_data.Path != null) Duration = Table.Instance.AnimDataAssets.AttackAnimTime / 2f * _data.Path.Count; _originPos = Table.Instance.GridPosToWorld(_data.OriginGridPos, "isUnit"); _targetPos = Table.Instance.GridPosToWorld(_data.TargetGridPos, "isUnit"); UpdateDirection(unitMono,_data.OriginGridPos,_data.TargetGridPos); return true; } public Vector3 GetPositionOnPath(List path2, float t) { if (path2 == null || path2.Count == 0) return Vector3.zero; var path = new List(); foreach (var p in path2) path.Add(Table.Instance.GridPosToWorld(p, "isUnit")); // 边界情况 if (path.Count == 1) return path[0]; // 计算总路程 float totalLength = 0; for (int i = 0; i < path.Count - 1; i++) { totalLength += Vector3.Distance(path[i], path[i+1]); } if (totalLength <= 0) return path[0]; // 确定目标移动距离 float targetDistance = totalLength * Mathf.Clamp01(t); float distanceCovered = 0; // 找到目标点所在的线段 for (int i = 0; i < path.Count - 1; i++) { float segmentLength = Vector2.Distance(path[i], path[i + 1]); if (distanceCovered + segmentLength >= targetDistance) { // 在此线段内进行插值 float distanceIntoSegment = targetDistance - distanceCovered; float segmentT = distanceIntoSegment / segmentLength; return Vector2.Lerp(path[i], path[i + 1], segmentT); } distanceCovered += segmentLength; } // 如果 t >= 1,直接返回终点 return path[path.Count - 1]; } public override void OnUpdate(UnitMono unitMono,float progressTime) { if (unitMono == null) return; float t = Mathf.Clamp(progressTime / Duration,0f,1f); //如果是直接移动过去 if(_data.Path == null) unitMono.gameObject.transform.position = Vector3.Lerp(_originPos, _targetPos, t); else { unitMono.gameObject.transform.position = GetPositionOnPath(_data.Path,t); } //Debug.Log($"{Time.time} / {progressTime} : {_originPos} -> {_targetPos} now @ {unitMono.gameObject.transform.position}"); } } }