//- 显示用户头像列表 // // using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using asap.core; using DG.Tweening; using game; using Game; using UniRx; using UnityEngine; using Random = UnityEngine.Random; //- public class ChallengeMoveToNextStageEvent { public int newStep; public int residual; } namespace GampPlay.ChallengeMatch.Road { public class ChallengeMatchPlayers : MonoBehaviour { //- [Header("头像")] public GameObject eventChallengeHead; //- [Header("区域")] public ChallengeMatchSceneUIRegion[] uiRegion; [Header("区域")] public ChallengeMatchSceneUIRegion uiStartRegion; // -初始区域 public ChallengeMatchSceneUIRegion uiMoveRegion; //- 车上区域 [Header("左边抛洒")] public int[] stepThrowLeft; [Header("右边抛洒")] public int[] stepThrowRight; [Header("跳跃动画Key")] private string JumpKey = "fx_anim_eventchallengehead_jump_success_01"; [Header("跳跃动画失败Key")] private string JumpFailKey = "fx_anim_eventchallengehead_jump_success_01"; [Header("本人起跳到其他人开始起跳")] public float jumpIntervalMy = 0.1f; [Header("其他人起跳开始间隔")] public float jumpInterval = 0.1f; [Header("每个人淘汰间隔")] public float eliminateInterval = 0.01f; [Header("跳到卡车时长")] public float jumpDuration = 0.6f; [Header("生成旗子时长")] public float flagUpDuration = 1f; //- [Header("几秒后开始扔下淘汰人员")] public float deltaTimeForEliminate = 0.2f; private FishingChallengeManager _fishingChallengeManager; // private readonly List _headList = new(); private CompositeDisposable _disposables = new(); private EventChallengeHead _myHead; private Canvas _canvas; //- 剩余数量 private int _residualHeadCount; private void Awake() { //- 设置相机 _canvas = transform.GetComponent(); _canvas.worldCamera = Camera.main; _fishingChallengeManager = GContext.container.Resolve(); GContext.OnEvent().Subscribe(ShowPlayer).AddTo(_disposables); GContext.OnEvent().Subscribe(OnFail).AddTo(_disposables); GContext.OnEvent().Subscribe(PlayAni).AddTo(_disposables); GContext.OnEvent().Subscribe(OnMoveNextStage).AddTo(_disposables); } private void Start() { } private void OnDisable() { _disposables?.Dispose(); _disposables = null; } private void OnDestroy() { } #region Game Logic private void ShowPlayer(ChallengeShowPlayerEvent challengeShowPlayerEvent) { var oldStep = challengeShowPlayerEvent.oldStep; var oldUIRegion = uiRegion[oldStep]; var posTran = oldUIRegion.posTran; var residual = posTran.Count; ELog($"ShowPlayer-> {oldStep} {residual}"); if (_headList.Count > 0) { _headList.ForEach(x => Destroy(x.gameObject)); _headList.Clear(); Destroy(_myHead.gameObject); } //- 剩余头像的数量 AddHeads(oldStep == 0 ? uiStartRegion : uiMoveRegion, residual); } private void AddHeads(ChallengeMatchSceneUIRegion curRegion, int residual) { var posTran = curRegion.posTran; var robots = GContext.container.Resolve().TbRobot.DataMap; var uiService = GContext.container.Resolve(); var myself = curRegion.myself; for (int i = 0; i < residual; i++) { var go = Instantiate(eventChallengeHead.gameObject, posTran[i]); go.transform.localScale = Vector3.one; go.transform.localPosition = Vector3.zero; go.name = "head_" + i; var head = go.GetComponent(); //- // if (i >= _fishingChallengeManager.fishingChallengeData.robotAccountList.Count) // { // var idx = Random.Range(0, _fishingChallengeManager.fishingChallengeData.robotAccountList.Count); // if (robots.TryGetValue(_fishingChallengeManager.fishingChallengeData.robotAccountList[idx], // out cfg.Robot robot)) // { // uiService.SetHeadImage(head.icon_head, robot.Avatar); // } // } // else { if (robots.TryGetValue(_fishingChallengeManager.fishingChallengeData.robotAccountList[i], out cfg.Robot robot)) { uiService.SetHeadImage(head.icon_head, robot.Avatar); } } _headList.Add(head); } _myHead = Instantiate(eventChallengeHead.gameObject, myself).GetComponent(); _myHead.transform.localScale = Vector3.one; _myHead.transform.localPosition = Vector3.zero; _myHead.bg_head_myself.SetActive(true); uiService.SetHeadImage(_myHead.icon_head, GContext.container.Resolve().AvatarUrl); _residualHeadCount = _headList.Count; } private async void OnFail(ChallengeFailEvent challengeFailEvent) { int oldStep = challengeFailEvent.oldStep; // var rectPos = uiRegion[oldStep].myselfRect; //淘汰动画 // float width = rectPos.rect.width / 2; // float height = rectPos.rect.height / 2; // Vector3 vector3 = new Vector3(UnityEngine.Random.Range(-width, width), UnityEngine.Random.Range(-height, height), 0); // _myHead.rectTransform.SetParent(rectPos); // _myHead.rectTransform.localScale = Vector3.one; // _myHead.rectTransform.DOLocalMove(vector3, 0.2f).SetEase(Ease.Linear); // _myHead.headAni.Play("fx_anim_eventchallengehead_jump_defeat_01"); // await Awaiters.Seconds(eliminateInterval * speed); var audioName = uiRegion[oldStep].fallAudioName; if (!string.IsNullOrEmpty(audioName)) { GContext.Publish(new EventUISound(audioName)); }; var throwDirection = GetThrowDirection(oldStep); _myHead.rectTransform.SetParent(headTrashTransform,worldPositionStays:true); var headWorldPos = _myHead.transform.position; _myHead.GetComponent().PerformArcJumpFailed(headWorldPos, throwDirection); // _myHead.headAni.Play(JumpFailKey); await Awaiters.Seconds(1f); challengeFailEvent.tcs.SetResult(true); } private ThrowDirection GetThrowDirection(int oldStep) { var throwDirection = ThrowDirection.TdLeft; if (stepThrowLeft.Contains(oldStep) && stepThrowRight.Contains(oldStep)) throwDirection = ThrowDirection.TdLeftRight; else if (stepThrowLeft.Contains(oldStep)) throwDirection = ThrowDirection.TdLeft; else if (stepThrowRight.Contains(oldStep)) throwDirection = ThrowDirection.TdRight; return throwDirection; } private async void PlayAni(ChallengePlayAniEvent challengePlayAniEvent) { var oldStep = challengePlayAniEvent.oldStep; var newStep = challengePlayAniEvent.newStep; ELog($"PlayAni-> {oldStep} => {newStep}"); // ELog($"PlayAni-> 更新剩余人数"); // 更新剩余人数 var eliminateNumber = _fishingChallengeManager.fishingChallengeData.eliminateNumber; var newEliminate = _fishingChallengeManager.CalcResidualNumber(oldStep); var showResidueNumEvent = new ShowResidueNumEvent { num = newEliminate }; GContext.Publish(showResidueNumEvent); float speed = 1; if (newStep > oldStep + 1) { speed = 0.7f; } ELog($"PlayAni->开始跳跃"); //- 跳跃,或者其他 //- 多组是否有可能 // await RunJumpGroup(oldStep, newStep, speed, newEliminate, eliminateNumber, showResidueNumEvent); await RunMatchPlayerLogic(oldStep, speed,newEliminate, eliminateNumber); challengePlayAniEvent.tcs.SetResult(true); } // 目前来处理,都是单个的 //- private async Task RunMatchPlayerLogic(int oldStep, float speed, int newEliminate,List eliminateNumber) { ELog($"RunMatchPlayerLogic-> {oldStep} => {oldStep + 1}"); var newStep = oldStep + 1; // var oldRegion = uiRegion[oldStep]; var regionIdx = Math.Min(uiRegion.Length - 1, newStep); var newRegion = uiRegion[regionIdx]; var posTran = newRegion.posTran; // var myself = newRegion.myself; var residual = posTran.Count; if (oldStep == 0) { // region1 -> region2 // await JumpSuccess(speed, myself, oldRegion, residual, posTran); // await Awaiters.Seconds(jumpToEliminateTime * speed); //- 破坏下一个阶段 //- 破坏的时间,如果满了的话,可以动 await JumpToTruck(oldStep,speed); await ActiveNextStage(newStep); await MoveToNextStage(newStep,residual); // var brokeStepEvent = await JumpDefeat(oldStep, newStep,speed, residual); _residualHeadCount = residual; // newEliminate -= eliminateNumber[oldStep]; // var showResidueNumEvent = new ShowResidueNumEvent // { // num = newEliminate // }; // GContext.Publish(showResidueNumEvent); UpdateEliminate(oldStep, newEliminate, eliminateNumber); await Awaiters.Seconds(1f * speed); // await brokeStepEvent.Tcs.Task; } else { //- 清除障碍物 // var brokeStepEvent = await JumpDefeat(oldStep, newStep,speed, residual); //- 开车 // GContext.Publish(new ChallengeMatchPlayEvent() { step = newStep }); await ActiveNextStage(newStep); await MoveToNextStage(newStep,residual); //-开车中掉落头像 _residualHeadCount = residual; UpdateEliminate(oldStep, newEliminate, eliminateNumber); await Awaiters.Seconds(1f * speed); // await brokeStepEvent.Tcs.Task; } //- 处理上车的 //淘汰动画 // if (newStep > 0) // { // GContext.Publish(new ChallengeMatchPlayEvent() { step = newStep }); // } // // _residualHeadCount = residual; // // newEliminate -= eliminateNumber[oldStep]; // var showResidueNumEvent = new ShowResidueNumEvent // { // num = newEliminate // }; // GContext.Publish(showResidueNumEvent); // await Awaiters.Seconds(1f * speed); // await brokeStepEvent.Tcs.Task; } private async Task ActiveNextStage(int newStep) { ELog("CleanNextStage-> Start"); var brokeStepEvent = new ChallengeBrokeStepEvent { step = newStep, dealyTime = flagUpDuration, }; GContext.Publish(brokeStepEvent); ELog("CleanNextStage-> End"); await brokeStepEvent.Tcs.Task; } public async void OnMoveNextStage(ChallengeMoveToNextStageEvent evt) { var newStep = evt.newStep; var residual = evt.residual; await MoveToNextStage(newStep, residual); } private async Task MoveToNextStage(int newStep,int residual) { ELog($"MoveToNextStage -> {newStep}: {residual} :_residualHeadCount {_residualHeadCount}"); GContext.Publish(new ChallengeMatchPlayEvent() { step = newStep }); var list = GetEliminateHeaders(residual); await Awaiters.Seconds(deltaTimeForEliminate); ThrowEliminateHeaders(list,newStep); ELog("MoveToNextStage Finished"); } private async Task JumpToTruck(int oldStep,float speed) { var oldRegion = uiStartRegion; var moveRegion = uiMoveRegion; var posTran = moveRegion.posTran; var myself = moveRegion.myself; var residual = posTran.Count; var count = _headList.Count; // TaskCompletionSource Tcs = new(); var jumpTcs = new TaskCompletionSource(); ELog($"JumpToTruck -> start {oldStep} {residual} headListCount:{count}"); _myHead.rectTransform.SetParent(myself); _myHead.rectTransform.localScale = Vector3.one; _myHead.rectTransform.DOLocalMove(Vector3.zero, jumpDuration); _myHead.headAni.Play(JumpKey); // 头狼起调 var myJumpAudioName = oldRegion.myJumpAudioName; if (!string.IsNullOrEmpty(myJumpAudioName)) { GContext.Publish(new EventUISound(myJumpAudioName)); } await Awaiters.Seconds(jumpIntervalMy * speed); // 跟随起跳 var followerJumpAudioName = oldRegion.followerJumpAudioName; if (!string.IsNullOrEmpty(myJumpAudioName)) { GContext.Publish(new EventUISound(followerJumpAudioName)); } for (var j = 0; j < residual; j++) { var kIndex = j; await Awaiters.Seconds(jumpInterval * speed); _headList[j].rectTransform.SetParent(posTran[j]); _headList[j].rectTransform.DOLocalMove(Vector3.zero, jumpDuration).SetEase(Ease.OutCubic); _headList[j].rectTransform.DOScale(Vector3.one, jumpDuration).SetEase(Ease.OutCubic).OnComplete(() => { if (kIndex == residual - 1) { jumpTcs.TrySetResult(true); } }); _headList[j].headAni.Play(JumpKey); } ELog($"JumpToTruck -> End {oldStep}"); await jumpTcs.Task; await Awaiters.NextFrame; } //- 要丢弃的头像放在这里 [Header("要丢弃的容器")] public Transform headTrashTransform; // private float distanceMin = 1f; // private float distanceMax = 2f; // private float distanceMinY = 1f; // private float distanceMaxY = 2f; private async void ThrowEliminateHeaders(List headList,int newStep,float speed = 1f) { ELog($"ThrowEliminateHeaders-> {headList.Count}"); // var heads = headList.Select(head => head.gameObject.name).ToList(); // ELog( "ThrowEliminateHeaders" + string.Join(",", heads)); // var oldStep = newStep - 1; // if (oldStep < 0) // oldStep = 0; var oldStep = Math.Max(0, newStep - 1); // var throwDirection = ThrowDirection.TdLeft; // if (stepThrowLeft.Contains(oldStep) && stepThrowRight.Contains(oldStep)) // throwDirection = ThrowDirection.TdLeftRight; // else if (stepThrowLeft.Contains(oldStep)) // throwDirection = ThrowDirection.TdLeft; // else if (stepThrowRight.Contains(oldStep)) // throwDirection = ThrowDirection.TdRight; var throwDirection = GetThrowDirection(oldStep); foreach (var head in headList) { await Awaiters.Seconds(eliminateInterval * speed); head.rectTransform.SetParent(headTrashTransform,worldPositionStays:true); var headWorldPos = head.transform.position; var audioName = uiRegion[oldStep].fallAudioName; if (!string.IsNullOrEmpty(audioName)) { GContext.Publish(new EventUISound(audioName)); } // head.rectTransform.DOScale(Vector3.one, jumpDead).SetEase(Ease.Linear); // var xDelta = UnityEngine.Random.Range(distanceMin, distanceMax); // var yDelta = UnityEngine.Random.Range(distanceMinY, distanceMaxY); // // var headPos = head.transform.localPosition; // // var vector3 = new Vector3(headPos.x + xDelta, headPos.y - yDelta , headPos.z); // // Vector3 worldPos; // if (throwDirection == ThrowDirection.TdLeft) // { // worldPos = new Vector3(headWorldPos.x - xDelta, headWorldPos.y - yDelta, headWorldPos.z); // } // else if (throwDirection == ThrowDirection.TdRight) // { // worldPos = new Vector3(headWorldPos.x + xDelta, headWorldPos.y - yDelta, headWorldPos.z); // } // else // { // var sign = UnityEngine.Random.Range(0, 2) * 2 - 1; // worldPos = new Vector3(headWorldPos.x + xDelta * sign, headWorldPos.y - yDelta, headWorldPos.z); // } head.GetComponent().PerformArcJump(headWorldPos, throwDirection); // head.rectTransform.DOLocalMove(vector3, jumpDuration).SetEase(Ease.OutCubic); // head.headAni.Play("fx_anim_eventchallengehead_jump_success_01"); // head.rectTransform.DOLocalMove(Vector3.zero, jumpDuration).SetEase(Ease.OutCubic); // head.rectTransform.DOScale(Vector3.one, jumpDuration).SetEase(Ease.OutCubic); // head.headAni.Play("fx_anim_eventchallengehead_jump_defeat_01"); } } //- 获得需要抛弃的头像列表 private List GetEliminateHeaders(int residual) { ELog("GetEliminateHeaders-> "); var list = new List(); for (var j = residual; j < _residualHeadCount; j++) { if (j < _headList.Count) { list.Add(_headList[j]); } } // var heads = list.Select(head => head.gameObject.name).ToList(); // ELog( "GetEliminateHeaders" + string.Join(",", heads)); return list; } private static void UpdateEliminate(int oldStep, int newEliminate, List eliminateNumber) { //- 更新剩余数量 newEliminate -= eliminateNumber[oldStep]; var showResidueNumEvent = new ShowResidueNumEvent { num = newEliminate }; GContext.Publish(showResidueNumEvent); } // private async Task JumpSuccess(float speed, Transform myself, ChallengeMatchSceneUIRegion oldRegion, int residual, List posTran) // { // ELog("JumpSuccess -> Start"); // //- 起跳 // _myHead.rectTransform.SetParent(myself); // _myHead.rectTransform.localScale = Vector3.one; // _myHead.rectTransform.DOLocalMove(Vector3.zero, jumpDuration); // _myHead.headAni.Play("fx_anim_eventchallengehead_jump_success_01"); // // 头狼起调 // var myJumpAudioName = oldRegion.myJumpAudioName; // if (!string.IsNullOrEmpty(myJumpAudioName)) // { // GContext.Publish(new EventUISound(myJumpAudioName)); // } // await Awaiters.Seconds(jumpIntervalMy * speed); // // // 跟随起跳 // var followerJumpAudioName = oldRegion.followerJumpAudioName; // if (!string.IsNullOrEmpty(myJumpAudioName)) // { // GContext.Publish(new EventUISound(followerJumpAudioName)); // } // // for (int j = 0; j < residual; j++) // { // await Awaiters.Seconds(jumpInterval * speed); // _headList[j].rectTransform.SetParent(posTran[j]); // _headList[j].rectTransform.DOLocalMove(Vector3.zero, jumpDuration).SetEase(Ease.OutCubic); // _headList[j].rectTransform.DOScale(Vector3.one, jumpDuration).SetEase(Ease.OutCubic); // _headList[j].headAni.Play("fx_anim_eventchallengehead_jump_success_01"); // } // // ELog("JumpSuccess -> End"); // } // private async Task JumpDefeat(int oldStep, int newStep, float speed, int residual) // { // ELog($"JumpDefeat -> {oldStep} => {newStep} speed: {speed} residual {residual}"); // var audioName = uiRegion[oldStep].fallAudioName; // var posTranRect = uiRegion[oldStep].posTranRect; // if (!string.IsNullOrEmpty(audioName)) // { // GContext.Publish(new EventUISound(audioName)); // } // // // var tranCount = posTranRect.Count; // var rectPos = posTranRect[0]; // float width = 0, height = 0; // // //- 破坏下一个阶段 // //- 破坏的时间,如果满了的话,可以动 // var brokeStepEvent = new ChallengeBrokeStepEvent // { // step = newStep, // dealyTime = BreakDuration, // }; // // if (residual >= _residualHeadCount) // { // GContext.Publish(brokeStepEvent); // } // else // { // for (int j = residual; j < _residualHeadCount; j++) // { // if (tranCount > j - residual) // { // rectPos = posTranRect[j - residual]; // width = rectPos.rect.width / 2; // height = rectPos.rect.height / 2; // } // // var vector3 = new Vector3(UnityEngine.Random.Range(-width, width), UnityEngine.Random.Range(-height, height), 0); // await Awaiters.Seconds(eliminateInterval * speed); // _headList[j].rectTransform.SetParent(rectPos); // _headList[j].rectTransform.DOScale(Vector3.one, jumpDead).SetEase(Ease.Linear); // _headList[j].rectTransform.DOLocalMove(vector3, jumpDead).SetEase(Ease.Linear); // _headList[j].headAni.Play("fx_anim_eventchallengehead_jump_defeat_01"); // if (j == residual) // { // // 播放破坏动画 // GContext.Publish(brokeStepEvent); // } // } // } // // return brokeStepEvent; // } // private async Task RunJumpGroup(int oldStep, int newStep, float speed, int newEliminate, List eliminateNumber, // ShowResidueNumEvent showResidueNumEvent) // { // for (int i = oldStep; i < newStep; i++) // { // var regionIdx = Math.Min(uiRegion.Length - 1, i + 1); // var randomPos = uiRegion[regionIdx]; // var posTran = randomPos.posTran; // var myself = randomPos.myself; // var residual = posTran.Count; // // _myHead.rectTransform.SetParent(myself); // _myHead.rectTransform.localScale = Vector3.one; // _myHead.rectTransform.DOLocalMove(Vector3.zero, jumpDuration); // _myHead.headAni.Play("fx_anim_eventchallengehead_jump_success_01"); // // 头狼起调 // var myJumpAudioName = uiRegion[i].myJumpAudioName; // if (!string.IsNullOrEmpty(myJumpAudioName)) // { // GContext.Publish(new EventUISound(myJumpAudioName)); // } // await Awaiters.Seconds(jumpIntervalMy * speed); // // 跟随起跳 // var followerJumpAudioName = uiRegion[i].followerJumpAudioName; // if (!string.IsNullOrEmpty(myJumpAudioName)) // { // GContext.Publish(new EventUISound(followerJumpAudioName)); // } // for (int j = 0; j < residual; j++) // { // await Awaiters.Seconds(jumpInterval * speed); // _headList[j].rectTransform.SetParent(posTran[j]); // _headList[j].rectTransform.DOLocalMove(Vector3.zero, jumpDuration).SetEase(Ease.OutCubic); // _headList[j].rectTransform.DOScale(Vector3.one, jumpDuration).SetEase(Ease.OutCubic); // _headList[j].headAni.Play("fx_anim_eventchallengehead_jump_success_01"); // } // var posTranRect = uiRegion[i].posTranRect; // //淘汰动画 // await Awaiters.Seconds(jumpToEliminateTime * speed); // // 播放动画声音 // var audioName = uiRegion[i].fallAudioName; // if (!string.IsNullOrEmpty(audioName)) // { // GContext.Publish(new EventUISound(audioName)); // } // // // // var tranCount = posTranRect.Count; // var rectPos = posTranRect[0]; // float width = 0, height = 0; // // //- 破坏的时间,如果满了的话,可以动 // var brokeStepEvent = new ChallengeBrokeStepEvent // { // step = (i + 1), // dealyTime = BreakDuration, // }; // // if (residual >= _residualHeadCount) // { // GContext.Publish(brokeStepEvent); // } // else // { // for (int j = residual; j < _residualHeadCount; j++) // { // if (tranCount > j - residual) // { // rectPos = posTranRect[j - residual]; // width = rectPos.rect.width / 2; // height = rectPos.rect.height / 2; // } // // Vector3 vector3 = new Vector3(UnityEngine.Random.Range(-width, width), // UnityEngine.Random.Range(-height, height), 0); // await Awaiters.Seconds(eliminateInterval * speed); // _headList[j].rectTransform.SetParent(rectPos); // _headList[j].rectTransform.DOScale(Vector3.one, jumpDead).SetEase(Ease.Linear); // _headList[j].rectTransform.DOLocalMove(vector3, jumpDead).SetEase(Ease.Linear); // _headList[j].headAni.Play("fx_anim_eventchallengehead_jump_defeat_01"); // if (j == residual) // { // // 播放破坏动画 // GContext.Publish(brokeStepEvent); // } // } // } // // ELog($"PlayAni->移动"); // // //从i到i+1平台,起点0不动 // //移动 // if (i >= 0) // { // GContext.Publish(new ChallengeMatchPlayEvent() { step = (i + 1) }); // } // // _residualHeadCount = residual; // newEliminate -= eliminateNumber[i]; // showResidueNumEvent.num = newEliminate; // GContext.Publish(showResidueNumEvent); // await Awaiters.Seconds(1f * speed); // // await brokeStepEvent.Tcs.Task; // // } // } #endregion #region Log private static void Log(object message) { Debug.Log($"ChallengeMatchPlayers => {message} "); } private static void ELog(string message) { #if UNITY_EDITOR Debug.Log($"ChallengeMatchPlayers => {message} "); #endif } #endregion } }