using System.Collections; using System.Collections.Generic; using AibisDream.FixSystem; using AibisDream; using Yarn.Unity; namespace AibisDream.MiniGame.Language { /// /// 表达系统的 Yarn 命令接口(原语言系统) /// public static class LanguageYarnCommand { private static AibisDream.ExpressionManager ExpressionManager => FixSystemCenter.SystemDic.Get(); private static bool TryGetPresentation(out LogReleasePresentationController presentation) { presentation = ExpressionManager != null ? ExpressionManager.LogReleasePresentation : null; if (presentation != null) return true; UnityEngine.Debug.LogError( "[LanguageYarnCommand] LogReleasePresentationController 未找到;演出命令安全结束。"); return false; } /// /// 启动表达粒子系统(在打开视图后调用),等待火山表达panel播完再返回。 /// 流程:若有上一轮则先淡出字与连线 → 再淡入火山释放 log → 再启动新一轮并等表达 panel 就绪。 /// 注意:Yarn Spinner 2.x 对同名 重载支持不可靠,只保留一个注册入口,用可选参数区分 3/4 参调用。 /// <> /// <> /// (第四项为「非目标」候选粒子总数,候选池 = 目标句字数 + 该值;不写第四项则用 Inspector 的 Candidate Count) /// /// 干扰短句(笑话等),用 | 分隔,用于非目标粒子字符池,如:"哈哈|嘿嘿|呵呵" /// 目标句子 /// 完成时触发的对话节点(可空字符串) /// 非目标候选粒子总数;<0 表示使用 Inspector 默认 [YarnCommand("start_expression")] public static IEnumerator StartExpression( string anxietyPhrasesStr, string targetSentence, string completionNode = "", float nonTargetParticleTotal = -1f) { return RunStartExpression( anxietyPhrasesStr, targetSentence, completionNode ?? "", UnityEngine.Mathf.RoundToInt(nonTargetParticleTotal)); } private static IEnumerator RunStartExpression(string anxietyPhrasesStr, string targetSentence, string completionNode, int nonTargetParticleTotal) { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!请确保场景中有 ExpressionManager 组件。"); yield break; } string[] phrases = null; if (!string.IsNullOrEmpty(anxietyPhrasesStr)) { phrases = anxietyPhrasesStr.Split('|'); for (int i = 0; i < phrases.Length; i++) { phrases[i] = phrases[i].Trim(); } } // 先清理上一轮演出,再淡出旧文字/连线并恢复 Log 操作界面。 yield return ExpressionManager.PreparePresentationForNextRound(); yield return ExpressionManager.FadeOutParticlesBeforeNewRound(0f); yield return ExpressionManager.EnsureReleaseLogFadedIn(1f); ExpressionManager.StartSystem(phrases, targetSentence, completionNode, nonTargetParticleTotal); yield return ExpressionManager.WaitUntilExpressionFlowReady(); } /// /// 关闭表达系统 /// <> /// [YarnCommand("close_expression")] public static void CloseExpression() { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); return; } ExpressionManager.CloseView(); } /// /// 重置表达系统(使用当前配置) /// <> /// 或 /// <> // 不播放入场动画 /// /// 是否播放入场效果 [YarnCommand("reset_expression")] public static void ResetExpression(bool playEntranceEffect = true) { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); return; } ExpressionManager.ResetSystem(playEntranceEffect); } /// /// 触发聚焦稳定化(从文字飘动保持态 → 概率递增 → 文字锁定 → 排列),等待全流程完成后返回 /// <> /// [YarnCommand("resolve_expression_focus")] public static IEnumerator ResolveExpressionFocus() { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine(ExpressionManager.ResolveFocusAndWait()); } /// /// 淡入 ExpressionManager 的 Sprite 图片 /// <> /// <> /// /// 淡入时长(秒),默认 1 [YarnCommand("expression_sprite_fade_in")] public static IEnumerator ExpressionSpriteFadeIn(float duration = 1f) { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine(ExpressionManager.FadeInSpriteOverlay(duration)); } /// /// 淡出 ExpressionManager 的 Sprite 图片 /// <> /// <> /// /// 淡出时长(秒),默认 1 [YarnCommand("expression_sprite_fade_out")] public static IEnumerator ExpressionSpriteFadeOut(float duration = 1f) { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine(ExpressionManager.FadeOutSpriteOverlay(duration)); } /// /// Glitch 噪波过渡,等待完成后再继续下一步。 /// <> -- 从 0 到 0.95,2 秒 /// <> -- 立即到 0.95(duration 默认 0) /// <> -- 从 0.3 到 0.45,1 秒 /// [YarnCommand("glitch_transition")] public static IEnumerator GlitchTransition(float to, float duration = 0f) { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine(ExpressionManager.TransitionGlitchAndWait(to, duration)); } [YarnCommand("expression_memory_begin")] public static IEnumerator ExpressionMemoryBegin( string memoryKey, string preset, float fadeDuration = -1f, float pushSpeed = -1f, float horizontalSpeed = -1f, bool preserveGlitch = false) { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine( ExpressionManager.BeginExpressionMemory( memoryKey, preset, fadeDuration, pushSpeed, horizontalSpeed, preserveGlitch)); } /// /// 显式淡入火山脸,并等待淡入完成。 /// <> /// [YarnCommand("expression_face_fade_in")] public static IEnumerator ExpressionFaceFadeIn(float duration = 0.45f) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.BeginFaceEntry(duration)); } [YarnCommand("expression_lie_begin")] public static IEnumerator ExpressionLieBegin(string keyword, string preset) { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine( ExpressionManager.BeginExpressionLie(keyword, preset)); } [YarnCommand("expression_lie_break")] public static IEnumerator ExpressionLieBreak() { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine(ExpressionManager.BreakExpressionLie()); } [YarnCommand("expression_truth_reveal")] public static IEnumerator ExpressionTruthReveal() { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine(ExpressionManager.RevealExpressionTruth()); } // 以下命令是一动作一命令。非 IEnumerator 命令只启动效果,节拍由 Yarn 的 wait 控制。 [YarnCommand("expression_lie_prepare")] public static void ExpressionLiePrepare(float freezeDuration, float noiseTarget) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.PrepareLieVisuals(freezeDuration, noiseTarget); } [YarnCommand("expression_truth_squeeze")] public static void ExpressionTruthSqueeze(float duration, float jitter, float alpha) { if (TryGetPresentation(out LogReleasePresentationController presentation)) 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) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.BeginLieCracking(lieAlpha); } [YarnCommand("expression_screen_dim")] public static void ExpressionScreenDim(float alpha, float riseDuration, float fallDuration) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.PlayScreenDim(alpha, riseDuration, fallDuration); } [YarnCommand("expression_memory_jolt")] public static void ExpressionMemoryJolt(float offset, float duration, float tear) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.PlayMemoryJolt(offset, duration, tear); } [YarnCommand("expression_truth_leak")] public static IEnumerator ExpressionTruthLeak(string fragment, float duration) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.LeakTruthFragment(fragment, duration)); } [YarnCommand("expression_lie_shuffle")] public static void ExpressionLieShuffle( string characterPool, float duration, float interval) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.StartLieCharacterShuffle(characterPool, duration, interval); } /// /// 演员大字闪现(阻塞):抖动的粒子字瞬间隐藏,屏幕中央出现白色大字(红青色散双影+急速缩放), /// 停顿 holdDuration 秒后恢复粒子字抖动。 /// <> /// [YarnCommand("expression_actor_flash")] public static IEnumerator ExpressionActorFlash( string text, float holdDuration = 0.6f, float fontSize = 10.5f, float settledScale = -1f, float punchScale = -1f, float chromaDistance = -1f, float chromaAlpha = -1f, float impact = -1f, float glitchPeak = -1f) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.FlashActorLie( text, holdDuration, fontSize, settledScale, punchScale, chromaDistance, chromaAlpha, impact, glitchPeak)); } /// /// 老虎机换字(非阻塞,节拍由 Yarn wait 控制):聚焦字在 duration 内只从 charPool 里疯狂换字。 /// <> /// [YarnCommand("expression_actor_slot")] public static void ExpressionActorSlot( string charPool, float duration, float interval = 0.05f, float fontSize = 14f) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.StartActorSlotMachine(charPool, duration, interval, fontSize); } /// /// 将 Glitch、记忆冲击与画面推近缓慢堆到峰值,停住后保持峰值,等待后续硬切。 /// <> /// [YarnCommand("expression_overload_peak")] public static IEnumerator ExpressionOverloadPeak( float riseDuration = 0.75f, float holdDuration = 0.22f, float zoom = 1.10f, float glitchPeak = 1f, float impact = 1f) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.BuildActorOverloadPeak( riseDuration, holdDuration, zoom, glitchPeak, impact)); } /// /// 单字/短词满屏重击,并等待该拍结束。 /// <> /// [YarnCommand("expression_actor_word_hit")] public static IEnumerator ExpressionActorWordHit( string text, float holdDuration = 0.16f, float fontSize = 18f, float punchScale = 1.55f) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.PlayActorWordHit(text, holdDuration, fontSize, punchScale)); } /// /// 单列词组严格裁在表情屏内,像字幕一样无缝向下滚动。 /// <> /// [YarnCommand("expression_actor_scroll")] public static IEnumerator ExpressionActorScroll( string phraseList, float scrollDuration = 1.8f, float loopDuration = 0.85f, float holdDuration = 0.45f, float fontSize = 5.2f) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.ScrollActorLies( phraseList, scrollDuration, loopDuration, holdDuration, fontSize)); } [YarnCommand("expression_memory_cut")] public static void ExpressionMemoryCut() { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.CutMemoryAndGlitchImmediate(); } [YarnCommand("expression_truth_snap")] public static void ExpressionTruthSnap(float peripheral, float calmRadius) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.SnapTruthImmediate(peripheral, calmRadius); } [YarnCommand("expression_glitch_pulse")] public static void ExpressionGlitchPulse(float peak, float riseDuration, float fallDuration) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.PlayGlitchPulse(peak, riseDuration, fallDuration); } [YarnCommand("expression_truth_blackout")] public static IEnumerator ExpressionTruthBlackout(float duration, float alpha) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.HoldTruthBlackout(duration, alpha)); } [YarnCommand("expression_lie_split")] public static void ExpressionLieSplit( float duration, float distanceRatio, float stretchX, float squashY) { if (TryGetPresentation(out LogReleasePresentationController presentation)) { presentation.SplitLieVisual( duration, distanceRatio, stretchX, squashY); } } [YarnCommand("expression_truth_flash")] public static void ExpressionTruthFlash( float alpha, float riseDuration, float holdDuration, float fallDuration) { if (TryGetPresentation(out LogReleasePresentationController presentation)) { presentation.PlayTruthFlash( alpha, riseDuration, holdDuration, fallDuration); } } [YarnCommand("expression_memory_brightness_pulse")] public static void ExpressionMemoryBrightnessPulse( float amount, float riseDuration, float fallDuration) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.PlayMemoryBrightnessPulse(amount, riseDuration, fallDuration); } [YarnCommand("expression_memory_tear")] public static void ExpressionMemoryTear(float peak, float duration) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.PlayMemoryTear(peak, duration); } [YarnCommand("expression_face_dip")] public static void ExpressionFaceDip(float duration, float ratio) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.PlayFaceDip(duration, ratio); } [YarnCommand("expression_truth_release")] public static void ExpressionTruthRelease(float alphaDuration) { if (TryGetPresentation(out LogReleasePresentationController presentation)) presentation.ReleaseTruthCharacters(alphaDuration); } [YarnCommand("expression_truth_resolve")] public static IEnumerator ExpressionTruthResolve( float duration, float peripheral, float calmRadius) { if (!TryGetPresentation(out LogReleasePresentationController presentation)) yield break; yield return ExpressionManager.StartCoroutine( presentation.ResolveTruthCharacters(duration, peripheral, calmRadius)); } [YarnCommand("expression_memory_end")] public static IEnumerator ExpressionMemoryEnd() { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); yield break; } yield return ExpressionManager.StartCoroutine(ExpressionManager.EndExpressionMemory()); } [YarnCommand("expression_truth_impact")] public static void ExpressionTruthImpact() { if (ExpressionManager == null) { UnityEngine.Debug.LogError("ExpressionManager 未找到!"); return; } ExpressionManager.ImpactExpressionTruth(); } // /// // /// Glitch 噪波过渡(指定起止值),等待完成后再继续下一步。 // /// // [YarnCommand("glitch_transition")] // public static IEnumerator GlitchTransition(float from, float to, float duration) // { // if (ExpressionManager == null) // { // UnityEngine.Debug.LogError("ExpressionManager 未找到!"); // yield break; // } // yield return ExpressionManager.StartCoroutine(ExpressionManager.TransitionGlitchAndWait(from, to, duration)); // } } }