Unity Editor Window中Handles.ArrowHandleCap不显示箭头的问题
箭头无法显示的原因及修复方案
我帮你排查了代码里的几个关键问题,这就是箭头没法显示的核心原因:
- 坐标空间不匹配:EditorWindow的GUI用的是窗口本地坐标系,但
Handles默认基于世界空间绘制,直接传窗口坐标会让箭头画在可视区域外。 - Handles绘制未在正确上下文:必须用
Handles.BeginGUI()和Handles.EndGUI()包裹Handles相关绘制,Unity才会把坐标转换到EditorWindow的本地空间。 - 箭头旋转方向错误:你原来的
Quaternion.LookRotation(Vector3.right)会让箭头指向右侧,而你的连线是从左节点右侧连到右节点左侧,箭头应该指向左侧才能指示流向。 - 绘制层级问题:曲线和箭头绘制在节点窗口之前,会被窗口挡住,导致看不见。
具体修复步骤
1. 调整绘制顺序,让箭头显示在节点上方
修改OnGUI()方法,把曲线绘制代码移到BeginWindows()和EndWindows()之后,这样箭头不会被节点窗口遮挡:
void OnGUI() { Rect graphPosition = new Rect(0f, 0f, position.width, position.height); GraphBackground.DrawGraphBackground(graphPosition, graphPosition); int selected = 0; string[] options = new string[] { "Option1", "Option2", "Option3", }; selected = EditorGUILayout.Popup("Label", selected, options); if (windowsToAttach.Count == 2) { attachedWindows.Add(windowsToAttach[0]); attachedWindows.Add(windowsToAttach[1]); windowsToAttach = new List<int>(); } // 先绘制节点窗口 BeginWindows(); if (GUILayout.Button("Create Node")) { windows.Add(new Rect(10, 10, 200, 40)); } for (int i = 0; i < windows.Count; i++) { windows[i] = GUI.Window(i, windows[i], DrawNodeWindow, "Window " + i); } EndWindows(); // 再绘制曲线和箭头,确保显示在节点上方 if (attachedWindows.Count >= 2) { for (int i = 0; i < attachedWindows.Count; i += 2) { DrawNodeCurve(windows[attachedWindows[i]], windows[attachedWindows[i + 1]]); } } }
2. 修复Handles的坐标上下文和箭头方向
修改DrawNodeCurve()方法,用Handles.BeginGUI()包裹绘制逻辑,并修正箭头旋转方向:
void DrawNodeCurve(Rect start, Rect end) { Vector3 startPos = new Vector3(start.x + start.width, start.y + start.height / 2, 0); Vector3 endPos = new Vector3(end.x, end.y + end.height / 2, 0); Vector3 startTan = startPos + Vector3.right * 50; Vector3 endTan = endPos + Vector3.left * 50; // 启动Handles的GUI上下文,转换到窗口本地坐标 Handles.BeginGUI(); // 绘制贝塞尔曲线 Handles.DrawBezier(startPos, endPos, startTan, endTan, Color.white, null, 5); // 设置箭头颜色为白色,调整大小到20(原来的10太小可能看不清) Handles.color = Color.white; // 箭头指向左侧(匹配连线进入end节点的方向) Quaternion arrowRotation = Quaternion.LookRotation(Vector3.left); // 绘制箭头,EventType.Repaint确保只在重绘时执行 Handles.ArrowHandleCap(0, endPos, arrowRotation, 20f, EventType.Repaint); // 结束Handles上下文 Handles.EndGUI(); }
备选方案:自定义箭头(如果Handles.ArrowHandleCap仍有问题)
如果还是无法显示系统箭头,可以用Handles.DrawLines绘制自定义三角形箭头,兼容性更好:
// 在DrawNodeCurve的Handles.BeginGUI()块中添加这段代码 Vector3 arrowDir = (startPos - endPos).normalized; // 箭头指向start到end的反向(即指向end节点) float arrowLength = 15f; float arrowWidth = 8f; // 计算箭头三个点的位置 Vector3 arrowTip = endPos; Vector3 arrowLeft = arrowTip + arrowDir * arrowLength + Vector3.Cross(arrowDir, Vector3.forward) * arrowWidth; Vector3 arrowRight = arrowTip + arrowDir * arrowLength - Vector3.Cross(arrowDir, Vector3.forward) * arrowWidth; // 绘制箭头的三条边 Handles.DrawLine(arrowTip, arrowLeft); Handles.DrawLine(arrowTip, arrowRight); Handles.DrawLine(arrowLeft, arrowRight);
内容的提问来源于stack exchange,提问作者Daniel Lip




