using UnityEngine; using System.Collections.Generic; using Shapes; namespace AibisDream.MiniGame.HuoShan { /// /// 语言想象系统主管理器 - 协调各模块工作 /// [RequireComponent(typeof(CircularViewport))] public class LanguageImaginationSystem : ImmediateModeShapeDrawer { [Header("场设置")] public float fieldWidth = 50f; public float fieldHeight = 50f; public int backgroundNodeCount = 200; [Header("圆形视口设置")] public float viewportRadius = 5f; [Header("连线设置")] public float connectionLineWidth = 0.05f; public Color backgroundConnectionColor = new Color(1f, 1f, 1f, 0.3f); public Color sentenceConnectionColor = Color.yellow; public Color candidateConnectionColor = Color.cyan; [Header("Gizmo调试设置")] public bool showGizmos = true; public bool showFieldBounds = true; public bool showNodes = true; public bool showConnections = true; public bool showSentenceNodes = true; public float nodeGizmoSize = 0.2f; private BackgroundTextLayer _backgroundLayer; private CircularViewport _viewport; private SentenceBuilder _sentenceBuilder; private void Start() { Initialize(); } private void Initialize() { // 初始化圆形视口 _viewport = GetComponent(); if (_viewport == null) { _viewport = gameObject.AddComponent(); } _viewport.viewportRadius = viewportRadius; // 初始化背景文字层 _backgroundLayer = new BackgroundTextLayer( fieldWidth, fieldHeight, backgroundNodeCount, transform ); // 初始化造句系统 _sentenceBuilder = new SentenceBuilder(_backgroundLayer, _viewport, this); } private void Update() { if (_backgroundLayer != null) { _backgroundLayer.Update(Time.deltaTime); } } public override void DrawShapes(Camera cam) { using (Draw.Command(cam)) { Draw.ResetAllDrawStates(); Draw.LineGeometry = LineGeometry.Volumetric3D; Draw.Thickness = connectionLineWidth; // 绘制背景文字之间的连线 if (_backgroundLayer != null) { DrawBackgroundConnections(); } // 绘制句子和候选文字的连线 if (_sentenceBuilder != null) { DrawSentenceConnections(); } } } private void DrawBackgroundConnections() { var allNodes = _backgroundLayer.GetAllNodes(); foreach (var node in allNodes) { // 只绘制在视口内的连线 if (!_viewport.IsPositionInViewport(node.Position)) continue; foreach (var connectedNode in node.ConnectedNodes) { // 只绘制连接的另一端也在视口内的连线 if (!_viewport.IsPositionInViewport(connectedNode.Position)) continue; // 跳过已经选定的节点之间的连线(由句子连线处理) if (node.State == TextNodeState.Selected || connectedNode.State == TextNodeState.Selected) continue; if (node.State == TextNodeState.Candidate || connectedNode.State == TextNodeState.Candidate) continue; Vector3 posA = new Vector3(node.Position.x, node.Position.y, 0); Vector3 posB = new Vector3(connectedNode.Position.x, connectedNode.Position.y, 0); // 根据节点亮度调整连线颜色 float avgBrightness = (node.Brightness + connectedNode.Brightness) * 0.5f; Color lineColor = backgroundConnectionColor * avgBrightness; Draw.Line(posA, posB, connectionLineWidth, lineColor); } } } private void DrawSentenceConnections() { var sentenceNodes = _sentenceBuilder.GetSentenceNodes(); // 绘制句子节点之间的连线(稳定清晰) for (int i = 0; i < sentenceNodes.Count - 1; i++) { var nodeA = sentenceNodes[i]; var nodeB = sentenceNodes[i + 1]; Vector3 posA = new Vector3(nodeA.Position.x, nodeA.Position.y, 0); Vector3 posB = new Vector3(nodeB.Position.x, nodeB.Position.y, 0); Draw.Line(posA, posB, connectionLineWidth * 2f, sentenceConnectionColor); } // 绘制候选文字与选定文字的连线 var allNodes = _backgroundLayer.GetAllNodes(); foreach (var node in allNodes) { if (node.State == TextNodeState.Candidate) { foreach (var connectedNode in node.ConnectedNodes) { if (connectedNode.State == TextNodeState.Selected) { Vector3 posA = new Vector3(node.Position.x, node.Position.y, 0); Vector3 posB = new Vector3(connectedNode.Position.x, connectedNode.Position.y, 0); // 根据概率调整连线颜色和宽度 float alpha = node.Probability; Color lineColor = candidateConnectionColor; lineColor.a = alpha; Draw.Line(posA, posB, connectionLineWidth * (0.5f + alpha * 0.5f), lineColor); } } } } } /// /// 开始构建句子(由Yarn指令调用) /// public void StartSentence(string sentence, int stuckIndex = -1) { if (_sentenceBuilder != null) { _sentenceBuilder.StartBuildingSentence(sentence, stuckIndex); } } /// /// 停止构建句子 /// public void StopSentence() { if (_sentenceBuilder != null) { _sentenceBuilder.StopBuilding(); } } private void OnDestroy() { if (_backgroundLayer != null) { _backgroundLayer.Cleanup(); } } private void OnDrawGizmos() { if (!showGizmos) return; // 绘制场边界 if (showFieldBounds) { Gizmos.color = new Color(0.5f, 0.5f, 0.5f, 0.3f); Vector3 center = transform.position; Vector3 size = new Vector3(fieldWidth, fieldHeight, 0.1f); Gizmos.DrawWireCube(center, size); } // 绘制节点和连线 if (_backgroundLayer != null && Application.isPlaying) { var allNodes = _backgroundLayer.GetAllNodes(); // 绘制节点 if (showNodes) { foreach (var node in allNodes) { Vector3 nodePos = new Vector3(node.Position.x, node.Position.y, 0) + transform.position; // 根据状态设置颜色 Color gizmoColor = GetNodeGizmoColor(node.State); Gizmos.color = gizmoColor * node.Brightness; // 根据状态设置大小 float size = nodeGizmoSize; if (node.State == TextNodeState.Selected) size = nodeGizmoSize * 1.5f; else if (node.State == TextNodeState.Candidate) size = nodeGizmoSize * 1.2f; else if (node.State == TextNodeState.Stuck) size = nodeGizmoSize * 1.3f; Gizmos.DrawSphere(nodePos, size); // 绘制文字标签 #if UNITY_EDITOR UnityEditor.Handles.Label(nodePos + Vector3.up * 0.5f, node.Text); #endif } } // 绘制连线 if (showConnections) { foreach (var node in allNodes) { Vector3 nodePos = new Vector3(node.Position.x, node.Position.y, 0) + transform.position; foreach (var connectedNode in node.ConnectedNodes) { Vector3 connectedPos = new Vector3(connectedNode.Position.x, connectedNode.Position.y, 0) + transform.position; // 根据节点状态设置连线颜色 Color lineColor = GetConnectionGizmoColor(node, connectedNode); Gizmos.color = lineColor; Gizmos.DrawLine(nodePos, connectedPos); } } } // 绘制句子节点 if (showSentenceNodes && _sentenceBuilder != null) { var sentenceNodes = _sentenceBuilder.GetSentenceNodes(); for (int i = 0; i < sentenceNodes.Count; i++) { var node = sentenceNodes[i]; Vector3 nodePos = new Vector3(node.Position.x, node.Position.y, 0) + transform.position; // 绘制句子节点高亮 Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(nodePos, nodeGizmoSize * 2f); // 绘制序号 #if UNITY_EDITOR UnityEditor.Handles.Label(nodePos + Vector3.up * 1f, $"[{i}]"); #endif // 绘制句子连线 if (i < sentenceNodes.Count - 1) { var nextNode = sentenceNodes[i + 1]; Vector3 nextPos = new Vector3(nextNode.Position.x, nextNode.Position.y, 0) + transform.position; Gizmos.color = Color.yellow; Gizmos.DrawLine(nodePos, nextPos); } } } } } private Color GetNodeGizmoColor(TextNodeState state) { return state switch { TextNodeState.Selected => Color.yellow, TextNodeState.Candidate => Color.cyan, TextNodeState.Stuck => Color.red, _ => Color.white }; } private Color GetConnectionGizmoColor(TextNode nodeA, TextNode nodeB) { // 句子连线 if (nodeA.State == TextNodeState.Selected && nodeB.State == TextNodeState.Selected) return Color.yellow; // 候选连线 if ((nodeA.State == TextNodeState.Candidate && nodeB.State == TextNodeState.Selected) || (nodeA.State == TextNodeState.Selected && nodeB.State == TextNodeState.Candidate)) return Color.cyan; // 背景连线 return new Color(1f, 1f, 1f, 0.3f); } } }