NGUI实现反向定位到层级面板结点

发布于:2025-07-07 ⋅ 阅读:(20) ⋅ 点赞:(0)

目的:方便还原工种快速定位到结点

操作:Game视图下,鼠标悬浮UI,双击F,反向定位到层级面板的结点

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class UIHoverFinder : MonoBehaviour 
{
    float lastFKeyTime = -1f;
    float doubleClickDur = 0.3f; // 0.3秒内算双击

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            if (Time.time - lastFKeyTime < doubleClickDur)
            {
                // 检测到双击F键
                OnDoubleFKey();
                lastFKeyTime = -1f; // 重置
            }
            else
            {
                lastFKeyTime = Time.time;
            }
        }
    }

    private void OnDoubleFKey()
    {
        GameObject hovered = UICamera.hoveredObject;
        if (hovered != null)
        {
            //判断没有BoxCollider时是否点击到
            Vector3 mousePos = Input.mousePosition;
            UIWidget[] allWidgets = hovered.transform.GetComponentsInChildren<UIWidget>();
            UIWidget res=null;
            for (int i = 0; i < allWidgets.Length; i++)
            {
                Rect screenRect = GetScreenRect(allWidgets[i]);
                if (screenRect.Contains(mousePos))
                {
                    if (res == null || allWidgets[i].depth > res.depth)
                    {
                        res = allWidgets[i];
                    }
                }
            }
            UnityEditor.Selection.activeGameObject = res!=null?res.gameObject:hovered;
        }
        else
        {
            Debug.Log("鼠标下没有NGUI控件");
        }
    }
    
    private Rect GetScreenRect(UIWidget widget)
    {
        if (widget == null) return new Rect();

        // 获取四个世界角点
        Vector3[] corners = widget.worldCorners;
        if (corners == null || corners.Length < 4) return new Rect();

        // 找到对应的摄像机
        Camera cam = NGUITools.FindCameraForLayer(widget.gameObject.layer);
        if (cam == null) return new Rect();

        // 转换到屏幕坐标
        Vector3 v0 = cam.WorldToScreenPoint(corners[0]);
        Vector3 v2 = cam.WorldToScreenPoint(corners[2]);

        // 注意:Unity屏幕坐标y轴是从下到上
        float xMin = Mathf.Min(v0.x, v2.x);
        float yMin = Mathf.Min(v0.y, v2.y);
        float width = Mathf.Abs(v2.x - v0.x);
        float height = Mathf.Abs(v2.y - v0.y);

        return new Rect(xMin, yMin, width, height);
    }
}