feat(eye): 移动结束后先眨眼再触发聚焦或想象效果

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-01 18:28:36 +08:00
co-authored by Cursor
parent aaf248a0ef
commit 9124a4bd6b
2 changed files with 103 additions and 13 deletions
@@ -1,5 +1,6 @@
using AibisDream.Framework;
using DG.Tweening;
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.Serialization;
@@ -83,11 +84,11 @@ namespace AibisDream
initialPosition = PanTransform.position;
}
public void MoveFocusTo(Transform target, float duration, Vector2 minBounds, Vector2 maxBounds, Vector2 viewportSize)
public Tween MoveFocusTo(Transform target, float duration, Vector2 minBounds, Vector2 maxBounds, Vector2 viewportSize)
{
if (target == null)
{
return;
return null;
}
Vector3 focusPosition = ClampFocusPosition(target.position, minBounds, maxBounds, viewportSize);
@@ -115,10 +116,26 @@ namespace AibisDream
if (duration <= 0f)
{
PanTransform.position = initialPosition + currentOffset;
return;
focusTween = null;
return null;
}
focusTween = PanTransform.DOMove(initialPosition + currentOffset, duration).SetEase(Ease.InOutSine);
return focusTween;
}
public IEnumerator WaitForFocusMove(float fallbackDuration = 0f)
{
if (focusTween != null && focusTween.IsActive())
{
yield return focusTween.WaitForCompletion();
yield break;
}
if (fallbackDuration > 0f)
{
yield return new WaitForSeconds(fallbackDuration);
}
}
private void Start()
+83 -10
View File
@@ -52,6 +52,81 @@ namespace AibisDream
public float GetEffectTransitionDuration() => visualSettings.GetDurationForState(_currentState);
private bool ShouldPreBlinkForFocusedEffect()
{
return _currentState is EyeColorState.CanImagineColor
or EyeColorState.CannotImagineColor
or EyeColorState.CanSeeColor;
}
private IEnumerator WaitForFocusMovement(float moveDuration)
{
if (!EnsureMouseFollowAndZoom())
{
yield break;
}
yield return mouseFollowAndZoom.WaitForFocusMove(moveDuration);
}
private IEnumerator RunFocusedEffectWithPreBlink(EyeTarget target)
{
if (EnsureMouseFollowAndZoom())
{
yield return mouseFollowAndZoom.WaitForFocusMove();
}
float duration = GetEffectTransitionDuration();
EyeViewportOverlay overlay = EnsureViewportOverlay();
if (overlay != null && Application.isPlaying && ShouldPreBlinkForFocusedEffect())
{
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);
}
}
else
{
eyeStateEffect?.ApplyFocusedEffect(target, this);
}
yield return new WaitForSeconds(duration);
}
private IEnumerator RunBlurOutWithPreBlink(EyeTarget target, float duration)
{
EyeViewportOverlay overlay = EnsureViewportOverlay();
if (overlay != null && Application.isPlaying)
{
yield return overlay.PlayPreEffectBlinkThen(
1,
visualSettings,
() => target.BlurOut(duration),
visualSettings.focusEffectAtBlinkOpen);
}
else
{
target.BlurOut(duration);
}
yield return new WaitForSeconds(duration);
}
private void OnValidate()
{
ApplyVisualSettingsNow(
@@ -289,7 +364,7 @@ namespace AibisDream
[YarnCommand("EyeBlink")]
public void EyeBlink(float duration = 0f)
{
EnsureViewportOverlay()?.PlayBlink(duration > 0f ? duration : null);
EnsureViewportOverlay()?.PlayBlink(duration > 0f ? duration : null, restartAutoBlinkAfter: true);
}
[YarnCommand("set_Eyetarget")]
@@ -311,28 +386,28 @@ namespace AibisDream
YarnVariableStorage.Instance.SetValue("$currentEyeTarget", target.name);
StartCoroutine(EyeEffect_FadeOut());
FocusOnTarget(target, 1f);
const float focusMoveDuration = 1f;
FocusOnTarget(target, focusMoveDuration);
if (currentTarget != null)
{
currentTarget.BlurIn(visualSettings.targetSwitchDuration);
}
yield return WaitForFocusMovement(focusMoveDuration);
if (currentTarget == target)
{
DialogController.Instance.StartDialogNode("重复看同一个目标");
currentTarget = target;
mouseFollowAndZoom.SetIndicatorTarget(currentTarget);
currentTarget.BlurOut(visualSettings.targetSwitchDuration);
yield return new WaitForSeconds(visualSettings.targetSwitchDuration);
yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration);
yield break;
}
currentTarget = target;
mouseFollowAndZoom.SetIndicatorTarget(currentTarget);
currentTarget.BlurOut(visualSettings.targetSwitchDuration);
yield return new WaitForSeconds(visualSettings.targetSwitchDuration);
yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration);
if (startDialogue)
{
@@ -357,10 +432,8 @@ namespace AibisDream
if (currentTarget != null)
{
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
eyeStateEffect?.ApplyFocusedEffect(currentTarget, this);
yield return RunFocusedEffectWithPreBlink(currentTarget);
}
yield return new WaitForSeconds(GetEffectTransitionDuration());
}
[YarnCommand("EyeEffect_FadeOut")]