feat(huoshan): 迭代log释放演出与Yarn命令
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1623,6 +1623,98 @@ namespace AibisDream.MiniGame.Language
|
||||
.SetTarget(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 真话聚合挣扎(非等待):向 target 推进的途中反复"够到一点又被拽回去"。
|
||||
/// 回抽幅度必须跨过 UpdateTruthGatherLock 的 0.08 解锁带,已锁的字才会崩开重新乱跳——
|
||||
/// 挣扎感来自进度曲线本身的往复,不依赖任何颜色或额外特效。
|
||||
/// </summary>
|
||||
/// <param name="target">最终停留的聚合进度</param>
|
||||
/// <param name="duration">整段时长</param>
|
||||
/// <param name="tugs">回抽次数;<=0 时退化为普通聚合</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 真话聚合崩塌(非等待):进度被一口气拽回 0,所有已锁的字沿原路退回悬浮位并恢复乱跳。
|
||||
/// Ease.InBack 会先向上顶一点点再垮掉——"又够了一下下,然后整个塌了"。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>真话聚合被打断:目标字向外爆散并恢复乱跳(非等待)。</summary>
|
||||
public void ScatterTruthGather(float burstDistance)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 真话聚合挣扎(非阻塞):向 target 推进的途中反复"够到一点又被拽回去",
|
||||
/// 已锁的字会崩开重新乱跳。挣扎感来自聚合曲线本身,不使用任何颜色或额外特效。
|
||||
/// <<expression_truth_strain 0.86 3.2 3>>
|
||||
/// </summary>
|
||||
/// <param name="target">最终停留的聚合进度</param>
|
||||
/// <param name="duration">整段时长</param>
|
||||
/// <param name="tugs">回抽次数(0~4);<=0 时退化为 expression_truth_gather</param>
|
||||
[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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 真话聚合崩塌(非阻塞):进度被一口气拽回 0,字沿原路退回悬浮位并恢复乱跳。
|
||||
/// 与 expression_truth_scatter 的区别:scatter 是径向爆散,collapse 是"被拽回去"。
|
||||
/// <<expression_truth_collapse 0.45>>
|
||||
/// </summary>
|
||||
[YarnCommand("expression_truth_collapse")]
|
||||
public static void ExpressionTruthCollapse(float duration = 0.45f)
|
||||
{
|
||||
if (TryGetPresentation(out LogReleasePresentationController presentation))
|
||||
presentation.CollapseTruthGatherAttempt(duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 火山脸错误闪红(非阻塞):聚合失败时短暂替换红屏 Sprite,随后恢复,并轻微下沉。
|
||||
/// 注意:LOG1/LOG2 的失败信号已明确不使用红色与脸部报错,此命令仅保留兼容。
|
||||
/// <<expression_face_error 0.5 0.85>>
|
||||
/// </summary>
|
||||
[YarnCommand("expression_face_error")]
|
||||
@@ -691,6 +696,27 @@ namespace AibisDream.MiniGame.Language
|
||||
presentation.PlayGlitchPulse(peak, riseDuration, fallDuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 火山「屏幕」Sprite 直驱撕裂花屏(非阻塞)。作用在屏幕材质,不是叠一层噪波。
|
||||
/// <paramref name="level"/> 是 0–1 的目标档位,<paramref name="duration"/> 是推到该档位的时间;
|
||||
/// 到位后一直保持(Shader 自带憋气/发力循环,不会变成静止花屏),要收掉就再调一次 level=0。
|
||||
/// <<expression_screen_glitch 0.55 1.2>> … <<expression_screen_glitch 0 1.5>>
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用现有目标粒子完整显示一个红色攻击词,并等待确定性的冲击动作结束。
|
||||
/// 超过目标粒子数量时会安全跳过,不会截断。
|
||||
|
||||
@@ -9,8 +9,8 @@ using UnityEngine;
|
||||
namespace AibisDream.MiniGame.Language
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>调节记忆的轻微失真扰动(非等待)。</summary>
|
||||
/// <summary>调节记忆材质的轻微失真扰动(非等待)。</summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>真话聚合挣扎(非等待):推进途中反复"够到又被拽回去",字会锁上再崩开。</summary>
|
||||
public void BeginTruthStrainAttempt(float target, float duration, int tugs)
|
||||
{
|
||||
if (!ExpectState(nameof(BeginTruthStrainAttempt), PresentationState.Memory))
|
||||
return;
|
||||
particleManager?.BeginTruthStrain(target, duration, tugs);
|
||||
}
|
||||
|
||||
/// <summary>真话聚合崩塌(非等待):进度被拽回 0,所有字沿原路退回并恢复乱跳。</summary>
|
||||
public void CollapseTruthGatherAttempt(float duration)
|
||||
{
|
||||
if (!ExpectState(nameof(CollapseTruthGatherAttempt), PresentationState.Memory))
|
||||
return;
|
||||
particleManager?.CollapseTruthGather(duration);
|
||||
}
|
||||
|
||||
/// <summary>火山脸错误闪红:聚合失败的报错信号(非等待)。</summary>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记忆材质上的瞬时失真脉冲(抬升 _SimGlitch 后回落),不再驱动 noise 叠层。
|
||||
/// 撕裂仍走 PlayMemoryTear / impact,避免两路抢同一参数。
|
||||
/// </summary>
|
||||
public void PlayGlitchPulse(float peak, float riseDuration, float fallDuration)
|
||||
{
|
||||
if (!ExpectState(
|
||||
@@ -1387,6 +1386,16 @@ namespace AibisDream.MiniGame.Language
|
||||
Mathf.Max(0.01f, fallDuration)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 已弃用:屏幕 Glitch 请走 ExpressionManager.SetScreenGlitchLevel(屏幕自身材质)。
|
||||
/// 记忆阶段失真请用 PlayGlitchPulse / 记忆 impact。
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>记忆材质瞬时失真:抬升 _SimGlitch 后回到基线。</summary>
|
||||
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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user