You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity Editor Window中Handles.ArrowHandleCap不显示箭头的问题

箭头无法显示的原因及修复方案

我帮你排查了代码里的几个关键问题,这就是箭头没法显示的核心原因:

  1. 坐标空间不匹配:EditorWindow的GUI用的是窗口本地坐标系,但Handles默认基于世界空间绘制,直接传窗口坐标会让箭头画在可视区域外。
  2. Handles绘制未在正确上下文:必须用Handles.BeginGUI()Handles.EndGUI()包裹Handles相关绘制,Unity才会把坐标转换到EditorWindow的本地空间。
  3. 箭头旋转方向错误:你原来的Quaternion.LookRotation(Vector3.right)会让箭头指向右侧,而你的连线是从左节点右侧连到右节点左侧,箭头应该指向左侧才能指示流向。
  4. 绘制层级问题:曲线和箭头绘制在节点窗口之前,会被窗口挡住,导致看不见。

具体修复步骤

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

火山引擎 最新活动