using Spine.Unity; using TMPro; using UnityEngine; public class DispatchersController : MonoBehaviour { enum DispatcherState : byte { Idle, Moving, MissionProgressing, BackToBase, } [SerializeField] SkeletonGraphic[] dispatcherAnims; [SerializeField] RectTransform startPosition; [SerializeField] LineBetweenObjects lineBetweenOriginToButton; [SerializeField] TextMeshProUGUI moveRemainTimeText; DispatchData.Area targetArea; DispatcherState state; Vector2 targetPos; float moveElapsedTime; RectTransform rt => (RectTransform)transform; private void LateUpdate() { if (targetArea is null) return; DispatcherState prevState = state; SetTimersAndStateOfCurrent(); bool isMoving = false; switch (state) { case DispatcherState.Moving: { ChangeLookDirection(targetPos - rt.anchoredPosition); rt.anchoredPosition = Vector2.Lerp(startPosition.anchoredPosition, targetPos, moveElapsedTime / targetArea.MissionMoveTime); isMoving = true; } break; case DispatcherState.MissionProgressing: { rt.anchoredPosition = targetPos; } break; case DispatcherState.BackToBase: { ChangeLookDirection(startPosition.anchoredPosition - rt.anchoredPosition); rt.anchoredPosition = Vector2.Lerp(targetPos, startPosition.anchoredPosition, moveElapsedTime / targetArea.MissionMoveTime); isMoving = true; } break; } if(prevState != state) SetDispatcherAnimByState(); lineBetweenOriginToButton?.gameObject.SetActive(state != DispatcherState.Idle); moveRemainTimeText?.gameObject.SetActive(isMoving); if(isMoving) { float remainTime = targetArea.MissionMoveTime - moveElapsedTime; moveRemainTimeText?.SetText(FormatString.TextTime((int)remainTime)); } } private void SetTimersAndStateOfCurrent() { var now = TimeUtils.Now(); if (targetArea.Mission.EndTime >= now) { var missionStartTime = targetArea.Mission.EndTime.AddSeconds(-targetArea.Mission.TotalProgressTime); float curProgressTimeSec = (float)(now - missionStartTime).TotalSeconds; if (curProgressTimeSec < targetArea.MissionMoveTime) { state = DispatcherState.Moving; moveElapsedTime = curProgressTimeSec; } else if (curProgressTimeSec < targetArea.MissionMoveTime + targetArea.MissionProgressTime) { state = DispatcherState.MissionProgressing; } else if (curProgressTimeSec < targetArea.Mission.TotalProgressTime) { state = DispatcherState.BackToBase; moveElapsedTime = curProgressTimeSec - targetArea.MissionMoveTime - targetArea.MissionProgressTime; } } else { state = DispatcherState.Idle; } } private void SetDispatcherAnimByState() { string animName = GetAnimNameByState(); for(int i = 0; i < dispatcherAnims.Length; i++) dispatcherAnims[i].AnimationState.SetAnimation(0, animName, true); } private string GetAnimNameByState() { switch (state) { case DispatcherState.Idle: return "idle"; case DispatcherState.Moving: return "move"; case DispatcherState.MissionProgressing: return "attack"; case DispatcherState.BackToBase: return "move"; } return "idle"; } public void SetDispatch(RectTransform targetPos, DispatchData.Area targetArea) { this.targetArea = targetArea; this.targetPos = targetPos.anchoredPosition; for (int i = 0; i < targetArea.EmployeeIDs.Count; i++) { if (MateDataGroup.Instance.TryGetMateData(targetArea.EmployeeIDs[i], out var mateData)) SetDispatcher(i, mateData); else SetDispatcher(i, null); } lineBetweenOriginToButton?.SetStart(startPosition); lineBetweenOriginToButton?.SetEnd(targetPos); state = DispatcherState.Idle; } private void SetDispatcher(int index, MateData mateData) { if (index < 0 || index >= dispatcherAnims.Length) return; var anim = dispatcherAnims[index]; if(mateData is null) { anim.gameObject.SetActive(false); } else { anim.skeletonDataAsset = mateData.SkeletonDataAsset; anim.Initialize(true); } } private void ChangeLookDirection(Vector2 lookDirection) { Vector3 rot = Vector3.zero; if (lookDirection.x < 0) rot = Global.V3_RotRev; for (int i = 0; i < dispatcherAnims.Length; i++) dispatcherAnims[i].transform.rotation = Quaternion.Euler(rot); } }