From bee4e0c796e789505714d2ede6259abf96526dd5 Mon Sep 17 00:00:00 2001 From: bottlefish <781230111@qq.com> Date: Sat, 25 Jul 2026 15:56:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(huoshan):=20=E8=BF=AD=E4=BB=A3log=E9=87=8A?= =?UTF-8?q?=E6=94=BE=E6=BC=94=E5=87=BA=E4=B8=8EYarn=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../Language/LanguageParticleManager.cs | 92 ++++++++ .../HuoShan/Language/LanguageYarnCommand.cs | 82 ++++--- .../LogReleasePresentationController.cs | 222 +++++++++++------- 3 files changed, 286 insertions(+), 110 deletions(-) diff --git a/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs b/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs index 3c8735f27..c7f07abf0 100644 --- a/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs +++ b/Assets/Scripts/MiniGame/HuoShan/Language/LanguageParticleManager.cs @@ -1623,6 +1623,98 @@ namespace AibisDream.MiniGame.Language .SetTarget(this); } + /// + /// 真话聚合挣扎(非等待):向 target 推进的途中反复"够到一点又被拽回去"。 + /// 回抽幅度必须跨过 UpdateTruthGatherLock 的 0.08 解锁带,已锁的字才会崩开重新乱跳—— + /// 挣扎感来自进度曲线本身的往复,不依赖任何颜色或额外特效。 + /// + /// 最终停留的聚合进度 + /// 整段时长 + /// 回抽次数;<=0 时退化为普通聚合 + public void BeginTruthStrain(float target, float duration, int tugs) + { + if (completionPhase != CompletionPhase.FocusHolding) + { + Debug.LogWarning( + $"[LanguageParticleManager] 真话挣扎在 {completionPhase} 状态被调用;已安全跳过。"); + return; + } + + int tugCount = Mathf.Clamp(tugs, 0, 4); + if (tugCount <= 0) + { + BeginTruthGather(target, duration); + return; + } + + float clampedTarget = Mathf.Clamp01(target); + float start = truthGatherProgress; + float total = Mathf.Max(0.2f, duration); + // 末尾留一段单纯的推进,让整句最后停在 target 而不是停在回抽底部 + float settleDuration = total * 0.18f; + float cycleDuration = (total - settleDuration) / tugCount; + float pushDuration = Mathf.Max(0.05f, cycleDuration * 0.72f); + float recoilDuration = Mathf.Max(0.04f, cycleDuration - pushDuration); + + DOTween.Kill(TruthGatherTweenId); + Sequence sequence = DOTween.Sequence().SetId(TruthGatherTweenId).SetTarget(this); + for (int i = 1; i <= tugCount; i++) + { + // 每次比上一次够得更远,最后一次刚好摸到 target 再被拽回来 + float peak = Mathf.Lerp(start, clampedTarget, i / (float)tugCount); + // 回抽越往后越狠;下限 0.1 保证越过 0.08 解锁带 + float recoil = 0.10f + 0.03f * (i - 1); + float valley = Mathf.Max(0f, peak - recoil); + + sequence.Append( + DOTween.To( + () => truthGatherProgress, + value => truthGatherProgress = value, + peak, + pushDuration) + .SetEase(Ease.OutCubic)); + sequence.Append( + DOTween.To( + () => truthGatherProgress, + value => truthGatherProgress = value, + valley, + recoilDuration) + .SetEase(Ease.OutExpo)); + } + + sequence.Append( + DOTween.To( + () => truthGatherProgress, + value => truthGatherProgress = value, + clampedTarget, + Mathf.Max(0.05f, settleDuration)) + .SetEase(Ease.OutCubic)); + } + + /// + /// 真话聚合崩塌(非等待):进度被一口气拽回 0,所有已锁的字沿原路退回悬浮位并恢复乱跳。 + /// Ease.InBack 会先向上顶一点点再垮掉——"又够了一下下,然后整个塌了"。 + /// + public void CollapseTruthGather(float duration) + { + if (completionPhase != CompletionPhase.FocusHolding) + { + Debug.LogWarning( + $"[LanguageParticleManager] 真话崩塌在 {completionPhase} 状态被调用;已安全跳过。"); + return; + } + + DOTween.Kill(TruthGatherTweenId); + DOTween.To( + () => truthGatherProgress, + value => truthGatherProgress = value, + 0f, + Mathf.Max(0.08f, duration)) + .SetEase(Ease.InBack) + .SetId(TruthGatherTweenId) + .SetTarget(this); + } + /// 真话聚合被打断:目标字向外爆散并恢复乱跳(非等待)。 public void ScatterTruthGather(float burstDistance) { diff --git a/Assets/Scripts/MiniGame/HuoShan/Language/LanguageYarnCommand.cs b/Assets/Scripts/MiniGame/HuoShan/Language/LanguageYarnCommand.cs index e40a76deb..3bdd58140 100644 --- a/Assets/Scripts/MiniGame/HuoShan/Language/LanguageYarnCommand.cs +++ b/Assets/Scripts/MiniGame/HuoShan/Language/LanguageYarnCommand.cs @@ -337,34 +337,6 @@ namespace AibisDream.MiniGame.Language presentation.SqueezeTruthCharacters(duration, jitter, alpha); } - [YarnCommand("expression_lie_show")] - public static void ExpressionLieShow(string keyword, float duration, float characterSpacing) - { - if (TryGetPresentation(out LogReleasePresentationController presentation)) - presentation.ShowLieKeyword(keyword, duration, characterSpacing); - } - - [YarnCommand("expression_scanline")] - public static void ExpressionScanline(float duration, bool stalled) - { - if (TryGetPresentation(out LogReleasePresentationController presentation)) - presentation.PlayScreenScanline(duration, stalled); - } - - [YarnCommand("expression_system_message")] - public static void ExpressionSystemMessage(string value, string style, float fadeDuration) - { - if (TryGetPresentation(out LogReleasePresentationController presentation)) - presentation.ShowSystemMessage(value, style, fadeDuration); - } - - [YarnCommand("expression_system_message_hide")] - public static void ExpressionSystemMessageHide(float fadeDuration) - { - if (TryGetPresentation(out LogReleasePresentationController presentation)) - presentation.HideSystemMessage(fadeDuration); - } - [YarnCommand("expression_lie_crack_begin")] public static void ExpressionLieCrackBegin(float lieAlpha) { @@ -420,8 +392,41 @@ namespace AibisDream.MiniGame.Language presentation.ScatterTruthGatherAttempt(burst); } + /// + /// 真话聚合挣扎(非阻塞):向 target 推进的途中反复"够到一点又被拽回去", + /// 已锁的字会崩开重新乱跳。挣扎感来自聚合曲线本身,不使用任何颜色或额外特效。 + /// <> + /// + /// 最终停留的聚合进度 + /// 整段时长 + /// 回抽次数(0~4);<=0 时退化为 expression_truth_gather + [YarnCommand("expression_truth_strain")] + public static void ExpressionTruthStrain(float target = 0.85f, float duration = 3f, float tugs = 2f) + { + if (TryGetPresentation(out LogReleasePresentationController presentation)) + { + presentation.BeginTruthStrainAttempt( + target, + duration, + UnityEngine.Mathf.RoundToInt(tugs)); + } + } + + /// + /// 真话聚合崩塌(非阻塞):进度被一口气拽回 0,字沿原路退回悬浮位并恢复乱跳。 + /// 与 expression_truth_scatter 的区别:scatter 是径向爆散,collapse 是"被拽回去"。 + /// <> + /// + [YarnCommand("expression_truth_collapse")] + public static void ExpressionTruthCollapse(float duration = 0.45f) + { + if (TryGetPresentation(out LogReleasePresentationController presentation)) + presentation.CollapseTruthGatherAttempt(duration); + } + /// /// 火山脸错误闪红(非阻塞):聚合失败时短暂替换红屏 Sprite,随后恢复,并轻微下沉。 + /// 注意:LOG1/LOG2 的失败信号已明确不使用红色与脸部报错,此命令仅保留兼容。 /// <> /// [YarnCommand("expression_face_error")] @@ -691,6 +696,27 @@ namespace AibisDream.MiniGame.Language presentation.PlayGlitchPulse(peak, riseDuration, fallDuration); } + /// + /// 火山「屏幕」Sprite 直驱撕裂花屏(非阻塞)。作用在屏幕材质,不是叠一层噪波。 + /// 是 0–1 的目标档位, 是推到该档位的时间; + /// 到位后一直保持(Shader 自带憋气/发力循环,不会变成静止花屏),要收掉就再调一次 level=0。 + /// <> … <> + /// + [YarnCommand("expression_screen_glitch")] + public static void ExpressionScreenGlitch( + float level = 0.5f, + float duration = 1f) + { + if (ExpressionManager == null) + { + UnityEngine.Debug.LogError( + "[LanguageYarnCommand] expression_screen_glitch 找不到 ExpressionManager;已安全跳过。"); + return; + } + + ExpressionManager.SetScreenGlitchLevel(level, duration); + } + /// /// 用现有目标粒子完整显示一个红色攻击词,并等待确定性的冲击动作结束。 /// 超过目标粒子数量时会安全跳过,不会截断。 diff --git a/Assets/Scripts/MiniGame/HuoShan/Language/LogReleasePresentationController.cs b/Assets/Scripts/MiniGame/HuoShan/Language/LogReleasePresentationController.cs index 50ced39bf..324ae765f 100644 --- a/Assets/Scripts/MiniGame/HuoShan/Language/LogReleasePresentationController.cs +++ b/Assets/Scripts/MiniGame/HuoShan/Language/LogReleasePresentationController.cs @@ -9,8 +9,8 @@ using UnityEngine; namespace AibisDream.MiniGame.Language { /// - /// Owns the post-output performance for Huoshan's three blocked logs. Memory effects - /// stay on their own SpriteRenderers, while the opaque face and dialogue UI remain clean. + /// Owns the post-output performance for Huoshan's three blocked logs. All memory + /// distortion lives on the HuoshanMemory material; face / dialogue stay clean. /// public sealed class LogReleasePresentationController : MonoBehaviour { @@ -71,6 +71,7 @@ namespace AibisDream.MiniGame.Language [SerializeField] private LanguageParticleManager particleManager; [SerializeField] private SpriteRenderer faceRenderer; [SerializeField] private Sprite errorFaceSprite; + [Tooltip("可选。记忆演出不再驱动 noise;仅在进入/退出时清零遗留 Intensity,避免 glitch_transition 残留。")] [SerializeField] private SpriteNoiseGlitchController glitchController; [SerializeField] private RectTransform expressionScreenMaskRect; [SerializeField] private TMP_FontAsset screenFont; @@ -82,10 +83,10 @@ namespace AibisDream.MiniGame.Language [SerializeField] private Material memoryMaterial; [Header("Memory Simulation")] - [Tooltip("三档演出预设下记忆的轻微失真强度;随记忆透明度一起浮现。")] - [SerializeField, Range(0f, 1f)] private float simGlitchLight = 0.20f; - [SerializeField, Range(0f, 1f)] private float simGlitchMedium = 0.26f; - [SerializeField, Range(0f, 1f)] private float simGlitchHeavy = 0.32f; + [Tooltip("三档演出预设下记忆材质的轻微失真强度;随记忆透明度一起浮现。")] + [SerializeField, Range(0f, 1f)] private float simGlitchLight = 0.28f; + [SerializeField, Range(0f, 1f)] private float simGlitchMedium = 0.36f; + [SerializeField, Range(0f, 1f)] private float simGlitchHeavy = 0.44f; [Header("Timing")] [SerializeField, Min(0.01f)] private float faceFadeDuration = 0.45f; @@ -145,7 +146,6 @@ namespace AibisDream.MiniGame.Language private int actorFlashCount; private Coroutine actorOverdriveRoutine; private Coroutine actorFlashLoopRoutine; - private Texture2D runtimeWhiteTexture; private Sprite runtimeWhiteSprite; private MaterialPropertyBlock memoryBlockA; @@ -158,6 +158,7 @@ namespace AibisDream.MiniGame.Language private float vignette; private float noise; private float simGlitch; + private float memoryBaseSimGlitch; private float horizontalTear; private float memoryImpact; private float memoryDamage; @@ -279,12 +280,7 @@ namespace AibisDream.MiniGame.Language state = PresentationState.FaceEntering; // 梳理完成起:目标字切到白色(并取消加粗),玩法阶段颜色不受影响。 particleManager?.ApplyPresentationResolvedVisuals(presentationResolvedColor); - if (glitchController != null) - { - glitchController.SetCompositeMode(SpriteNoiseGlitchController.CompositeMode.TransparentOverlay); - glitchController.Intensity = 0f; - glitchController.SetAmbientNoise(0f, 320f, 0f); - } + SilenceNoiseOverlayIfPresent(); if (faceRenderer == null) { @@ -346,15 +342,9 @@ namespace AibisDream.MiniGame.Language state = PresentationState.Memory; // 兜底:跳过 face_fade_in 直进记忆时,目标字仍切到演出白。 particleManager?.ApplyPresentationResolvedVisuals(presentationResolvedColor); - - if (glitchController != null) - { - glitchController.SetCompositeMode(SpriteNoiseGlitchController.CompositeMode.TransparentOverlay); - if (!preserveGlitch) - glitchController.Intensity = 0f; - glitchController.SetAmbientNoise(0f, 320f, 0f); - glitchController.ClearCalmField(true); - } + // 记忆失真全部走 HuoshanMemory 材质;清掉 noise 叠层残留。 + _ = preserveGlitch; + SilenceNoiseOverlayIfPresent(); SpriteRenderer incoming = activeMemoryRenderer == memoryRendererA ? memoryRendererB : memoryRendererA; SpriteRenderer outgoing = activeMemoryRenderer; @@ -488,16 +478,20 @@ namespace AibisDream.MiniGame.Language DOTween.Kill(this); float duration = Mathf.Max(0.01f, freezeDuration); // 谎话期间把模拟感压到目标值:记忆被伪装得"过分干净"。 - DOTween.To(() => simGlitch, value => simGlitch = value, Mathf.Clamp01(noiseTarget), duration) + float resolved = Mathf.Clamp01(noiseTarget); + memoryBaseSimGlitch = resolved; + DOTween.To(() => simGlitch, value => simGlitch = value, resolved, duration) .SetEase(Ease.OutQuad) .SetTarget(this); } - /// 调节记忆的轻微失真扰动(非等待)。 + /// 调节记忆材质的轻微失真扰动(非等待)。 public void SetSimulationGlitch(float target, float duration) { EnsureRuntimeObjects(); - DOTween.To(() => simGlitch, value => simGlitch = value, Mathf.Clamp01(target), Mathf.Max(0.01f, duration)) + float resolved = Mathf.Clamp01(target); + memoryBaseSimGlitch = resolved; + DOTween.To(() => simGlitch, value => simGlitch = value, resolved, Mathf.Max(0.01f, duration)) .SetEase(Ease.OutQuad) .SetTarget(this); } @@ -705,14 +699,7 @@ namespace AibisDream.MiniGame.Language DisableMemoryRenderer(memoryRendererB); activeMemoryRenderer = null; StopTruthLieFlicker(); - - if (glitchController != null) - { - glitchController.Intensity = 0f; - glitchController.SetAmbientNoise(0f, 320f, 0f); - glitchController.ClearCalmField(true); - glitchController.SetCompositeMode(SpriteNoiseGlitchController.CompositeMode.TransparentOverlay); - } + SilenceNoiseOverlayIfPresent(); } /// @@ -772,10 +759,8 @@ namespace AibisDream.MiniGame.Language Mathf.Lerp(0.26f, 0.16f, flashProgress))); try { - if (glitchController != null) - { + if (resolvedGlitchPeak > 0.001f) StartCoroutine(PulseGlitch(resolvedGlitchPeak, 0.04f, 0.14f)); - } particleManager?.SetTargetParticlesAlpha(0f, 0f); @@ -960,13 +945,10 @@ namespace AibisDream.MiniGame.Language Mathf.Max(0.05f, duration), Mathf.Max(0.02f, interval), truthCharacters)); - if (glitchController != null) - { - StartCoroutine(PulseGlitch( - 0.64f, - Mathf.Max(0.05f, duration * 0.82f), - Mathf.Max(0.05f, duration * 0.18f))); - } + StartCoroutine(PulseGlitch( + 0.64f, + Mathf.Max(0.05f, duration * 0.82f), + Mathf.Max(0.05f, duration * 0.18f))); } public IEnumerator PlayActorWordHit( @@ -1113,9 +1095,6 @@ namespace AibisDream.MiniGame.Language effectStrength = Mathf.Clamp01(peripheral); calmRadius = Mathf.Clamp01(calmTarget); particleManager?.SnapTruthImmediate(); - - if (glitchController != null) - glitchController.Intensity = 0f; state = PresentationState.TruthHolding; } @@ -1135,6 +1114,22 @@ namespace AibisDream.MiniGame.Language particleManager?.ScatterTruthGather(burstDistance); } + /// 真话聚合挣扎(非等待):推进途中反复"够到又被拽回去",字会锁上再崩开。 + public void BeginTruthStrainAttempt(float target, float duration, int tugs) + { + if (!ExpectState(nameof(BeginTruthStrainAttempt), PresentationState.Memory)) + return; + particleManager?.BeginTruthStrain(target, duration, tugs); + } + + /// 真话聚合崩塌(非等待):进度被拽回 0,所有字沿原路退回并恢复乱跳。 + public void CollapseTruthGatherAttempt(float duration) + { + if (!ExpectState(nameof(CollapseTruthGatherAttempt), PresentationState.Memory)) + return; + particleManager?.CollapseTruthGather(duration); + } + /// 火山脸错误闪红:聚合失败的报错信号(非等待)。 public void PlayFaceErrorFlash(float duration, float intensity) { @@ -1371,6 +1366,10 @@ namespace AibisDream.MiniGame.Language yield return new WaitForSeconds(Mathf.Max(0.05f, total - scrambleDuration)); } + /// + /// 记忆材质上的瞬时失真脉冲(抬升 _SimGlitch 后回落),不再驱动 noise 叠层。 + /// 撕裂仍走 PlayMemoryTear / impact,避免两路抢同一参数。 + /// public void PlayGlitchPulse(float peak, float riseDuration, float fallDuration) { if (!ExpectState( @@ -1387,6 +1386,16 @@ namespace AibisDream.MiniGame.Language Mathf.Max(0.01f, fallDuration))); } + /// + /// 已弃用:屏幕 Glitch 请走 ExpressionManager.SetScreenGlitchLevel(屏幕自身材质)。 + /// 记忆阶段失真请用 PlayGlitchPulse / 记忆 impact。 + /// + public void PlayScreenGlitch(float intensity, float duration) + { + _ = intensity; + _ = duration; + } + public IEnumerator PlayTruthAttack( string text, float duration, @@ -1463,8 +1472,21 @@ namespace AibisDream.MiniGame.Language PresentationState.TruthHolding)) yield break; - if (glitchController != null) - glitchController.TransitionTo(0f, Mathf.Max(0.08f, duration * 0.65f)); + float settleDuration = Mathf.Max(0.08f, duration * 0.65f); + DOTween.To( + () => simGlitch, + value => simGlitch = value, + memoryBaseSimGlitch, + settleDuration) + .SetEase(Ease.OutQuad) + .SetTarget(this); + DOTween.To( + () => horizontalTear, + value => horizontalTear = value, + 0f, + settleDuration) + .SetEase(Ease.OutQuad) + .SetTarget(this); if (particleManager != null) yield return particleManager.SettleTruthPhraseAndWait(text, duration); @@ -1495,12 +1517,21 @@ namespace AibisDream.MiniGame.Language DOTween.To(() => memoryOverdrive, value => memoryOverdrive = value, 1f, rise) .SetEase(Ease.InQuad) .SetTarget(this); - - if (glitchController != null) - { - glitchController.SetCompositeMode(SpriteNoiseGlitchController.CompositeMode.TransparentOverlay); - glitchController.TransitionTo(Mathf.Clamp01(glitchPeak), rise); - } + float peak = Mathf.Clamp01(glitchPeak); + DOTween.To( + () => simGlitch, + value => simGlitch = value, + Mathf.Lerp(memoryBaseSimGlitch, 1f, peak), + rise) + .SetEase(Ease.InQuad) + .SetTarget(this); + DOTween.To( + () => horizontalTear, + value => horizontalTear = value, + Mathf.Lerp(0.18f, 0.72f, peak), + rise) + .SetEase(Ease.InQuad) + .SetTarget(this); if (actorFlashText != null) { @@ -1699,8 +1730,12 @@ namespace AibisDream.MiniGame.Language StopScanline(); StopScreenDim(); ReleaseScreenTextClipMaterials(); - if (glitchController != null) - glitchController.TransitionTo(0f, 0.18f); + DOTween.To(() => simGlitch, value => simGlitch = value, memoryBaseSimGlitch, 0.18f) + .SetEase(Ease.OutQuad) + .SetTarget(this); + DOTween.To(() => horizontalTear, value => horizontalTear = value, 0f, 0.18f) + .SetEase(Ease.OutQuad) + .SetTarget(this); state = PresentationState.TruthHolding; } @@ -1732,26 +1767,20 @@ namespace AibisDream.MiniGame.Language HideSystemMessageImmediate(); StopScanline(); StopScreenDim(); - if (glitchController != null) - { - glitchController.ClearCalmField(true); - glitchController.TransitionTo(0f, 0.12f); - glitchController.SetAmbientNoise(0f, 320f, 0f); - } + SilenceNoiseOverlayIfPresent(); + DOTween.To(() => simGlitch, value => simGlitch = value, 0f, 0.12f) + .SetEase(Ease.OutQuad) + .SetTarget(this); + DOTween.To(() => horizontalTear, value => horizontalTear = value, 0f, 0.12f) + .SetEase(Ease.OutQuad) + .SetTarget(this); yield return new WaitForSeconds(memoryExitDuration); DisableMemoryRenderer(memoryRendererA); DisableMemoryRenderer(memoryRendererB); if (currentMemoryKind == MemoryKind.PrivateOffice) - { particleManager?.SetTargetParticlesAlpha(0.6f, 0.18f); - if (glitchController != null) - { - glitchController.SetAmbientNoise(0.012f, 430f, 0.24f); - glitchController.Intensity = 0.03f; - } - } state = PresentationState.TruthHolding; } @@ -1787,13 +1816,7 @@ namespace AibisDream.MiniGame.Language } } - if (glitchController != null) - { - glitchController.Intensity = 0f; - glitchController.ClearCalmField(true); - glitchController.SetAmbientNoise(0f, 320f, 0f); - glitchController.SetCompositeMode(SpriteNoiseGlitchController.CompositeMode.OpaqueBackground); - } + ResetNoiseOverlayForGlitchTransition(); particleManager?.RestoreTargetPresentationDefaults(); state = PresentationState.Idle; @@ -1805,6 +1828,7 @@ namespace AibisDream.MiniGame.Language horizontalTear = 0f; noise = 0f; simGlitch = 0f; + memoryBaseSimGlitch = 0f; memoryImpact = 0f; memoryDamage = 0f; memoryOverdrive = 0f; @@ -2028,14 +2052,48 @@ namespace AibisDream.MiniGame.Language .WaitForCompletion(); } + /// 记忆材质瞬时失真:抬升 _SimGlitch 后回到基线。 private IEnumerator PulseGlitch(float peak, float riseDuration, float fallDuration) { - if (glitchController == null) + float clampedPeak = Mathf.Clamp01(peak); + if (clampedPeak <= 0.001f) yield break; - glitchController.SetCompositeMode(SpriteNoiseGlitchController.CompositeMode.TransparentOverlay); - yield return glitchController.TransitionToAndWait(Mathf.Clamp01(peak), riseDuration); - yield return glitchController.TransitionToAndWait(0f, fallDuration); + float rise = Mathf.Max(0.01f, riseDuration); + float fall = Mathf.Max(0.01f, fallDuration); + float startSim = simGlitch; + float restoreSim = memoryBaseSimGlitch > 0.001f ? memoryBaseSimGlitch : startSim; + float targetSim = Mathf.Max(startSim, Mathf.Lerp(restoreSim, 1f, clampedPeak)); + + yield return DOTween.To(() => simGlitch, value => simGlitch = value, targetSim, rise) + .SetEase(Ease.OutQuad) + .SetTarget(this) + .WaitForCompletion(); + yield return DOTween.To(() => simGlitch, value => simGlitch = value, restoreSim, fall) + .SetEase(Ease.InQuad) + .SetTarget(this) + .WaitForCompletion(); + } + + private void SilenceNoiseOverlayIfPresent() + { + if (glitchController == null) + return; + + glitchController.Intensity = 0f; + glitchController.SetAmbientNoise(0f, 320f, 0f); + glitchController.ClearCalmField(true); + } + + private void ResetNoiseOverlayForGlitchTransition() + { + if (glitchController == null) + return; + + SilenceNoiseOverlayIfPresent(); + // 回到 glitch_transition 原始合成;Layer 保持 Default,勿改 HuoshanScreen。 + glitchController.SetCompositeMode(SpriteNoiseGlitchController.CompositeMode.OpaqueBackground); + glitchController.gameObject.layer = 0; } private IEnumerator ShuffleLieCharactersRoutine( @@ -2116,7 +2174,6 @@ namespace AibisDream.MiniGame.Language } calmRadius = 0f; calmFeather = 0.20f; - glitchController?.SetCalmField(truthBounds); } private void ConfigureMemoryLook(MemoryKind kind, Preset preset) @@ -2140,7 +2197,7 @@ namespace AibisDream.MiniGame.Language MemoryKind.Sunset => 0.18f, _ => 0.46f }; - // 颗粒噪点弃用;仅由 _SimGlitch 保留轻微 UV 失真扰动。 + // 颗粒噪点与 noise 叠层均弃用;失真只走记忆材质 _SimGlitch。 noise = 0f; simGlitch = preset.Name switch { @@ -2148,6 +2205,7 @@ namespace AibisDream.MiniGame.Language "Heavy" => simGlitchHeavy, _ => simGlitchLight }; + memoryBaseSimGlitch = simGlitch; horizontalTear = 0f; memoryTint = kind switch {