From 5a37f529ab0c45136dfb3369a915db20f72b8e32 Mon Sep 17 00:00:00 2001 From: bottlefish <781230111@qq.com> Date: Sun, 19 Jul 2026 22:36:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(dialog):=20=E4=BF=AE=E5=A4=8D=E5=BF=AB?= =?UTF-8?q?=E8=BF=9B=E6=97=B6=E5=90=8E=E5=A4=84=E7=90=86=E6=B8=90=E5=8F=98?= =?UTF-8?q?=E5=9B=9E=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/Dialog System/BaseYarnCommand.cs | 119 ++++++++++++++---- 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/Assets/Scripts/Dialog System/BaseYarnCommand.cs b/Assets/Scripts/Dialog System/BaseYarnCommand.cs index 550f843cd..88ae66606 100644 --- a/Assets/Scripts/Dialog System/BaseYarnCommand.cs +++ b/Assets/Scripts/Dialog System/BaseYarnCommand.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Generic; using AibisDream.Framework; using AibisDream.UI; using UnityEngine; @@ -11,6 +12,10 @@ namespace AibisDream { public static class BaseYarnCommand { + private static readonly Dictionary ActiveVolumeWeightTweens = new(); + private static readonly Dictionary ActiveVolumeBrightnessTweens = new(); + private static long _nextVolumeTweenToken; + #region 命令名 [YarnCommand("NextYarn")] @@ -54,6 +59,7 @@ namespace AibisDream return; } + CancelVolumeTween(volume, ActiveVolumeWeightTweens); volume.weight = Mathf.Clamp01(weight); } @@ -69,23 +75,14 @@ namespace AibisDream } targetWeight = Mathf.Clamp01(targetWeight); - if (duration <= 0f) - { - volume.weight = targetWeight; - yield break; - } - - var startWeight = volume.weight; - var elapsed = 0f; - while (elapsed < duration) - { - elapsed += Time.unscaledDeltaTime; - var progress = Mathf.Clamp01(elapsed / duration); - volume.weight = Mathf.Lerp(startWeight, targetWeight, EaseInOutSine(progress)); - yield return null; - } - - volume.weight = targetWeight; + yield return TweenVolumeFloat( + volume, + ActiveVolumeWeightTweens, + () => volume.weight, + value => volume.weight = value, + targetWeight, + duration, + EaseInOutSine); } [YarnCommand("tween_volume_weight_async")] @@ -103,28 +100,32 @@ namespace AibisDream [YarnCommand("set_volume_brightness")] public static void SetVolumeBrightness(string volumeName, float brightness) { - if (!TryGetVolumeAdjustments(volumeName, out _, out var adjustments)) + if (!TryGetVolumeAdjustments(volumeName, out var volume, out var adjustments)) { return; } + CancelVolumeTween(volume, ActiveVolumeBrightnessTweens); adjustments.m_Brightness.value = Mathf.Clamp(brightness, -1f, 1f); } [YarnCommand("tween_volume_brightness")] public static IEnumerator TweenVolumeBrightness(string volumeName, float targetBrightness, float duration) { - if (!TryGetVolumeAdjustments(volumeName, out _, out var adjustments)) + if (!TryGetVolumeAdjustments(volumeName, out var volume, out var adjustments)) { yield break; } targetBrightness = Mathf.Clamp(targetBrightness, -1f, 1f); - yield return TweenUnscaledFloat( + yield return TweenVolumeFloat( + volume, + ActiveVolumeBrightnessTweens, () => adjustments.m_Brightness.value, value => adjustments.m_Brightness.value = value, targetBrightness, - duration); + duration, + SmootherStep); } [YarnCommand("tween_volume_brightness_async")] @@ -153,12 +154,12 @@ namespace AibisDream // Bloom 先扩散;等 Bloom 完全起来后,才用曝光把剩余暗部推到纯白。 adjustments.m_Brightness.value = 0f; - yield return TweenUnscaledFloat( + yield return TweenFloat( () => volume.weight, value => volume.weight = value, 1f, bloomDuration); - yield return TweenUnscaledFloat( + yield return TweenFloat( () => adjustments.m_Brightness.value, value => adjustments.m_Brightness.value = value, 1f, @@ -177,12 +178,12 @@ namespace AibisDream } // 先从纯白恢复画面层次,再逐渐收掉仍然存在的 Bloom。 - yield return TweenUnscaledFloat( + yield return TweenFloat( () => adjustments.m_Brightness.value, value => adjustments.m_Brightness.value = value, 0f, exposureDuration); - yield return TweenUnscaledFloat( + yield return TweenFloat( () => volume.weight, value => volume.weight = value, 0f, @@ -217,7 +218,7 @@ namespace AibisDream return true; } - private static IEnumerator TweenUnscaledFloat( + private static IEnumerator TweenFloat( Func getter, Action setter, float target, @@ -233,7 +234,8 @@ namespace AibisDream var elapsed = 0f; while (elapsed < duration) { - elapsed += Time.unscaledDeltaTime; + // 与 Yarn 的 <> 使用同一时间域,让快进同步加速后处理演出。 + elapsed += Time.deltaTime; var progress = Mathf.Clamp01(elapsed / duration); setter(Mathf.Lerp(start, target, SmootherStep(progress))); yield return null; @@ -242,6 +244,69 @@ namespace AibisDream setter(target); } + private static IEnumerator TweenVolumeFloat( + Volume volume, + Dictionary activeTweens, + Func getter, + Action setter, + float target, + float duration, + Func easing) + { + var volumeId = volume.GetInstanceID(); + var token = ++_nextVolumeTweenToken; + activeTweens[volumeId] = token; + + if (duration <= 0f) + { + if (IsCurrentVolumeTween(activeTweens, volumeId, token)) + setter(target); + CompleteVolumeTween(activeTweens, volumeId, token); + yield break; + } + + var start = getter(); + var elapsed = 0f; + while (elapsed < duration) + { + if (volume == null || !IsCurrentVolumeTween(activeTweens, volumeId, token)) + yield break; + + // 与 Yarn 的 <> 使用同一时间域,让快进同步加速后处理演出。 + elapsed += Time.deltaTime; + var progress = Mathf.Clamp01(elapsed / duration); + setter(Mathf.Lerp(start, target, easing(progress))); + yield return null; + } + + if (volume != null && IsCurrentVolumeTween(activeTweens, volumeId, token)) + setter(target); + CompleteVolumeTween(activeTweens, volumeId, token); + } + + private static void CancelVolumeTween(Volume volume, Dictionary activeTweens) + { + if (volume != null) + activeTweens.Remove(volume.GetInstanceID()); + } + + private static bool IsCurrentVolumeTween( + Dictionary activeTweens, + int volumeId, + long token) + { + return activeTweens.TryGetValue(volumeId, out var activeToken) && activeToken == token; + } + + private static void CompleteVolumeTween( + Dictionary activeTweens, + int volumeId, + long token) + { + if (IsCurrentVolumeTween(activeTweens, volumeId, token)) + activeTweens.Remove(volumeId); + } + private static float EaseInOutSine(float progress) { progress = Mathf.Clamp01(progress);