fix: 火山玩法本地化问题

This commit is contained in:
2026-08-02 19:26:56 +08:00
parent 6c46874e44
commit 2fa3eb8024
4 changed files with 126 additions and 29 deletions
@@ -11,7 +11,7 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a86a72005fba4c99a59962fb9e92df83, type: 3}
m_Name: ExpressionContentCatalog
m_EditorClassIdentifier:
m_EditorClassIdentifier:
rounds:
- id: log1
targetReference: l10n.hs.exp.log1.target
@@ -20,8 +20,8 @@ MonoBehaviour:
- id: log2
targetReference: l10n.hs.exp.log2.target
tokenReference: l10n.hs.exp.log2.tokens
nonTargetParticleCount: 28
nonTargetParticleCount: 26
- id: log3
targetReference: l10n.hs.exp.log3.target
tokenReference: l10n.hs.exp.log3.tokens
nonTargetParticleCount: 38
nonTargetParticleCount: 34
@@ -31,33 +31,33 @@ MonoBehaviour:
minimumReadablePhraseScale: 0.65
- localeCode: en
unitMode: 1
targetFontScale: 0.75
nonTargetFontScale: 0.7
floatingFontScale: 0.7
nonTargetCountScale: 0.75
targetFontScale: 0.85
nonTargetFontScale: 0.8
floatingFontScale: 0.8
nonTargetCountScale: 0.85
wordSpacing: 0.18
minimumReadablePhraseScale: 0.65
- localeCode: es
unitMode: 1
targetFontScale: 0.75
nonTargetFontScale: 0.7
floatingFontScale: 0.7
nonTargetCountScale: 0.75
targetFontScale: 0.85
nonTargetFontScale: 0.8
floatingFontScale: 0.8
nonTargetCountScale: 0.85
wordSpacing: 0.18
minimumReadablePhraseScale: 0.65
- localeCode: ru
unitMode: 1
targetFontScale: 0.75
nonTargetFontScale: 0.7
floatingFontScale: 0.7
nonTargetCountScale: 0.75
targetFontScale: 0.85
nonTargetFontScale: 0.8
floatingFontScale: 0.8
nonTargetCountScale: 0.85
wordSpacing: 0.18
minimumReadablePhraseScale: 0.65
- localeCode: pt-BR
unitMode: 1
targetFontScale: 0.75
nonTargetFontScale: 0.7
floatingFontScale: 0.7
nonTargetCountScale: 0.75
targetFontScale: 0.85
nonTargetFontScale: 0.8
floatingFontScale: 0.8
nonTargetCountScale: 0.85
wordSpacing: 0.18
minimumReadablePhraseScale: 0.65
@@ -2222,6 +2222,44 @@ namespace AibisDream.MiniGame.Language
}
}
/// <summary>
/// 只恢复当前演出短语使用的粒子;超出短语长度的旧词保持隐藏。
/// </summary>
public void SetCurrentPresentationPhraseAlpha(
float targetAlpha,
float duration = 0f)
{
List<CandidateParticle> particles = GetPresentationPhraseParticles();
int visibleCount = finalTargetUnits.Count > 0
? Mathf.Min(finalTargetUnits.Count, particles.Count)
: particles.Count;
float alphaValue = Mathf.Clamp01(targetAlpha);
for (int i = 0; i < particles.Count; i++)
{
CandidateParticle particle = particles[i];
if (particle == null)
continue;
DOTween.Kill(particle);
float destinationAlpha = i < visibleCount ? alphaValue : 0f;
if (duration <= 0f)
{
particle.alpha = destinationAlpha;
}
else
{
DOTween.To(
() => particle.alpha,
value => particle.alpha = value,
destinationAlpha,
duration)
.SetEase(Ease.OutQuad)
.SetTarget(particle);
}
}
}
/// <summary>
/// 将已完成聚焦的目标粒子改排为红色攻击词。文字必须完整放进现有目标粒子,
/// 超长时拒绝播放,避免演出层静默删字。
@@ -2433,10 +2471,12 @@ namespace AibisDream.MiniGame.Language
/// </summary>
public IEnumerator SettleTruthPhraseAndWait(string text, float duration)
{
List<CandidateParticle> particles = GetPresentationPhraseParticles();
List<string> units = TokenizeActiveText(text);
List<CandidateParticle> particles = GetPresentationPhraseParticles(
units.Count,
allowExpansion: true);
if (!ValidatePresentationPhrase(text, particles, "真话稳定"))
yield break;
List<string> units = TokenizeActiveText(text);
PreparePresentationPhraseControl();
@@ -2555,19 +2595,74 @@ namespace AibisDream.MiniGame.Language
}
}
private List<CandidateParticle> GetPresentationPhraseParticles()
private List<CandidateParticle> GetPresentationPhraseParticles(
int requiredCount = 0,
bool allowExpansion = false)
{
List<CandidateParticle> particles = orderedRedParticles
.Where(particle => particle != null)
.Distinct()
.ToList();
if (particles.Count > 0)
if (particles.Count == 0)
{
particles = targetParticles
.Where(particle => particle != null)
.OrderBy(particle => particle.transform.position.x)
.ToList();
}
if (!allowExpansion || requiredCount <= particles.Count)
return particles;
return targetParticles
.Where(particle => particle != null)
.OrderBy(particle => particle.transform.position.x)
.ToList();
// 最终稳定文案可能比本轮目标句更长(英文和俄文尤其常见)。
// 此时玩法已经结束,干扰粒子也已淡出,可以安全复用它们补足展示容量,
// 避免容量校验跳过整段收尾并把上一句攻击词留在红色失稳状态。
if (candidateParticles.Count < requiredCount)
EnsureCandidatePoolSize(requiredCount);
var existing = new HashSet<CandidateParticle>(particles);
CandidateParticle[] sourceParticles = particles.ToArray();
Vector3 phraseCenter = sourceParticles.Length > 0
? ComputeCentroid(particles)
: (worldCanvas != null ? worldCanvas.transform.position : transform.position);
foreach (CandidateParticle particle in candidateParticles
.Where(particle => particle != null && !existing.Contains(particle))
.OrderBy(particle =>
(particle.transform.position - phraseCenter).sqrMagnitude))
{
int sourceIndex = particles.Count - sourceParticles.Length;
Vector3 sourcePosition = sourceParticles.Length > 0
? sourceParticles[sourceIndex % sourceParticles.Length].transform.position
: phraseCenter;
particle.transform.DOKill();
DOTween.Kill(particle);
particle.transform.position = sourcePosition;
particle.transform.localScale = Vector3.one * ResolvedFocusScale;
particle.velocity = Vector2.zero;
particle.isRed = true;
particle.isTemporaryRed = true;
particle.isOrange = false;
particle.hasEffect = false;
particle.isCalmed = true;
particle.isStatic = true;
particle.anxietyShakeIntensity = 0f;
particle.ClearFocusInterference();
particle.alpha = 0f;
particles.Add(particle);
existing.Add(particle);
if (!targetParticles.Contains(particle))
targetParticles.Add(particle);
if (!orderedRedParticles.Contains(particle))
orderedRedParticles.Add(particle);
if (particles.Count >= requiredCount)
break;
}
return particles;
}
private bool ValidatePresentationPhrase(
@@ -2698,7 +2793,7 @@ namespace AibisDream.MiniGame.Language
activeSnapshot?.Profile?.MinimumReadablePhraseScale ?? 0.65f;
if (activePhraseScale < minimumReadable)
{
Debug.LogError(
Debug.LogWarning(
$"[LanguageParticleManager] 表达文字需要缩放到 {activePhraseScale:0.00}" +
$"低于 Locale Profile 最小可读值 {minimumReadable:0.00}" +
"运行时仍会缩放以保证文字完整显示。");
@@ -2770,6 +2865,8 @@ namespace AibisDream.MiniGame.Language
nonTargetParticleFontSize,
false,
nonTargetParticleBold);
particle.anxietyShakeIntensity = 0f;
particle.ClearFocusInterference();
}
}
@@ -901,7 +901,7 @@ namespace AibisDream.MiniGame.Language
particleManager?.PrepareTruthReleaseFromLie();
particleManager?.ApplyPresentationResolvedVisuals(presentationResolvedColor);
particleManager?.SetTargetParticlesAlpha(1f, 0f);
particleManager?.SetCurrentPresentationPhraseAlpha(1f, 0f);
Bounds truthBounds = particleManager != null
? particleManager.GetFinalTruthWorldBounds()
: new Bounds(GetScreenBounds().center, Vector3.one);