using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; using System.Linq; using System; using Cysharp.Threading.Tasks; //工人是固定的跟随模式,监工是随机分配的,场上的监工数量会比实际更多 //分配监工 // 1.分配都是新的监工 一定从起点开始 // 2.撤回的可以从半路撤回 public class GoldRushTentCell : MonoBehaviour { [SerializeField] Button tentBtn; [SerializeField] GameObject funcGo; [SerializeField] GameObject lockCntGo; //淘金次数解锁 [SerializeField] Text lockCntText; [SerializeField] Button unLockBtn; [SerializeField] GameObject lockMoneyGo; [SerializeField] Button unlockMoneyBtn; //货币解锁 [SerializeField] Image unlockMoneyIcon; [SerializeField] Image unlockMoneyRedpoint; [SerializeField] Text unlockMoneyText; [SerializeField] GameObject goldRushMissionWaitGo; //未发布任务 [SerializeField] GameObject goldRushMissionWorkingGo; //已发布任务 [SerializeField] Text goldRushItemText; [SerializeField] Image workingProcess; [SerializeField] UIEffectPlayer refreshItemEffect; [SerializeField] Text workingText; //外出中 [SerializeField] UIHeroController[] workerArr; //小兵跟随 [SerializeField] RectTransform[] workerGoArr; [SerializeField] RectTransform[] hidePosArr; //未解锁时 屏幕外坐标 [SerializeField] RectTransform[] startPosArr; //起点 站岗坐标 [SerializeField] GoldRushPosEvent[] pathPointArr; //移动点 [SerializeField] UIAlphaTween[] wordArr; [SerializeField] Text[] textArr; [SerializeField] GoldRushLeader tmpLeader; //监工 [SerializeField] Transform leaderParent; [SerializeField] GoldRushPosEvent[] leaderPathPointArr; public int campID = 0; //小兵工人 Tween[] sequenceArr = new Tween[3]; Dictionary workerPosDic = new Dictionary(); //工人已达移动点 List workingLeaderList = new List(); //正在工作的监工 和分配列表一致 List callBackLeaderList = new List(); //返程的监工(完工的 和 被召回的) Queue poolLeaderList = new Queue(); //监工池 int workState = -1; // - 1未解锁 0 站岗 1 前进 2 返程 int leaderCount = 0; //当前监工数量 void Start() { Init(); tentBtn.AddListener(ClickTent); unlockMoneyBtn.AddListener(ClickUnlockMoney); unLockBtn.AddListener(ClickUnlock); } void OnEnable() { GoldRushManager.Instance.PathEvent += PathEvent; GoldRushManager.Instance.OnGoldRushCampEvent += OnGoldRushCampEvent; GoldRushManager.Instance.OnGoldRushInfoEvent += Display; GoldRushManager.Instance.OnRefreshItemEvent += OnRefreshItemEvent; GlobalTimeEvent.Instance.secondEvent += OnSecondEvent; PlayerDatas.Instance.playerDataRefreshEvent += OnPlayerDataRefreshEvent; leaderCount = GoldRushManager.Instance.GetCampWorkerCnt(campID); Display(); } void OnDisable() { GoldRushManager.Instance.PathEvent -= PathEvent; GoldRushManager.Instance.OnGoldRushCampEvent -= OnGoldRushCampEvent; GoldRushManager.Instance.OnGoldRushInfoEvent -= Display; GoldRushManager.Instance.OnRefreshItemEvent -= OnRefreshItemEvent; GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent; PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerDataRefreshEvent; } void OnPlayerDataRefreshEvent(PlayerDataType type) { if (type == GoldRushManager.Instance.unLockMoneyType) { if (GoldRushManager.Instance.GetCampLockState(campID) == 2) { var campConfig = GoldRushCampConfig.Get(campID); unlockMoneyRedpoint.SetActive(UIHelper.CheckMoneyCount(campConfig.MoneyUnlock[0], campConfig.MoneyUnlock[1], 0)); } } } void FixFollowWoker(int lockState) { //跟随小兵如果在外出中,且没有监工,则隐藏 if (workingLeaderList.Count == 0 && callBackLeaderList.Count == 0 && workState <= 0 && GoldRushManager.Instance.GetCampEndTime(campID) != 0) { for (int i = 0; i < workerArr.Length; i++) { workerGoArr[i].localPosition = hidePosArr[i].localPosition; } return; } // 初始状态 if (lockState != 0) { //未解锁 显示隐藏坐标 for (int i = 0; i < workerArr.Length; i++) { workerGoArr[i].localPosition = hidePosArr[i].localPosition; } } else if (workState == -1 && lockState == 0) { //解锁的时候,如果不在起点则跑步过去 workState = 0; for (int i = 0; i < sequenceArr.Length; i++) { sequenceArr[i].Kill(); var worker = workerArr[i]; worker.PlayAnimation("run", true, false); sequenceArr[i] = workerGoArr[i].DOLocalMove(startPosArr[i].localPosition, 1f).SetEase(Ease.Linear); sequenceArr[i].OnComplete(() => { worker.PlayAnimation("idle", true, false); }); } } } void OnGoldRushCampEvent(int _campID) { if (_campID != campID) return; var realCount = GoldRushManager.Instance.GetCampWorkerCnt(campID); if (realCount > leaderCount) { //分配监工 GoldRushEvent(campID, 0, realCount - leaderCount); } else if (realCount < leaderCount) { //召回监工 GoldRushEvent(campID, 1, leaderCount - realCount); } leaderCount = realCount; Display(); } void OnRefreshItemEvent(int _campID) { if (_campID != campID) return; refreshItemEffect.Play(); } void Display() { if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.GoldRush)) { funcGo.SetActive(false); return; } funcGo.SetActive(true); var campConfig = GoldRushCampConfig.Get(campID); int lockState = GoldRushManager.Instance.GetCampLockState(campID); if (lockState == 1) { if (GoldRushManager.Instance.panningCnt < campConfig.PanningUnlock) { lockCntGo.SetActive(true); unLockBtn.SetActive(false); lockCntText.text = Language.Get("GoldRush32", GoldRushManager.Instance.panningCnt, campConfig.PanningUnlock); } else { lockCntGo.SetActive(false); unLockBtn.SetActive(true); } lockMoneyGo.SetActive(false); goldRushMissionWaitGo.SetActive(false); goldRushMissionWorkingGo.SetActive(false); } else if (lockState == 2) { lockCntGo.SetActive(false); unLockBtn.SetActive(false); lockMoneyGo.SetActive(true); unlockMoneyRedpoint.SetActive(UIHelper.CheckMoneyCount(campConfig.MoneyUnlock[0], campConfig.MoneyUnlock[1], 0)); unlockMoneyIcon.SetIconWithMoneyType(campConfig.MoneyUnlock[0]); unlockMoneyText.text = campConfig.MoneyUnlock[1].ToString(); goldRushMissionWaitGo.SetActive(false); goldRushMissionWorkingGo.SetActive(false); } else { lockCntGo.SetActive(false); unLockBtn.SetActive(false); lockMoneyGo.SetActive(false); var goldID = GoldRushManager.Instance.GetCampGoldID(campID); if (goldID == 0) { goldRushMissionWaitGo.SetActive(true); goldRushMissionWorkingGo.SetActive(false); } else { goldRushMissionWaitGo.SetActive(false); goldRushMissionWorkingGo.SetActive(true); var goldConfig = GoldRushItemConfig.Get(goldID); goldRushItemText.text = GoldRushManager.Instance.GetCampItemName(goldConfig); var endTime = GoldRushManager.Instance.GetCampEndTime(campID); if (endTime == 0) { //未开始 workingText.text = ""; workingProcess.fillAmount = 0; } else { //按原总时长当进度条 workingProcess.fillAmount = (goldConfig.NeedSeconds - (GoldRushManager.Instance.GetCampEndTime(campID) - TimeUtility.AllSeconds)) / (float)goldConfig.NeedSeconds; } } } FixFollowWoker(lockState); } void OnSecondEvent() { //进度条和 外出中文字 int lockState = GoldRushManager.Instance.GetCampLockState(campID); if (lockState != 0) { return; } var goldID = GoldRushManager.Instance.GetCampGoldID(campID); if (goldID == 0) { return; } var endTime = GoldRushManager.Instance.GetCampEndTime(campID); if (endTime == 0) { return; } var addStr = new string('.', (int)Time.time % 4); workingText.text = Language.Get("GoldRush37") + addStr; var goldConfig = GoldRushItemConfig.Get(goldID); //按原总时长当进度条 workingProcess.fillAmount = (goldConfig.NeedSeconds - (GoldRushManager.Instance.GetCampEndTime(campID) - TimeUtility.AllSeconds)) / (float)goldConfig.NeedSeconds; } void GoldRushEvent(int _campID, int eventType, int leaderCount) { if (_campID != campID) { return; } if (eventType == 0) { //出发 AssignLeader(leaderCount); } else if (eventType == 1) { //返程 CallBackLeader(leaderCount); } } void Init() { for (int i = 0; i < workerArr.Length; i++) { workerPosDic[i] = -1; //-1代表起点,站岗坐标 wordArr[i].SetEndState(); } } public void StartMove(bool isBack) { for (int i = 0; i < sequenceArr.Length; i++) { sequenceArr[i].Kill(); WorkerMove(isBack, i); } } void WorkerMove(bool isBack, int workerIndex) { var worker = workerArr[workerIndex]; var workerGo = workerGoArr[workerIndex]; int curIndex = workerPosDic[workerIndex]; int moveIndex = isBack ? curIndex - 1 : curIndex + 1; GoldRushPosEvent pathPosEvent = isBack ? pathPointArr[curIndex] : pathPointArr[moveIndex]; //判断事件, 当前点或者下一个点 Vector3 nextPos; if (moveIndex <= -1) { moveIndex = -1; nextPos = startPosArr[workerIndex].localPosition; } else { if (moveIndex >= pathPointArr.Length) { moveIndex = pathPointArr.Length - 1; } nextPos = pathPointArr[moveIndex].transform.localPosition; } worker.PlayAnimation("run", true, false); workerPosDic[workerIndex] = moveIndex; bool isRush = pathPosEvent.m_PosEvent == PosEvent.Rush; bool isJump = pathPosEvent.m_PosEvent == PosEvent.Jump; worker.SetSpeed((isRush ? 2 : 1) * (isBack ? 0.5f : 1)); // 先出发的终点要往前一点 Vector3 offset = Vector3.zero; if (moveIndex == pathPointArr.Length - 1) { offset = new Vector3((pathPointArr.Length - workerIndex - 1) * 70, 0, 0); } var endPos = nextPos - offset; var dis = Vector3.Distance(workerGo.localPosition, endPos); var duration = dis / pathPosEvent.m_Speed / (isBack ? pathPosEvent.m_BackSlowSpeedScale : 1); // Debug.Log("第" + workerIndex + "个工人" + " duration" + duration + " 移动index " + moveIndex + " Time=" + Time.time); if (workerGo.localPosition.x < endPos.x) { worker.transform.localRotation = Quaternion.Euler(0, 0, 0); } else { //转向 worker.transform.localRotation = Quaternion.Euler(0, 180, 0); } if (!isJump) { sequenceArr[workerIndex] = workerGo.DOLocalMove(endPos, duration).SetEase(pathPosEvent.m_EaseType); } else { //抛物线跳跃 // 计算抛物线路径点 Vector3[] path = new Vector3[3]; path[0] = workerGo.localPosition; // 起点 //顶点x 是两者之间 y增加高度 path[1] = new Vector3(endPos[0] + (workerGo.localPosition.x - endPos[0]) / 2, endPos[1] + pathPosEvent.m_Value1, nextPos.z); path[2] = endPos; // 终点 // 使用 DOPath 实现抛物线移动 sequenceArr[workerIndex] = workerGo.DOLocalPath(path, pathPosEvent.m_Value2, PathType.CatmullRom).SetEase(pathPosEvent.m_EaseType); } sequenceArr[workerIndex].OnComplete(() => { // Debug.Log("Sequence completed for worker " + workerIndex); if (moveIndex == (isBack ? -1 : pathPointArr.Length - 1)) { worker.PlayAnimation("idle", true, false); worker.transform.localRotation = Quaternion.Euler(0, 0, 0); if (moveIndex == -1) { workState = 0; } return; } WorkerMove(isBack, workerIndex); }); } void PathEvent(PosEvent posEvent, bool isBack, int _tendID, int index, string content) { if (_tendID != campID) return; if (posEvent == PosEvent.TargetFollow) { if (isBack) return; // 已经在外出中不跟随 if (workState == 1) return; StartMove(false); workState = 1; } else if (posEvent == PosEvent.TargetWord) { wordArr[index].SetActive(true); wordArr[index].Play(); textArr[index].text = Language.Get(content); ForceRefreshLayout(); } else if (posEvent == PosEvent.TargetAction) { for (int i = 0; i < wordArr.Length; i++) { workerArr[i].PlayAnimation(content); } } } /// /// 强制刷新Layout,解决嵌套Layout和ContentSizeFitter的重叠问题 /// async UniTask ForceRefreshLayout() { await UniTask.DelayFrame(2); foreach (var word in wordArr) { LayoutRebuilder.ForceRebuildLayoutImmediate(word.GetComponent()); } } void AssignLeader(int addCount) { //不同营地之间错位出发 float addTime = 0; var curTime = Time.time; if (curTime - GoldRushManager.Instance.lastAssignWorkTime < 0.2f) { addTime = 0.2f - (curTime - GoldRushManager.Instance.lastAssignWorkTime); } if (addTime != 0) { GoldRushManager.Instance.lastAssignWorkTime += 0.2f; } else { GoldRushManager.Instance.lastAssignWorkTime = curTime; } //分配的时候加新的监工 for (int i = 0; i < addCount; i++) { float waitTime = i * 0.3f + addTime; var newLeader = RequestLeader(); workingLeaderList.Add(newLeader); newLeader.Init(leaderPathPointArr, waitTime, campID, i, false, (bool value) => { //是否返程 if (!value) { workingLeaderList.Remove(newLeader); ReturnLeader(newLeader); } }); } } GoldRushLeader RequestLeader() { if (poolLeaderList.Count == 0) { return Instantiate(tmpLeader, leaderParent); } return poolLeaderList.Dequeue(); } void ReturnLeader(GoldRushLeader leader) { poolLeaderList.Enqueue(leader); } //半路召回的,拉货回来的 void CallBackLeader(int callBackCount) { //不同营地之间错位出发 float addTime = 0; var curTime = Time.time; if (curTime - GoldRushManager.Instance.lastCallBackTime < 0.2f) { addTime = 0.2f - (curTime - GoldRushManager.Instance.lastCallBackTime); } if (addTime != 0) { GoldRushManager.Instance.lastCallBackTime += 0.2f; } else { GoldRushManager.Instance.lastCallBackTime = curTime; } bool followBack = false; bool forcrCallBack = false; if (GoldRushManager.Instance.forceStopCampID == campID) { forcrCallBack = true; GoldRushManager.Instance.forceStopCampID = 0; } //从workingLeaderList 中取出最后面调回的监工,不够的新建 for (int i = 0; i < callBackCount; i++) { if (workingLeaderList.Count > 0) { //半路拉回来的 var leader = workingLeaderList[workingLeaderList.Count - 1]; //原样显示 callBackLeaderList.Add(leader); workingLeaderList.Remove(leader); leader.StartLeaderMove(true); leader.forcrCallBack = forcrCallBack; leader.OnComplete = (bool value) => { callBackLeaderList.Remove(leader); ReturnLeader(leader); }; if (workingLeaderList.Count == 0 && workState == 1) { followBack = true; } } else { float waitTime = i * 0.6f + addTime; var newLeader = RequestLeader(); callBackLeaderList.Add(newLeader); int index = Math.Max(leaderCount - i - 1, 0); //从后往前召回 newLeader.Init(leaderPathPointArr, waitTime, campID, index, true, (bool value) => { if (value) { //返回的监工 callBackLeaderList.Remove(newLeader); ReturnLeader(newLeader); } }); newLeader.forcrCallBack = forcrCallBack; if (workState == -1) { //重登的时候,外出的修复状态 workState = 1; var keys = workerPosDic.Keys.ToList(); for (int k = 0; k < keys.Count; k++) { workerPosDic[keys[k]] = pathPointArr.Length - 1; } } if (workingLeaderList.Count == 0 && workState == 1) { followBack = true; } } } if (followBack && GoldRushManager.Instance.GetCampWorkerCnt(campID) == 0) { StartMove(true); workState = 2; } } void ClickTent() { if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.GoldRush, true)) { return; } var lockState = GoldRushManager.Instance.GetCampLockState(campID); if (lockState != 0) { return; } var goldID = GoldRushManager.Instance.GetCampGoldID(campID); if (goldID != 0) { GoldRushManager.Instance.selectCampID = campID; UIManager.Instance.OpenWindow(); return; } if (!UIHelper.CheckMoneyCount(52, 1, 1)) { return; } GoldRushManager.Instance.SendGoldRushOP(0, campID, 0); } void ClickUnlockMoney() { int lockState = GoldRushManager.Instance.GetCampLockState(campID); if (lockState != 2) { return; } var config = GoldRushCampConfig.Get(campID); ConfirmCancel.MoneyIconToggleConfirmByType(ToggleCheckType.GoldRush, config.MoneyUnlock[1], config.MoneyUnlock[0], Language.Get("GoldRush35", UIHelper.GetIconNameWithMoneyType(config.MoneyUnlock[0]), config.MoneyUnlock[1]), () => { if (!UIHelper.CheckMoneyCount(config.MoneyUnlock[0], config.MoneyUnlock[1], 2)) { return; } GoldRushManager.Instance.SendGoldRushUnlock(0, campID); refreshItemEffect.Play(); SysNotifyMgr.Instance.ShowTip("GoldRush8"); }); } //达到可解锁条件 需手动解锁 void ClickUnlock() { int lockState = GoldRushManager.Instance.GetCampLockState(campID); if (lockState != 1) { return; } var config = GoldRushCampConfig.Get(campID); if (GoldRushManager.Instance.panningCnt < config.PanningUnlock) return; GoldRushManager.Instance.SendGoldRushUnlock(0, campID); refreshItemEffect.Play(); SysNotifyMgr.Instance.ShowTip("GoldRush8"); } }