From 1e8ec2e64fb73d63f5aafac8914daadcd4cbf41f Mon Sep 17 00:00:00 2001 From: bottlefish <781230111@qq.com> Date: Tue, 21 Jul 2026 01:18:46 +0800 Subject: [PATCH] =?UTF-8?q?feat(eye):=20=E7=9C=A8=E7=9C=BC=E4=BB=85?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E6=83=B3=E8=B1=A1=E4=B8=8A=E8=89=B2=E5=B9=B6?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E8=87=AA=E5=8A=A8=E7=9C=A8=E7=9C=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- Assets/Scenes/PeipeiFixScene.unity | 4 +- .../Scripts/MiniGame/Peipei/Eye/EyeSystem.cs | 114 +++++++----------- .../MiniGame/Peipei/Eye/EyeViewportOverlay.cs | 41 ++++++- .../MiniGame/Peipei/Eye/EyeVisualSettings.cs | 9 +- 4 files changed, 90 insertions(+), 78 deletions(-) diff --git a/Assets/Scenes/PeipeiFixScene.unity b/Assets/Scenes/PeipeiFixScene.unity index 8d153a7e0..f9aaf0d03 100644 --- a/Assets/Scenes/PeipeiFixScene.unity +++ b/Assets/Scenes/PeipeiFixScene.unity @@ -1025,8 +1025,8 @@ MonoBehaviour: eyeWidth: 0.557 eyeHeight: 0.549 edgeSoftness: 0.1871 - autoBlink: 1 - autoBlinkInterval: {x: 12, y: 18} + autoBlink: 0 + autoBlinkInterval: {x: 8, y: 15} blinkCloseDuration: 0.1 blinkOpenDuration: 0.1 focusEffectAtBlinkOpen: 0.85 diff --git a/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs b/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs index b7d1c6e07..35cb5f65d 100644 --- a/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs +++ b/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs @@ -52,11 +52,10 @@ namespace AibisDream public float GetEffectTransitionDuration() => visualSettings.GetDurationForState(_currentState); - private bool ShouldPreBlinkForFocusedEffect() + /// 仅「可想象色彩」上色时眨眼;无 autoBlink / 失焦眨眼。 + private bool ShouldBlinkForImagine() { - return _currentState is EyeColorState.CanImagineColor - or EyeColorState.CannotImagineColor - or EyeColorState.CanSeeColor; + return _currentState == EyeColorState.CanImagineColor; } private IEnumerator WaitForFocusMovement(float moveDuration) @@ -79,25 +78,14 @@ namespace AibisDream float duration = GetEffectTransitionDuration(); EyeViewportOverlay overlay = EnsureViewportOverlay(); - if (overlay != null && Application.isPlaying && ShouldPreBlinkForFocusedEffect()) + if (overlay != null && Application.isPlaying && ShouldBlinkForImagine()) { - if (_currentState == EyeColorState.CanImagineColor) - { - yield return overlay.PlayPreEffectBlinkThen( - 2, - visualSettings, - () => eyeStateEffect?.ApplyFocusedEffect(target, this), - visualSettings.imagineEffectAtBlinkOpen, - visualSettings.imagineBlinkGap); - } - else - { - yield return overlay.PlayPreEffectBlinkThen( - 1, - visualSettings, - () => eyeStateEffect?.ApplyFocusedEffect(target, this), - visualSettings.focusEffectAtBlinkOpen); - } + yield return overlay.PlayPreEffectBlinkThen( + 2, + visualSettings, + () => eyeStateEffect?.ApplyFocusedEffect(target, this), + visualSettings.imagineEffectAtBlinkOpen, + visualSettings.imagineBlinkGap); } else { @@ -107,19 +95,9 @@ namespace AibisDream yield return new WaitForSeconds(duration); } - private IEnumerator RunBlurOutWithPreBlink(EyeTarget target, float duration) + private IEnumerator RunBlurOut(EyeTarget target, float duration) { - EyeViewportOverlay overlay = EnsureViewportOverlay(); - - if (overlay != null && Application.isPlaying) - { - yield return overlay.PlayPreEffectBlinkThen( - 1, - visualSettings, - () => target.BlurOut(duration), - visualSettings.focusEffectAtBlinkOpen); - } - else + if (target != null) { target.BlurOut(duration); } @@ -127,42 +105,34 @@ namespace AibisDream yield return new WaitForSeconds(duration); } - private IEnumerator RunUnfocusedEffectWithPreBlink(EyeTarget target) + /// + /// 换目标时的失焦:只做效果,不眨眼(眨眼仅在想象上色 FadeIn)。 + /// + private void ApplyUnfocusedEffectSilent(EyeTarget target) + { + if (target == null || eyeStateEffect == null) + { + return; + } + + if (_currentState == EyeColorState.CanImagineColor + && target.IsAtUnfocusedColorState(visualSettings)) + { + return; + } + + eyeStateEffect.ApplyUnfocusedEffect(target, this); + } + + private IEnumerator RunUnfocusedEffect(EyeTarget target) { if (target == null || eyeStateEffect == null) { yield break; } - float duration = GetEffectTransitionDuration(); - EyeViewportOverlay overlay = EnsureViewportOverlay(); - - if (overlay != null && Application.isPlaying && ShouldPreBlinkForFocusedEffect()) - { - if (_currentState == EyeColorState.CanImagineColor) - { - yield return overlay.PlayPreEffectBlinkThen( - 2, - visualSettings, - () => eyeStateEffect.ApplyUnfocusedEffect(target, this), - visualSettings.imagineEffectAtBlinkOpen, - visualSettings.imagineBlinkGap); - } - else - { - yield return overlay.PlayPreEffectBlinkThen( - 1, - visualSettings, - () => eyeStateEffect.ApplyUnfocusedEffect(target, this), - visualSettings.focusEffectAtBlinkOpen); - } - } - else - { - eyeStateEffect.ApplyUnfocusedEffect(target, this); - } - - yield return new WaitForSeconds(duration); + eyeStateEffect.ApplyUnfocusedEffect(target, this); + yield return new WaitForSeconds(GetEffectTransitionDuration()); } private void OnValidate() @@ -347,6 +317,14 @@ namespace AibisDream EnsureViewportOverlay()?.EnterModule(visualSettings); } + /// + /// UF 等密集演出:抑制非显式眨眼(含想象过渡眨眼);Yarn EyeBlink 仍可用。 + /// + public void SetNonExplicitBlinkSuppressed(bool suppressed) + { + EnsureViewportOverlay()?.SetNonExplicitBlinkSuppressed(suppressed); + } + private void InitializeAllTargets() { foreach (EyeTarget target in targets) @@ -442,7 +420,7 @@ namespace AibisDream if (startDialogue) { DialogController.Instance.StartDialogNode("重复看同一个目标"); - yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration); + yield return RunBlurOut(currentTarget, visualSettings.targetSwitchDuration); } yield break; @@ -451,7 +429,7 @@ namespace AibisDream EyeTarget leavingTarget = currentTarget; if (leavingTarget != null) { - StartCoroutine(EyeEffect_FadeOut()); + ApplyUnfocusedEffectSilent(leavingTarget); } const float focusMoveDuration = 1f; @@ -461,7 +439,7 @@ namespace AibisDream currentTarget = target; mouseFollowAndZoom.SetIndicatorTarget(currentTarget); - yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration); + yield return RunBlurOut(currentTarget, visualSettings.targetSwitchDuration); if (startDialogue) { @@ -513,7 +491,7 @@ namespace AibisDream } AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine"); - yield return RunUnfocusedEffectWithPreBlink(currentTarget); + yield return RunUnfocusedEffect(currentTarget); } [YarnCommand("EyeEffect_Init")] diff --git a/Assets/Scripts/MiniGame/Peipei/Eye/EyeViewportOverlay.cs b/Assets/Scripts/MiniGame/Peipei/Eye/EyeViewportOverlay.cs index 8ea60a87a..17a0956b1 100644 --- a/Assets/Scripts/MiniGame/Peipei/Eye/EyeViewportOverlay.cs +++ b/Assets/Scripts/MiniGame/Peipei/Eye/EyeViewportOverlay.cs @@ -37,6 +37,10 @@ namespace AibisDream private float blinkOpen = 1f; private bool moduleActive; private bool editorPreviewActive; + /// + /// UF 等密集演出段:关掉 autoBlink 与效果过渡眨眼,仅保留 Yarn EyeBlink。 + /// + private bool suppressNonExplicitBlink; private bool hierarchyReady; private bool lifecycleReady; private Coroutine deferPrepareRoutine; @@ -75,6 +79,7 @@ namespace AibisDream public void ExitModule() { moduleActive = false; + suppressNonExplicitBlink = false; if (editorPreviewActive) { return; @@ -85,6 +90,27 @@ namespace AibisDream activeSettings = null; } + /// + /// 抑制自动眨眼与效果过渡眨眼;显式 PlayBlink / Yarn EyeBlink 仍可用。 + /// + public void SetNonExplicitBlinkSuppressed(bool suppressed) + { + suppressNonExplicitBlink = suppressed; + if (suppressed) + { + StopAutoBlink(); + return; + } + + if (activeSettings != null + && activeSettings.autoBlink + && Application.isPlaying + && (moduleActive || editorPreviewActive)) + { + StartAutoBlink(activeSettings); + } + } + public void EnterEditorPreview(EyeVisualSettings settings) { editorPreviewActive = true; @@ -141,7 +167,10 @@ namespace AibisDream return; } - if (settings.autoBlink && Application.isPlaying && (moduleActive || editorPreviewActive)) + if (settings.autoBlink + && Application.isPlaying + && (moduleActive || editorPreviewActive) + && !suppressNonExplicitBlink) { StartAutoBlink(settings); } @@ -256,6 +285,7 @@ namespace AibisDream return Application.isPlaying && moduleActive && !editorPreviewActive + && !suppressNonExplicitBlink && overlayShaderAvailable && settings != null && settings.enableViewportOverlay; @@ -268,6 +298,11 @@ namespace AibisDream return; } + if (suppressNonExplicitBlink) + { + return; + } + if (!(moduleActive || editorPreviewActive)) { return; @@ -301,7 +336,7 @@ namespace AibisDream SetOverlayActive(true); - if (settings.autoBlink && Application.isPlaying) + if (settings.autoBlink && Application.isPlaying && !suppressNonExplicitBlink) { StartAutoBlink(settings); } @@ -328,7 +363,7 @@ namespace AibisDream private void StartAutoBlink(EyeVisualSettings settings) { StopAutoBlink(); - if (!settings.autoBlink) + if (!settings.autoBlink || suppressNonExplicitBlink) { return; } diff --git a/Assets/Scripts/MiniGame/Peipei/Eye/EyeVisualSettings.cs b/Assets/Scripts/MiniGame/Peipei/Eye/EyeVisualSettings.cs index 6643f31df..e7edfd6d1 100644 --- a/Assets/Scripts/MiniGame/Peipei/Eye/EyeVisualSettings.cs +++ b/Assets/Scripts/MiniGame/Peipei/Eye/EyeVisualSettings.cs @@ -84,16 +84,15 @@ namespace AibisDream [Tooltip("Softness of the elliptical sight boundary.")] [Range(0.001f, 0.2f)] public float edgeSoftness = 0.022f; - [Tooltip("Off by default so you can tune the sight without blinking.")] + [Tooltip("Deprecated: unused. Blink only on imagine FadeIn.")] public bool autoBlink; - public Vector2 autoBlinkInterval = new(8f, 15f); + [HideInInspector] public Vector2 autoBlinkInterval = new(8f, 15f); public float blinkCloseDuration = 0.09f; public float blinkOpenDuration = 0.14f; - [Header("Transition Blink")] - [Tooltip("聚焦:单次眨眼开眼到该进度时触发变清晰(0=刚睁眼,1=完全睁开)。")] - [Range(0f, 1f)] public float focusEffectAtBlinkOpen = 0.85f; + [Header("Imagine Blink (EyeEffect_FadeIn only)")] + [HideInInspector] public float focusEffectAtBlinkOpen = 0.85f; [Tooltip("想象:两次眨眼之间的间隔(秒)。")] public float imagineBlinkGap = 0.04f;