using System; using System.Collections; using System.Collections.Generic; using TableConfig; using UnityEngine; using UnityEngine.UI; using DG.Tweening; namespace Snxxz.UI { public class TreasureAnimation : MonoBehaviour { [SerializeField] UIAlphaTween m_DisplayAlphaTween; [SerializeField] RectTransform m_ContainerStars; [SerializeField] PositionTween m_StarPositionTween; [SerializeField] UIEffect[] m_Stars; [SerializeField] TreasureMeridianBehaviour[] m_TreasureMeridians; [SerializeField] PositionTween m_AchievementPosTween; [SerializeField] PositionTween m_ProgressPosTween; [SerializeField] RectTransform m_ContianerPotential; [SerializeField] RectTransform m_ContainerLevelUp; [SerializeField] PositionTween m_SkillPosTween; [SerializeField] ScaleTween m_SkillSclTween; [SerializeField] ScaleTween m_PotentialSclTween; [SerializeField] RectTransform m_AchievementSfxTarget; [SerializeField] PositionTween m_HeroShowSkillPowTween; [SerializeField] RectTransform m_ContainerSkillShowBottom; [SerializeField] ScaleTween[] m_PotentialPointSclTweens; [SerializeField] TreasurePotentialBriefInfo[] m_TreasurePotentials; [SerializeField] RectTransform[] m_PotentialLineMasks; [SerializeField] RectTransform m_PotentialSkill; TreasureModel m_Model; TreasureModel model { get { return m_Model ?? (m_Model = ModelCenter.Instance.GetModel()); } } #region const const int POTENTIALUNLOCKSFX = 5190; public const int SPIRALSFX = 5126; const int CONVERGESFX = 5127; public const float LINE_NORMAL_LENGTH = 187f; public const float LINE_NORMAL_SCALE = 0.78f; const float POTENTIAL_TIME_SCALE = 0.5f; const float SPIRAL_SFX_TIME_SCALE = 0.6f; const float LINE_SFX_TIME_SCALE = 0.3f; const float POSITION_TWEEN_SPEED = 300f; public const int LINESFX = 5121; public const string LINE_STATE_1 = "Effect_FaBao_Xian1_01"; public const string LINE_STATE_2 = "Effect_FaBao_Xian1_02"; public const string LINE_STATE_3 = "Effect_FaBao_Xian1_03"; public const string LINE_STATE_4 = "Effect_FaBao_Xian1_04"; public const string LINE_STATE_5 = "Effect_FaBao_Xian1_05"; public const int POTENTIAL_LINESFX = 5173; public const string POTENTIAL_LINE_STATE_1 = "Effect_FaBao_Xian2"; public const string POTENTIAL_LINE_STATE_2 = "Effect_FaBao_Xian2_02"; public static readonly int Param_Step = Animator.StringToHash("Step"); #endregion #region public public int selectTreasureId { get; set; } private int displayTreasure { get; set; } public event Action OnStageUpLineComplete; public event Action OnStepComplete; public event Action OnAchievementSfxComplete; public event Action OnAchievementTweenComplete; public event Action OnUnlockPotentialComplete; public event Action OnPotentialLevelUpComplete; public event Action OnPotentialLineAnimComplete; TreasureShowStep m_Step = TreasureShowStep.None; TreasureShowStep m_BeforeStep = TreasureShowStep.None; public TreasureShowStep step { get { return m_Step; } set { stepComplete = true; if (step == value && value != TreasureShowStep.Lock) { if (value == TreasureShowStep.UnLock) { m_ProgressPosTween.SetEndState(); m_PotentialSclTween.SetEndState(); UI3DTreasureSelectStage.Instance.SetEndState(); } return; } switch (m_BeforeStep) { case TreasureShowStep.Lock: if (value != TreasureShowStep.Lock) { ExitShowLock(); } break; } m_Step = value; m_BeforeStep = value; switch (value) { case TreasureShowStep.Lock: OnEnterShowLock(); break; case TreasureShowStep.FirstUnLock: OnEnterFisrtUnlock(); break; case TreasureShowStep.UnLock: OnEnterShowUnLock(); break; case TreasureShowStep.FirstPotential: OnEnterFirstPotential(); break; case TreasureShowStep.Potential: OnEnterPotential(); break; } } } public void DisplayPotentialLevelUp(int _index, int level) { if (_index >= m_TreasurePotentials.Length || _index < 0) { return; } if (level == 15 && _index < 2) { stepComplete = false; } displayTreasure = model.selectedTreasure; StartCoroutine(Co_PotentialLevelUp(_index, level)); } IEnumerator Co_PotentialLevelUp(int _index, int level) { yield return StartCoroutine(Co_PotentialSpiral(_index, SPIRALSFX)); if (displayTreasure != model.selectedTreasure) { stepComplete = true; yield break; } //UIEffect effect = null; //if (level == 1) //{ // effect = EffectMgr.Instance.PlayUIEffect(POTENTIAL_LINESFX, 2100, transform, false); // if (effect == null) // { // stepComplete = true; // yield break; // } // effect.keep = true; // effect.maskArea = m_PotentialLineMasks[_index]; // effect.SetMask(); // yield return StartCoroutine(Co_DisplayPotentialLine(_index,effect)); //} if (displayTreasure != model.selectedTreasure) { //StopPotentialLineEffect(effect); stepComplete = true; yield break; } if (OnPotentialLevelUpComplete != null) { OnPotentialLevelUpComplete(_index, level); } stepComplete = true; //yield return null; //StopPotentialLineEffect(effect); } public void DisplayPotentialLine(int _index) { stepComplete = false; StartCoroutine(Co_PotentialLineAnim(_index)); } IEnumerator Co_PotentialLineAnim(int _index) { UIEffect effect = EffectMgr.Instance.PlayUIEffect(POTENTIAL_LINESFX, 2100, transform, false); if (effect == null) { stepComplete = true; yield break; } effect.keep = true; effect.maskArea = m_PotentialLineMasks[_index]; effect.SetMask(); yield return StartCoroutine(Co_DisplayPotentialLine(_index, effect)); stepComplete = true; StopPotentialLineEffect(effect); if (OnPotentialLineAnimComplete != null) { OnPotentialLineAnimComplete(_index); } } private void StopPotentialLineEffect(UIEffect _effect) { if (_effect != null) { _effect.keep = false; _effect.maskArea = null; _effect.StopImediatly(); _effect = null; } } IEnumerator Co_PotentialSpiral(int _index, int effectId) { var effect = EffectMgr.Instance.PlayUIEffect(effectId, 2700, m_TreasurePotentials[_index].transform, false); var duration = effect.duration; var _time = 0f; while (_time < duration) { _time += Time.deltaTime; yield return null; if (displayTreasure != model.selectedTreasure) { effect.StopImediatly(); effect = null; yield break; } } } IEnumerator Co_DisplayPotentialLine(int _index,UIEffect effect) { var _duration = effect.duration; var _time = 0f; var _frompos = transform.InverseTransformPoint(m_TreasurePotentials[_index].transform.TransformPoint(Vector3.zero)); var _topos = transform.InverseTransformPoint(m_PotentialSkill.transform.TransformPoint(Vector3.zero)); effect.transform.localPosition = _frompos; var _angle = VectorUtility.VectorAngle(_topos, _frompos); effect.transform.localEulerAngles = Vector3.zero.SetZ(_angle); var _animator = effect.target.GetAnimator(); _animator.transform.localScale = Vector3.one.SetY(Vector2.Distance(_topos, _frompos) / LINE_NORMAL_LENGTH * LINE_NORMAL_SCALE); _animator.Play(POTENTIAL_LINE_STATE_1, 0, 0); while (_time < _duration) { _time += Time.deltaTime; yield return null; if (displayTreasure != model.selectedTreasure) { yield break; } } } public void UnlockTreasurePotential(int _index) { if (_index >= m_TreasurePotentials.Length || _index < 0) { return; } stepComplete = false; displayTreasure = model.selectedTreasure; StartCoroutine(Co_UnlockTreasurePotential(_index)); } IEnumerator Co_UnlockTreasurePotential(int _index) { StartCoroutine(Co_PotentialSpiral(_index, POTENTIALUNLOCKSFX)); yield return WaitingForSecondConst.WaitMS600; if (displayTreasure != model.selectedTreasure) { stepComplete = true; yield break; } stepComplete = true; m_TreasurePotentials[_index].DisplayUnlock(); if (OnUnlockPotentialComplete != null) { OnUnlockPotentialComplete(_index); } } public void OnStageUp(int _index) { stepComplete = false; StartCoroutine(Co_StepStage(_index)); } IEnumerator Co_StepStage(int _index) { float _timer = 0f; float _duration = 0f; var _config = ScriptableObjectLoader.LoadSoTreasureMeridian(model.selectedTreasure); var _effect = EffectMgr.Instance.PlayUIEffect(SPIRALSFX, 2700, m_TreasureMeridians[_index].transform.parent, false); _effect.transform.localPosition = _config[_index].position; _duration = _effect.duration; if (_index == _config.stagePointNum - 1 && m_ProgressPosTween.gameObject.activeInHierarchy) { m_ProgressPosTween.Play(true); } while (_timer < _duration) { _timer += Time.deltaTime; yield return null; } _duration = 0.3f; _timer = 0f; var _current = m_TreasureMeridians[_index]; _current.RequestStateSfx(); _current.selectSfx.Play(); if (_current.selectSfx.IsPlaying) { _current.selectSfx.transform.DOScale(Vector3.zero, _duration); } while (_timer < _duration) { _timer += Time.deltaTime; yield return null; } _current.selectSfx.StopImediatly(); stepComplete = true; if (OnStageUpLineComplete != null) { OnStageUpLineComplete(); } } public void OnStageLock(int _index) { StartCoroutine(Co_StageLock(_index)); } IEnumerator Co_StageLock(int _index) { float _timer = 0f; float _duration = 0f; stepComplete = false; var _config = ScriptableObjectLoader.LoadSoTreasureMeridian(model.selectedTreasure); _index = Mathf.Max(_index, 0); var _current = m_TreasureMeridians[_index]; if (_index < 0) { stepComplete = true; yield break; } if (_index < _config.stagePointNum - 1) { var _effect = EffectMgr.Instance.PlayUIEffect(LINESFX, 2500, m_TreasureMeridians[_index].transform.parent, false); _effect.transform.localPosition = _config[_index].position; var _angle = VectorUtility.VectorAngle(_config[_index + 1].position, _config[_index].position); _effect.transform.localEulerAngles = Vector3.zero.SetZ(_angle); var _animator = _effect.target.GetAnimator(); _animator.transform.localScale = Vector3.one.SetY(Vector2.Distance(_config[_index + 1].position, _config[_index].position) / LINE_NORMAL_LENGTH * LINE_NORMAL_SCALE); _animator.Play(LINE_STATE_1, 0, 0); _duration = _effect.duration; _timer = 0f; while (_timer < _duration * 0.6f) { _timer += Time.deltaTime; yield return null; } _effect.StopImediatly(); var _next = m_TreasureMeridians[_index + 1]; _current.RequestSfx(); _next.RequestSfx(); _duration = 0.3f; _timer = 0f; if (_next.selectSfx.IsPlaying) { _next.selectSfx.transform.localScale = Vector3.zero; _next.selectSfx.transform.DOScale(Vector3.one, _duration); } while (_timer < _duration) { _timer += Time.deltaTime; yield return null; } } stepComplete = true; if (OnStageUpLineComplete != null) { OnStageUpLineComplete(); } } public void OnHeroSkillShow(int _index) { var _config = ScriptableObjectLoader.LoadSoTreasureMeridian(selectTreasureId); m_HeroShowSkillPowTween.gameObject.SetActive(true); m_ContainerSkillShowBottom.gameObject.SetActive(false); m_HeroShowSkillPowTween.from = _config[_index].position; m_HeroShowSkillPowTween.SetStartState(); m_HeroShowSkillPowTween.Play(()=> { m_ContainerSkillShowBottom.gameObject.SetActive(true); }); } public void TreasureTween(bool _play = false) { UI3DTreasureSelectStage.Instance.SetStartState(); if (_play) { UI3DTreasureSelectStage.Instance.Tween(null); } } [Header("领取成就特效")] [SerializeField, Header("单个飞行时间")] float achievement_sfx_duration = 1.0f; [SerializeField, Header("特效间隔时间")] float achievement_sfx_interval = 0.15f; [SerializeField, Header("特效个数")] int achievement_sfx_count = 5; public void ShowAchievementCompleteSfx(RectTransform _root, int _id) { var _worldPos = _root.TransformPoint(Vector3.zero); var _startPos = transform.InverseTransformPoint(_worldPos); _worldPos = m_AchievementSfxTarget.TransformPoint(Vector3.zero); var _endPos = transform.InverseTransformPoint(_worldPos); StartCoroutine(Co_AchivementGotSfx(_startPos, _endPos, _id)); } IEnumerator Co_AchivementGotSfx(Vector3 _start, Vector3 _end, int _id) { float _timer = 0f; bool _boom = false; var _n = _end - _start; var _selectTreasure = selectTreasureId; _n = (Quaternion.AngleAxis(90, Vector3.forward) * _n).normalized; List _points = new List(achievement_sfx_count); List _effects = new List(achievement_sfx_count); UIEffect _boomSfx = null; for (int i = 0; i < achievement_sfx_count; i++) { var _d = UnityEngine.Random.Range(50f, 200.0f); var _m = (_start + _end) / 2 + (_d * (i % 2 == 0 ? 1 : -1)) * _n; _points.Add(_m); } while (_timer < achievement_sfx_duration + achievement_sfx_interval * (achievement_sfx_count - 1)) { if (_selectTreasure != selectTreasureId) { for (int i = 0; i < _effects.Count; i++) { _effects[i].StopImediatly(); _effects[i] = null; } if (_boomSfx != null) { _boomSfx.StopImediatly(); _boomSfx = null; } yield break; } yield return null; _timer += Time.deltaTime; int _count = Mathf.Min((int)(_timer / achievement_sfx_interval) + 1, achievement_sfx_count); for (int i = 0; i < _count; i++) { if (_effects.Count < i + 1 || _effects[i] == null) { var _effect = EffectMgr.Instance.PlayUIEffect(3009, 2700, transform, _start, true); _effects.Add(_effect); } var _t = Mathf.Clamp01((_timer - achievement_sfx_interval * i) / achievement_sfx_duration); var _pos = Bezier.BezierCurve(_start, _points[i], _end, _t); _effects[i].transform.localPosition = _pos; } if (!_boom && _timer > achievement_sfx_duration + achievement_sfx_interval * (achievement_sfx_count - 1) - 0.5f) { _boom = true; _boomSfx = EffectMgr.Instance.PlayUIEffect(5138, 2500, transform, _end, false); } } for (int i = 0; i < _effects.Count; i++) { _effects[i].StopImediatly(); _effects[i] = null; } _effects.Clear(); if (OnAchievementSfxComplete != null) { OnAchievementSfxComplete(_id); } } public void SetDisplayEnd() { m_DisplayAlphaTween.SetEndState(); } #endregion #region private float timer = 0f; public bool stepComplete { get; set; } List m_LineSfxs = new List(); private void Init() { m_ContainerStars.gameObject.SetActive(false); } void ExitShowLock() { m_ContainerStars.gameObject.SetActive(false); } void OnEnterShowLock() { m_DisplayAlphaTween.SetStartState(); m_DisplayAlphaTween.Play(); m_ContainerStars.gameObject.SetActive(true); m_StarPositionTween.SetStartState(); TreasureMeridianConfig _config = ScriptableObjectLoader.LoadSoTreasureMeridian(selectTreasureId); for (int i = 0; i < m_Stars.Length; i++) { if (_config == null || i >= _config.stagePointNum) { m_Stars[i].gameObject.SetActive(false); } else { m_Stars[i].gameObject.SetActive(true); m_Stars[i].StopImediatly(); m_Stars[i].effect = _config[i].effect; m_Stars[i].transform.localPosition = _config[i].position; m_Stars[i].Play(); m_Stars[i].target.GetAnimator().Play("Effect_FaBao_Light_1", 0, UnityEngine.Random.Range(0, 0.8f)); } } TreasureTween(); } void OnEnterFisrtUnlock() { OnEnterShowLock(); m_DisplayAlphaTween.SetStartState(); m_AchievementPosTween.SetStartState(); m_ProgressPosTween.SetStartState(); m_StarPositionTween.SetStartState(); for (int i = 0; i < m_TreasureMeridians.Length; i++) { m_TreasureMeridians[i].gameObject.SetActive(false); } stepComplete = false; m_DisplayAlphaTween.Play(() => { TreasureTween(true); m_StarPositionTween.Play(OnStarTweenComplete); }); } void OnStarTweenComplete() { timer = 0; StartCoroutine(Co_ShowMeridianLine()); } IEnumerator Co_ShowMeridianLine() { var _index = 0; TreasureMeridianConfig _config = ScriptableObjectLoader.LoadSoTreasureMeridian(selectTreasureId); RecycleLineSfx(); var _duration = 0f; while (_index < _config.stagePointNum) { timer = 0f; var _effect1 = EffectMgr.Instance.PlayUIEffect(SPIRALSFX, 2700, m_TreasureMeridians[_index].transform.parent, false); _effect1.transform.position = m_TreasureMeridians[_index].transform.position; _duration = _effect1.duration; while (timer < _duration * SPIRAL_SFX_TIME_SCALE) { yield return null; } m_TreasureMeridians[_index].gameObject.SetActive(true); m_TreasureMeridians[_index].RequestStateSfx(); m_Stars[_index].StopImediatly(); timer = 0f; if (_index < _config.stagePointNum - 1) { var _effect2 = EffectMgr.Instance.PlayUIEffect(LINESFX, 2500, m_TreasureMeridians[_index].transform.parent, false); _duration = _effect2.duration; _effect2.keep = true; m_LineSfxs.Add(_effect2); _effect2.transform.position = m_TreasureMeridians[_index].transform.position; var _angle = VectorUtility.VectorAngle(_config[_index + 1].position, _config[_index].position); _effect2.transform.localEulerAngles = Vector3.zero.SetZ(_angle); var _animator = _effect2.target.GetAnimator(); _animator.transform.localScale = Vector3.one.SetY(Vector2.Distance(_config[_index + 1].position, _config[_index].position) / LINE_NORMAL_LENGTH * LINE_NORMAL_SCALE); _animator.SetInteger(Param_Step, 0); _animator.Play(LINE_STATE_1, 0, 0); while (timer < _duration * LINE_SFX_TIME_SCALE) { yield return null; } _animator.SetInteger(Param_Step, 1); } _index++; } for (int i = 0; i < _config.stagePointNum; i++) { m_TreasureMeridians[i].PlayLineSfx(2, true); } RecycleLineSfx(); timer = 0f; _duration = m_AchievementPosTween.duration + m_AchievementPosTween.delay; m_AchievementPosTween.Play(() => { if (OnAchievementTweenComplete != null) { OnAchievementTweenComplete(); } }); Treasure treasure; model.TryGetTreasure(selectTreasureId, out treasure); if (!treasure.IsHighestStage) { m_ProgressPosTween.Play(); } if (OnStepComplete != null) { OnStepComplete(TreasureShowStep.FirstUnLock); } while (timer < _duration) { yield return null; } stepComplete = true; model.TryGetTreasure(selectTreasureId, out treasure); if (treasure.treasureStages[0].unlockType != TreasureStageUnlock.None) { OnStageUp(0); } model.treasureEntranceShowId = 0; } void OnEnterShowUnLock() { stepComplete = false; m_DisplayAlphaTween.SetStartState(); m_DisplayAlphaTween.Play(); UI3DTreasureSelectStage.Instance.SetStartState(); OnEnterPotential(); m_ProgressPosTween.SetEndState(); m_AchievementPosTween.SetEndState(); m_PotentialSclTween.SetEndState(); UI3DTreasureSelectStage.Instance.Tween(() => { stepComplete = true; if (OnStepComplete != null) { OnStepComplete(TreasureShowStep.UnLock); } }); } void OnEnterFirstPotential() { timer = 0; stepComplete = false; for (int i = 0; i < m_TreasureMeridians.Length; i++) { m_TreasureMeridians[i].StopSfx(); } StartCoroutine(Co_ShowFirstPotential()); } IEnumerator Co_ShowFirstPotential() { Treasure _treasure; model.TryGetTreasure(selectTreasureId, out _treasure); if (_treasure == null) { stepComplete = true; yield break; } var _duration = 0.0f; var _stages = _treasure.treasureStages; var _config = ScriptableObjectLoader.LoadSoTreasureMeridian(model.selectedTreasure); var _skillStage = _stages.FindIndex((x) => { return x.unlockType == TreasureStageUnlock.Skill; }); var _skillStageIndex = _treasure.GetStageIndex(_skillStage); for (int i = 0; i < _config.stagePointNum; i++) { if (i == _skillStageIndex) { continue; } _duration = Mathf.Max(m_TreasureMeridians[i].scaleTween.delay + m_TreasureMeridians[i].scaleTween.duration, _duration); m_TreasureMeridians[i].scaleTween.Play(); m_TreasureMeridians[i].scaleTween.SetEndState(); } while (timer < _duration) { yield return null; } timer = 0; _duration = 0; for (int i = 0; i < _config.stagePointNum; i++) { if (i == _skillStageIndex) { continue; } var _positionTween = m_TreasureMeridians[i].positionTween; _positionTween.from = _config[i].position; _positionTween.to = _config[_skillStageIndex].position; var _distance = Vector2.Distance(_positionTween.from, _positionTween.to); _positionTween.duration = _distance / POSITION_TWEEN_SPEED; _duration = Mathf.Max(_positionTween.delay + _positionTween.duration, _duration); _positionTween.Play(() => { _positionTween.gameObject.SetActive(false); }); } while (timer < _duration) { yield return null; } if (_config.stagePointNum > 1) { timer = 0; var _effect = EffectMgr.Instance.PlayUIEffect(CONVERGESFX, 2700, m_TreasureMeridians[_skillStageIndex].transform.parent, false); _effect.transform.localPosition = _config[_skillStageIndex].position; while (timer < 0.5f) { yield return null; } } timer = 0; m_ContainerLevelUp.gameObject.SetActive(false); m_ContianerPotential.gameObject.SetActive(true); m_PotentialSclTween.SetStartState(); m_SkillPosTween.from = _config[_skillStageIndex].position; m_SkillPosTween.SetStartState(); m_SkillPosTween.Play(); _duration = m_SkillPosTween.delay + m_SkillPosTween.duration; while (timer < _duration) { yield return null; } timer = 0; m_SkillSclTween.Play(); m_SkillSclTween.SetEndState(); _duration = m_SkillSclTween.delay + m_SkillSclTween.duration; while (timer < _duration * POTENTIAL_TIME_SCALE) { yield return null; } timer = 0f; m_PotentialSclTween.Play(); _duration = m_PotentialSclTween.duration + m_PotentialSclTween.delay; while (timer < _duration) { yield return null; } for (int i = 0; i < m_PotentialPointSclTweens.Length; i++) { var _index = i; m_PotentialPointSclTweens[_index].Play(); m_PotentialPointSclTweens[_index].SetEndState(); } stepComplete = true; if (OnStepComplete != null) { OnStepComplete(TreasureShowStep.FirstPotential); } } private void OnEnterPotential() { m_SkillPosTween.SetEndState(); m_SkillSclTween.SetEndState(); } void RecycleLineSfx() { for (int i = 0; i < m_LineSfxs.Count; i++) { m_LineSfxs[i].keep = false; m_LineSfxs[i].StopImediatly(); } m_LineSfxs.Clear(); } private void LateUpdate() { switch (step) { case TreasureShowStep.FirstPotential: case TreasureShowStep.FirstUnLock: timer += Time.deltaTime; break; } } #endregion public enum TreasureShowStep { None, Lock, FirstUnLock, UnLock, FirstPotential, Potential, } } }