feat(huoshan): 校准表达屏布局与状态文字

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-26 14:30:56 +08:00
co-authored by Cursor
parent 52fe5c9485
commit 2dafeb8432
3 changed files with 116 additions and 14 deletions
+18 -8
View File
@@ -11799,7 +11799,7 @@ RectTransform:
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0.68, y: -3.41}
m_SizeDelta: {x: 8, y: 8}
m_SizeDelta: {x: 8.6, y: 8.6}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!95 &1390110700
Animator:
@@ -15877,10 +15877,20 @@ MonoBehaviour:
- {fileID: 3026354965058437897, guid: 9f16e7c0b1ad4f8ca326cc74d2a7e501, type: 3}
- {fileID: 8353437890852674847, guid: 9f16e7c0b1ad4f8ca326cc74d2a7e501, type: 3}
- {fileID: -7585816161148619266, guid: 9f16e7c0b1ad4f8ca326cc74d2a7e501, type: 3}
screenLocalPosition: {x: 0.68, y: -8.95, z: 0}
screenLocalScale: {x: 1.1, y: 1.1, z: 1}
integrationProgressText: {fileID: 4809132844776029470}
interferenceCountText: {fileID: 700187870001090773}
outputButton: {fileID: 686920449707611471}
screenFont: {fileID: 11400000, guid: f242fb3dde1933640859f1c54591c9c8, type: 2}
integrationStatusPosition: {x: -8.75, y: 4.15}
interferenceStatusPosition: {x: -8.75, y: 3.08}
statusPanelSize: {x: 4.55, y: 0.6}
statusTextMargins: {x: 0.16, y: 0.05, z: 0.08, w: 0.05}
statusFontSize: 0.26
screenTextColor: {r: 0.78, g: 0.91, b: 1, a: 1}
outputButtonPosition: {x: 4.86, y: -0.065}
outputButtonSize: {x: 2.72, y: 1.13}
objectivePosition: {x: -8.18, y: -4.08}
objectiveSize: {x: 7.4, y: 0.95}
objectiveFontSize: 0.28
@@ -16530,7 +16540,7 @@ RectTransform:
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0.68, y: -3.41}
m_SizeDelta: {x: 8, y: 8}
m_SizeDelta: {x: 8.6, y: 8.6}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1057368176524979656
MonoBehaviour:
@@ -18078,7 +18088,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
worldCanvas: {fileID: 1390110703}
canvasSize: 9
canvasSize: 8.6
layoutShape: 1
circleRadiusOverride: -1
chineseFontAsset: {fileID: 11400000, guid: f242fb3dde1933640859f1c54591c9c8, type: 2}
@@ -18089,7 +18099,7 @@ MonoBehaviour:
candidateCount: 40
redParticleCount: 8
connectionDistance: 1.8
textMargin: 0.5
textMargin: 0.45
anxietyPhrases: []
targetSentence: "\u522B\u8FC7\u6765\u6211\u611F\u89C9\u5BB3\u6015"
completionDialogNode:
@@ -19500,8 +19510,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 4.8, y: 0.25}
m_SizeDelta: {x: 1, y: 1}
m_AnchoredPosition: {x: 4.86, y: -0.065}
m_SizeDelta: {x: 2.72, y: 1.13}
m_Pivot: {x: 0, y: 0.5}
--- !u!212 &6432803466182350851
SpriteRenderer:
@@ -20047,8 +20057,8 @@ Transform:
m_GameObject: {fileID: 6969460407008948536}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0.68, y: -9.200001, z: 0}
m_LocalScale: {x: 1.15, y: 1.15, z: 1}
m_LocalPosition: {x: 0.68, y: -8.95, z: 0}
m_LocalScale: {x: 1.1, y: 1.1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4035817972811077304}
@@ -45,6 +45,8 @@ namespace AibisDream.MiniGame.Language
[Header("Frame Animation")]
[SerializeField] private SpriteRenderer screenRenderer;
[SerializeField] private Sprite[] frames = new Sprite[53];
[SerializeField] private Vector3 screenLocalPosition = new Vector3(0.68f, -8.95f, 0f);
[SerializeField] private Vector3 screenLocalScale = new Vector3(1.1f, 1.1f, 1f);
[Header("Existing TMP / Interaction")]
[SerializeField] private TMP_Text integrationProgressText;
@@ -52,6 +54,18 @@ namespace AibisDream.MiniGame.Language
[SerializeField] private Button outputButton;
[SerializeField] private TMP_FontAsset screenFont;
[Header("Status TMP (screen-space world units)")]
[SerializeField] private Vector2 integrationStatusPosition = new Vector2(-8.75f, 4.15f);
[SerializeField] private Vector2 interferenceStatusPosition = new Vector2(-8.75f, 3.08f);
[SerializeField] private Vector2 statusPanelSize = new Vector2(4.55f, 0.6f);
[SerializeField] private Vector4 statusTextMargins = new Vector4(0.16f, 0.05f, 0.08f, 0.05f);
[SerializeField] private float statusFontSize = 0.26f;
[SerializeField] private Color screenTextColor = new Color(0.78f, 0.91f, 1f, 1f);
[Header("Output Button Hit Area")]
[SerializeField] private Vector2 outputButtonPosition = new Vector2(4.86f, -0.065f);
[SerializeField] private Vector2 outputButtonSize = new Vector2(2.72f, 1.13f);
[Header("Objective TMP (384x216 reference)")]
[SerializeField] private Vector2 objectivePosition = new Vector2(-8.18f, -4.08f);
[SerializeField] private Vector2 objectiveSize = new Vector2(7.4f, 0.95f);
@@ -96,6 +110,12 @@ namespace AibisDream.MiniGame.Language
{
outputText = outputButton.GetComponentInChildren<TMP_Text>(true);
}
if (screenRenderer != null)
{
screenRenderer.transform.localPosition = screenLocalPosition;
screenRenderer.transform.localScale = screenLocalScale;
}
}
private void ConfigureExistingUiAsTextOnly()
@@ -103,10 +123,9 @@ namespace AibisDream.MiniGame.Language
MakeParentImageTransparent(integrationProgressText);
MakeParentImageTransparent(interferenceCountText);
if (integrationProgressText != null)
integrationProgressText.raycastTarget = false;
if (interferenceCountText != null)
interferenceCountText.raycastTarget = false;
ConfigureStatusText(integrationProgressText, integrationStatusPosition);
ConfigureStatusText(interferenceCountText, interferenceStatusPosition);
ConfigureOutputText();
if (outputButton != null && outputButton.targetGraphic != null)
{
@@ -117,6 +136,75 @@ namespace AibisDream.MiniGame.Language
}
}
private void ConfigureStatusText(TMP_Text text, Vector2 panelPosition)
{
if (text == null)
return;
if (screenFont != null)
text.font = screenFont;
text.fontSize = statusFontSize;
text.fontStyle = FontStyles.Normal;
text.color = screenTextColor;
text.alignment = TextAlignmentOptions.MidlineLeft;
text.enableWordWrapping = false;
text.overflowMode = TextOverflowModes.Truncate;
text.margin = statusTextMargins;
text.raycastTarget = false;
if (text.transform.parent is RectTransform panelRect)
{
panelRect.anchorMin = new Vector2(0.5f, 0.5f);
panelRect.anchorMax = new Vector2(0.5f, 0.5f);
panelRect.pivot = new Vector2(0f, 0.5f);
panelRect.anchoredPosition = panelPosition;
panelRect.sizeDelta = statusPanelSize;
}
RectTransform textRect = text.rectTransform;
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.pivot = new Vector2(0.5f, 0.5f);
textRect.anchoredPosition = Vector2.zero;
textRect.sizeDelta = Vector2.zero;
}
private void ConfigureOutputText()
{
if (outputButton == null)
return;
RectTransform buttonRect = outputButton.transform as RectTransform;
if (buttonRect != null)
{
buttonRect.anchorMin = new Vector2(0.5f, 0.5f);
buttonRect.anchorMax = new Vector2(0.5f, 0.5f);
buttonRect.pivot = new Vector2(0f, 0.5f);
buttonRect.anchoredPosition = outputButtonPosition;
buttonRect.sizeDelta = outputButtonSize;
}
if (outputText == null)
return;
if (screenFont != null)
outputText.font = screenFont;
outputText.fontStyle = FontStyles.Normal;
outputText.color = screenTextColor;
outputText.alignment = TextAlignmentOptions.Center;
outputText.enableWordWrapping = false;
outputText.overflowMode = TextOverflowModes.Truncate;
RectTransform textRect = outputText.rectTransform;
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.pivot = new Vector2(0.5f, 0.5f);
textRect.anchoredPosition = Vector2.zero;
textRect.sizeDelta = Vector2.zero;
}
private static void MakeParentImageTransparent(TMP_Text text)
{
if (text == null || text.transform.parent == null)
@@ -177,9 +265,9 @@ namespace AibisDream.MiniGame.Language
text.fontSharedMaterial = objectiveMaterial;
}
text.fontSize = objectiveFontSize;
text.fontStyle = FontStyles.Bold;
text.fontStyle = FontStyles.Normal;
text.color = objectiveColor;
text.alignment = TextAlignmentOptions.Left;
text.alignment = TextAlignmentOptions.MidlineLeft;
text.enableWordWrapping = true;
text.overflowMode = TextOverflowModes.Truncate;
text.raycastTarget = false;
@@ -654,6 +654,10 @@ namespace AibisDream.MiniGame.Language
// 确保 Canvas 配置正确
if (worldCanvas != null)
{
RectTransform rectTransform = worldCanvas.GetComponent<RectTransform>();
if (rectTransform != null)
rectTransform.sizeDelta = new Vector2(canvasSize, canvasSize);
// 设置 WorldSpace Canvas 的相机
if (worldCanvas.worldCamera == null)
{