From 1f931e987fffd5d0fee55a989061753d6d396377 Mon Sep 17 00:00:00 2001 From: bottlefish <781230111@qq.com> Date: Wed, 15 Jul 2026 19:37:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(huoshan):=20=E4=BC=98=E5=8C=96=E8=AF=AD?= =?UTF-8?q?=E8=A8=80=E7=B2=92=E5=AD=90=E5=B8=83=E5=B1=80=E4=B8=8E=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E9=87=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scenes/HuoShanFixScene.unity | 14 +- .../HuoShan/Language/ExpressionManager.cs | 6 +- .../Language/LanguageParticleManager.cs | 171 ++++++++++++++---- 3 files changed, 145 insertions(+), 46 deletions(-) diff --git a/Assets/Scenes/HuoShanFixScene.unity b/Assets/Scenes/HuoShanFixScene.unity index 8ead2b0c2..80a7f408b 100644 --- a/Assets/Scenes/HuoShanFixScene.unity +++ b/Assets/Scenes/HuoShanFixScene.unity @@ -9259,9 +9259,9 @@ MonoBehaviour: _ambientNoiseScale: 320 _ambientNoiseBrightness: 0.55 _calmFieldPadding: {x: 0.55, y: 0.4} - _calmFieldFeather: 0.45 - _calmFieldResidualIntensity: 0.04 - _calmFieldBoundaryWarp: 0.025 + _calmFieldFeather: 0.85 + _calmFieldResidualIntensity: 0.08 + _calmFieldBoundaryWarp: 0.05 _calmFieldTransitionDuration: 0.45 --- !u!1 &751535848 GameObject: @@ -15057,7 +15057,7 @@ MonoBehaviour: defaultTargetSentence: "\u8FD9\u662F\u4E00\u4E2A\u6D4B\u8BD5\u793A\u4F8B" spriteRenderer: {fileID: 2468058580162010626} glitchController: {fileID: 741515695} - ambientNoiseDensity: 0.06 + ambientNoiseDensity: 0 ambientNoiseScale: 360 ambientNoiseBrightness: 0.5 --- !u!114 &2138889541 @@ -17270,13 +17270,13 @@ MonoBehaviour: shakeSpeed: 10 changeInterval: 0.28 floatAmplitude: 0.02 - glitchBaselineMax: 0.08 + glitchBaselineMax: 0 driftBias: 0.1 - shakeIntensity: 0.05 shakeSpeed: 12 changeInterval: 0.18 floatAmplitude: 0.028 - glitchBaselineMax: 0.15 + glitchBaselineMax: 0 driftBias: 0.15 targetConnectionThickness: 0.02 nonTargetConnectionThickness: 0.012 @@ -17310,7 +17310,7 @@ MonoBehaviour: completionBlastForce: 3.5 completionBlastAlphaRatio: 0.35 completionCalmDelay: 0.55 - completionGlitchPulsePeak: 0.25 + completionGlitchPulsePeak: 0 confirmButtonFadeDuration: 0.35 confirmButtonRiseOffset: 0.35 panelStartAtEntranceProgress: 0.6 diff --git a/Assets/Scripts/MiniGame/HuoShan/Language/ExpressionManager.cs b/Assets/Scripts/MiniGame/HuoShan/Language/ExpressionManager.cs index a237a4e72..f566455b6 100644 --- a/Assets/Scripts/MiniGame/HuoShan/Language/ExpressionManager.cs +++ b/Assets/Scripts/MiniGame/HuoShan/Language/ExpressionManager.cs @@ -34,7 +34,7 @@ namespace AibisDream [Header("常驻细密噪点(不随 glitch 强度消失,营造老屏幕底噪)")] [Tooltip("常驻噪点密度,0 = 关闭(恢复旧行为:LOG1 无噪点)")] - [SerializeField, Range(0f, 0.3f)] private float ambientNoiseDensity = 0.06f; + [SerializeField, Range(0f, 0.3f)] private float ambientNoiseDensity = 0f; [Tooltip("噪点细密程度,越大颗粒越细(glitch 主噪点默认 80)")] [SerializeField, Range(80f, 800f)] private float ambientNoiseScale = 360f; [Tooltip("常驻噪点亮度(低于 glitch 主噪点,保持底噪感)")] @@ -126,6 +126,7 @@ namespace AibisDream // 新一轮重置干扰联动(解除 yarn 覆盖、基线归零) yarnGlitchOverride = false; gameplayGlitchBaseline = 0f; + glitchController?.TransitionTo(0f, 0.25f); if (particleManager != null) { @@ -163,6 +164,7 @@ namespace AibisDream public IEnumerator FadeOutParticlesBeforeNewRound(float duration = 0f) { glitchController?.ClearCalmField(true); + glitchController?.TransitionTo(0f, 0.25f); if (particleManager == null) yield break; yield return StartCoroutine(particleManager.FadeOutBeforeNewExpressionRound(duration)); @@ -204,6 +206,7 @@ namespace AibisDream public void CloseView() { glitchController?.ClearCalmField(true); + glitchController?.TransitionTo(0f, 0f); if (expressionView != null) { @@ -222,6 +225,7 @@ namespace AibisDream public void ResetSystem(bool playEntranceEffect = true) { glitchController?.ClearCalmField(true); + glitchController?.TransitionTo(0f, 0.25f); if (particleManager != null) { diff --git a/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs b/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs index 3eebc274a..03ca80d68 100644 --- a/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs +++ b/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs @@ -117,12 +117,12 @@ namespace AibisDream.MiniGame.Language new InterferencePresentationPreset { shakeIntensity = 0.035f, shakeSpeed = 10f, changeInterval = 0.28f, - floatAmplitude = 0.02f, glitchBaselineMax = 0.08f, driftBias = 0.25f + floatAmplitude = 0.02f, glitchBaselineMax = 0f, driftBias = 0.25f }, new InterferencePresentationPreset { shakeIntensity = 0.05f, shakeSpeed = 12f, changeInterval = 0.18f, - floatAmplitude = 0.028f, glitchBaselineMax = 0.15f, driftBias = 0.4f + floatAmplitude = 0.028f, glitchBaselineMax = 0f, driftBias = 0.4f }, }; @@ -183,7 +183,7 @@ namespace AibisDream.MiniGame.Language [Tooltip("吹散后到进入平静态的延迟(秒)")] [SerializeField] private float completionCalmDelay = 0.55f; [Tooltip("完成瞬间 glitch 脉冲峰值(0 关闭)")] - [SerializeField, Range(0f, 1f)] private float completionGlitchPulsePeak = 0.25f; + [SerializeField, Range(0f, 1f)] private float completionGlitchPulsePeak = 0f; [Header("节奏统一")] [Tooltip("完成时确认按钮淡入/上浮时长(秒)")] @@ -1264,37 +1264,6 @@ namespace AibisDream.MiniGame.Language } // 激活 button 并淡入上浮(不可交互,播放火山表达确认后再解锁),与确认 timeline 并行 - if (focusSequenceButton != null) - { - var btnCg = focusSequenceButton.GetComponent(); - if (btnCg == null) - btnCg = focusSequenceButton.gameObject.AddComponent(); - var btnRect = focusSequenceButton.transform as RectTransform; - if (btnRect != null && !confirmButtonBasePosCaptured) - { - confirmButtonBaseAnchoredPos = btnRect.anchoredPosition; - confirmButtonBasePosCaptured = true; - } - - focusSequenceButton.gameObject.SetActive(true); - focusSequenceButton.interactable = false; - - DOTween.Kill(btnCg); - btnCg.alpha = 0f; - btnCg.DOFade(1f, confirmButtonFadeDuration).SetEase(Ease.OutQuad); - if (btnRect != null) - { - btnRect.DOKill(); - btnRect.anchoredPosition = confirmButtonBaseAnchoredPos + Vector2.down * confirmButtonRiseOffset; - btnRect.DOAnchorPos(confirmButtonBaseAnchoredPos, confirmButtonFadeDuration).SetEase(Ease.OutQuad); - } - } - if (confirmTimelineRoutine != null) - { - StopCoroutine(confirmTimelineRoutine); - } - confirmTimelineRoutine = StartCoroutine(PlayConfirmTimelineAndUnlockButton()); - foreach (var particle in candidateParticles) { if (!particle.isRed) @@ -1319,6 +1288,135 @@ namespace AibisDream.MiniGame.Language /// 延迟后进入平静态;同时打一次 glitch 短脉冲。 /// private void PlayCompletionBurst() + { + if (completionBurstRoutine != null) + { + StopCoroutine(completionBurstRoutine); + } + completionBurstRoutine = StartCoroutine(PlayCalmCompletionRoutine()); + } + + private IEnumerator PlayCalmCompletionRoutine() + { + float fadeDuration = Mathf.Max(0.05f, completionCalmDelay); + float moveDuration = Mathf.Max(0.05f, completionShockwaveDuration); + + if (connectionRenderer != null) + { + DOTween.To(() => connectionRenderer.NonTargetAlphaScale, v => connectionRenderer.NonTargetAlphaScale = v, 0f, fadeDuration) + .SetEase(Ease.OutQuad) + .SetTarget(this); + } + + foreach (var particle in candidateParticles) + { + if (particle == null) + continue; + + particle.velocity = Vector2.zero; + if (!particle.isRed) + { + particle.isCalmed = true; + particle.isStatic = true; + FadeOutTextParticle(particle, fadeDuration); + } + else + { + particle.isStatic = true; + particle.isCalmed = true; + particle.changeSpeedMultiplier = 1f; + } + } + + foreach (var particle in floatingParticles) + { + if (particle == null) + continue; + + particle.isCalmed = true; + particle.velocity = Vector2.zero; + FadeOutTextParticle(particle, fadeDuration); + } + + int tweenTargetCount = orderedRedParticles.Count; + int completedTweens = 0; + for (int i = 0; i < orderedRedParticles.Count; i++) + { + var particle = orderedRedParticles[i]; + if (particle == null) + { + completedTweens++; + continue; + } + + if (i < finalTargetCharacters.Count) + { + particle.ForceSetCharacter(finalTargetCharacters[i]); + } + + Vector3 targetPos = finalTargetPositions.Count > i + ? finalTargetPositions[i] + : (worldCanvas != null ? worldCanvas.transform.position : Vector3.zero); + + particle.alpha = particle.baseAlpha; + particle.transform.DOKill(); + particle.transform.DOMove(targetPos, moveDuration) + .SetEase(Ease.InOutQuad) + .OnComplete(() => completedTweens++); + particle.transform.DOScale(Vector3.one * focusZoomScale, moveDuration).SetEase(Ease.OutQuad); + } + + if (tweenTargetCount > 0) + { + while (completedTweens < tweenTargetCount) + { + yield return null; + } + } + else + { + yield return new WaitForSeconds(fadeDuration); + } + + ShowFocusSequenceButton(); + if (confirmTimelineRoutine != null) + { + StopCoroutine(confirmTimelineRoutine); + } + confirmTimelineRoutine = StartCoroutine(PlayConfirmTimelineAndUnlockButton()); + completionBurstRoutine = null; + } + + private void ShowFocusSequenceButton() + { + if (focusSequenceButton == null) + return; + + var btnCg = focusSequenceButton.GetComponent(); + if (btnCg == null) + btnCg = focusSequenceButton.gameObject.AddComponent(); + var btnRect = focusSequenceButton.transform as RectTransform; + if (btnRect != null && !confirmButtonBasePosCaptured) + { + confirmButtonBaseAnchoredPos = btnRect.anchoredPosition; + confirmButtonBasePosCaptured = true; + } + + focusSequenceButton.gameObject.SetActive(true); + focusSequenceButton.interactable = false; + + DOTween.Kill(btnCg); + btnCg.alpha = 0f; + btnCg.DOFade(1f, confirmButtonFadeDuration).SetEase(Ease.OutQuad); + if (btnRect != null) + { + btnRect.DOKill(); + btnRect.anchoredPosition = confirmButtonBaseAnchoredPos + Vector2.down * confirmButtonRiseOffset; + btnRect.DOAnchorPos(confirmButtonBaseAnchoredPos, confirmButtonFadeDuration).SetEase(Ease.OutQuad); + } + } + + private void PlayCompletionBurstLegacy() { Vector3 center = ComputeCentroid(targetParticles); @@ -1523,10 +1621,7 @@ namespace AibisDream.MiniGame.Language for (int i = 0; i < orderedRedParticles.Count; i++) { var particle = orderedRedParticles[i]; - Vector3 offset = particle.transform.position - focusCentroid; - float indexCenter = (orderedRedParticles.Count - 1) * 0.5f; - Vector3 spreadOffset = new Vector3((i - indexCenter) * spreadDistance, Mathf.Sin(i * 1.4f) * spreadDistance * 0.6f, 0f); - Vector3 focusPosition = focusTargetCenter + offset * focusZoomScale + spreadOffset; + Vector3 focusPosition = particle.transform.position; Vector3 finalPosition = finalTargetPositions.Count > i ? finalTargetPositions[i] : focusTargetCenter; focusPosition = ClampPositionToBounds(focusPosition, focusClipBounds); finalPosition = ClampPositionToBounds(finalPosition, focusClipBounds);