feat(huoshan): 迭代log释放演出与Yarn命令

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-25 15:56:53 +08:00
co-authored by Cursor
parent e2461ff0e5
commit bee4e0c796
3 changed files with 286 additions and 110 deletions
@@ -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">回抽次数;&lt;=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);&lt;=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"/> 是 01 的目标档位,<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
{