using System; using System.Collections.Generic; using Gameplay.Character; using Gameplay.Level; using Gameplay.Vehicle.Impl; using LTGame; using UnityEngine; namespace Gameplay.Vehicle.State { public class VehicleStateMove : BaseVehicleState { private List _tgsPath; private int _currentPathIndex; private Map _map; private Vector3 _targetPosition; private int _lastTargetCellIndex; private readonly List _roadPointList; private float _lastMoveSpeed; private int _loopAudioId; public VehicleStateMove(NormalVehicle owner) : base(owner, EVehicleState.Move) { _tgsPath = new List(); _roadPointList = new List(); } protected override void _OnEnter(NBaseState exitState, object param) { base._OnEnter(exitState, param); _lastTargetCellIndex = owner.controlData.targetCellIndex; _map = LevelManager.Instance.CurrentLevel.Map; // 初始化路径 _FindPath(); if (isFinished) return; owner.statusData.isMoveing = true; owner.vAnim.targetAnim = "move"; _PlayLoopAudio(); } private void _PlayLoopAudio() { _loopAudioId = -1; if (string.IsNullOrEmpty(owner.configData.audioData.walkLoopAudioId)) { return; } _loopAudioId = AudioManager.Instance.PlayAudio(owner.configData.audioData.walkLoopAudioId, AudioCriManager.EPlayType.Sound, owner.Node.GameObject, true); } protected override void _OnRunning() { base._OnRunning(); owner.fightData.lastMoveTime = LevelManager.Instance.CurrentLevel.LevelTime; if (owner.aliveData.currentHp <= 0) { isFinished = true; nextState = EVehicleState.Destroy; return; } // 如果目标改变,则重新寻路 if (_lastTargetCellIndex != owner.controlData.targetCellIndex) { isFinished = true; nextState = EVehicleState.Move; return; } // 持续判断当前索引格子是否可移动 var currentMoveCellIndex = _tgsPath[_currentPathIndex]; var islocalMove = currentMoveCellIndex == owner.transData.cellIndex; if (!islocalMove) { // 同方格移动,不处理 var canMove = PathFinder.CanPass(currentMoveCellIndex, owner); if (!canMove) { isFinished = true; nextState = EVehicleState.Move; return; } } _DoMove(); } protected override void _OnExit(NBaseState exitState, object param) { base._OnExit(exitState, param); owner.statusData.isMoveing = false; if (_loopAudioId != 0) { AudioManager.Instance.StopSoundById(_loopAudioId); } _PlayStopAudio(); } private void _PlayStopAudio() { if (string.IsNullOrEmpty(owner.configData.audioData.walkStopAudioId)) { return; } AudioManager.Instance.PlayAudio(owner.configData.audioData.walkStopAudioId, AudioCriManager.EPlayType.Sound, owner.Node.GameObject); DebugUtil.LogG("播放停止音效:" + owner.configData.audioData.walkStopAudioId); } private void _DoMove() { if (!_DirectMoveTo(_targetPosition, deltaTime)) { // 还在走,就继续走 return; } // 到达转折点 _currentPathIndex++; if (_currentPathIndex >= _tgsPath.Count) { if (owner.controlData.targetCellIndex != owner.transData.cellIndex) { // 重新寻路 isFinished = true; nextState = EDownState.Move; return; } // 到达终点 _ArriveBlock(); } else { var newCellIndex = _tgsPath[_currentPathIndex]; // 更新目标点 _targetPosition = _map.TGSCellIndex2WorldPosition(newCellIndex); } } private void _ArriveBlock() { isFinished = true; nextState = EVehicleState.Stop; owner.controlData.targetCellIndex = -1; owner.controlData.markEnemy = null; Framework.EventManager.Instance.Send(Framework.EventManager.EventName.LevelCharacterArriveBlock, owner); } private bool _DirectMoveTo(Vector3 pos, float dt) { var currentPos = owner.transData.pos; var toTarget = pos - currentPos; toTarget.y = 0; _RotateToBlock(toTarget, dt); var requireDistance = toTarget.magnitude; var moveSpeed = owner.fightData.GetMoveSpeed(); var moveDt = dt * moveSpeed; if (moveDt < requireDistance) { var moveDir = toTarget.normalized; var moveDistance = moveDt * moveDir; var newPos = currentPos + moveDistance; owner.transData.pos = newPos; return false; } else { // 直接到达目标点 owner.transData.pos = pos; return true; } } private void _RotateToBlock(Vector3 toTarget, float dt) { var toAngle = Vector3.SignedAngle(Vector3.forward, toTarget, Vector3.up); var currentAngle = owner.transData.yaw; if (Math.Abs(toAngle - currentAngle) > 0.1f) { var turnSpeed = owner.fightData.turnSpeed; var turnDt = dt * turnSpeed; var newAngle = Mathf.MoveTowardsAngle(currentAngle, toAngle, turnDt); owner.transData.yaw = newAngle; } } private bool _IsFathExist() { return !(_tgsPath == null || _tgsPath.Count <= 0); } private void _FindPath() { if (_map == null) return; _roadPointList.Clear(); _currentPathIndex = 0; var to = owner.controlData.targetCellIndex; var from = owner.transData.cellIndex; _tgsPath = PathFinder.FindPath(_map, to, owner); // 再次判定是否可以直接走通 if (_IsFathExist()) { _targetPosition = _map.TGSCellIndex2WorldPosition(_tgsPath[_currentPathIndex]); } else { owner.Log($"无有效路径: from:{from} to:{to}"); isFinished = true; nextState = EDownState.Idle; // 停止到当前节点 owner.StopToCurrentCell(); } for (var i = _tgsPath.Count - 1; i >= 0; --i) { var tgsIndex = _tgsPath[i]; var worldPos = _map.TGSCellIndex2WorldPosition(tgsIndex); _roadPointList.Add(worldPos); } if (!_tgsPath.Contains(owner.controlData.targetCellIndex)) { var targetPos = _map.TGSCellIndex2WorldPosition(owner.controlData.targetCellIndex); _roadPointList.Insert(0, targetPos); } } public List CalcRoadLine() { return _roadPointList; } public int GetCurrentIndex() { return _currentPathIndex; } } }