using System; using System.Collections.Generic; using DG.Tweening; using UnityEngine; namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse { public partial class DTMTrail : EnvironmentObject, IHaveTrail, IHaveInteraction { #region [暴露属性字段] Exposed Fields public GameObject headPoint, headCircle; public GameObject trailBody; public bool isHeadEnabled; public List renderers; public ParticleSystem headCircleParticle; public TrailRenderer trailRenderer { get; set; } public FlexibleFloat visibleTimeLength; public FlexibleBool enableTimes; public float enableProcessTime = 0.5f; public float headSize = 1f; public FlexibleFloat headRotateSpeed; public override bool haveEmission => true; #endregion #region [生命周期与工厂] Lifecycle & Factory public static DTMTrail GenerateElement(string elementName, Guid id, List tags, bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement, bool isStatic, FlexibleFloat visibleTimeLength, FlexibleBool enableTimes, FlexibleFloat headRotateSpeed, float enableProcessTime, float headSize) { DTMTrail dtmTrail = EnvironmentObject.GenerateElement(elementName, id, tags, isFirstGenerated, themeBundleName, objectName, parentElement, isStatic).GetComponent(); dtmTrail.isHeadEnabled = false; dtmTrail.visibleTimeLength = visibleTimeLength; dtmTrail.enableTimes = enableTimes; dtmTrail.headRotateSpeed = headRotateSpeed; dtmTrail.enableProcessTime = enableProcessTime; dtmTrail.headSize = headSize; return dtmTrail; } public override void SetDefaultSubmodules() { base.SetDefaultSubmodules(); colorSubmodule.emissionEnabled = true; colorSubmodule.originalEmissionColor = Color.white; colorSubmodule.originalEmissionIntensity = 1; } public override void FirstSetUpObject(bool isFirstGenerated) { //SetUpTweeners(); trailRenderer = trailBody.GetComponent(); var rotationBySpeedModule = headCircleParticle.rotationBySpeed; rotationBySpeedModule.z = 0; headPoint.transform.localScale = Vector3.zero; headCircle.transform.localScale = Vector3.zero; trailRenderer.emitting = false; renderers.ForEach(rend => rend.InitializeShader()); } public override void WhenStart() { base.WhenStart(); trailRenderer.emitting = true; trailRenderer.Clear(); headPoint.gameObject.SetActive(false); headCircle.gameObject.SetActive(false); } public override void Refresh() { base.Refresh(); renderers.ForEach(rend => { rend.material.SetColor("_BaseColor", colorSubmodule.currentBaseColor); rend.material.SetColor("_EmissionColor", colorSubmodule.GetCurrentEmissionColor()); }); } #endregion #region [事件动画逻辑] Event Animation Logic private void Update() { float songTime = CoreServices.TimeProvider.SongTime; enableTimes.UpdateFlexibleBool(songTime); if(enableTimes.value && !isHeadEnabled) { EnableHead(); isHeadEnabled = true; } else if(!enableTimes.value && isHeadEnabled) { DisableHead(); isHeadEnabled = false; } visibleTimeLength.UpdateFlexibleFloat(songTime); if (visibleTimeLength.animations.Count > 0) { trailRenderer.time = visibleTimeLength.value; } if (isHeadEnabled && headRotateSpeed.animations.Count > 0) { headRotateSpeed.UpdateFlexibleFloat(songTime); var rotationBySpeedModule = headCircleParticle.rotationBySpeed; rotationBySpeedModule.z = headRotateSpeed.value; } } private Sequence enableHeadSequence; private Sequence disableHeadSequence; private Sequence headBounceSequence; private void EnableHead() { enableHeadSequence?.Kill(true); disableHeadSequence?.Kill(true); enableHeadSequence = DOTween.Sequence(); enableHeadSequence.Append(headPoint.transform.DOScale(headSize, enableProcessTime).SetEase(Ease.OutQuad)); enableHeadSequence.Join(headCircle.transform.DOScale(headSize, enableProcessTime).SetEase(Ease.OutQuad)); enableHeadSequence.OnStart(() => { headPoint.gameObject.SetActive(true); headCircle.gameObject.SetActive(true); }); enableHeadSequence.Play(); } private void DisableHead() { enableHeadSequence?.Kill(true); disableHeadSequence?.Kill(true); disableHeadSequence = DOTween.Sequence(); disableHeadSequence.Append(headPoint.transform.DOScale(0, enableProcessTime).SetEase(Ease.OutQuad)); disableHeadSequence.Join(headCircle.transform.DOScale(0, enableProcessTime).SetEase(Ease.OutQuad)); disableHeadSequence.OnComplete(() => { headPoint.gameObject.SetActive(false); headCircle.gameObject.SetActive(false); }); disableHeadSequence.Play(); } public void TriggerInteraction() { headBounceSequence = DOTween.Sequence(); headBounceSequence.Append(headPoint.transform.DOBlendableScaleBy(Vector3.one * 0.2f, 0.2f).SetEase(Ease.OutBack)); headBounceSequence.Join(headCircle.transform.DOBlendableScaleBy(Vector3.one * 0.2f, 0.2f).SetEase(Ease.OutBack)); headBounceSequence.Append(headPoint.transform.DOBlendableScaleBy(Vector3.one * -0.2f, 0.2f).SetEase(Ease.OutBack)); headBounceSequence.Join(headCircle.transform.DOBlendableScaleBy(Vector3.one * -0.2f, 0.2f).SetEase(Ease.OutBack)); headBounceSequence.SetAutoKill(false); } #endregion } }