You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何让场景中Handle始终可见,选中时高亮、悬停时可选中?

Solution for Persistent, Highlightable Handles in Unity Editor

Alright, let's tackle these two Handle requirements for your Unity project. I've worked through similar scenarios before, so here's a step-by-step solution with code you can adapt right away.

1. Make Handles Always Visible + Highlight on Selection

By default, Unity only renders Handles when their parent GameObject is selected. To fix this, we'll force-draw the Handles every frame in the OnSceneGUI method of a custom Editor script. We'll also add logic to highlight the Handle when either the GameObject is selected or the mouse is hovering over it.

2. Show Handles Even When GameObject Is Unselected + Hover-to-Select

To let users select the GameObject by clicking the Handle (even if the object wasn't selected before), we'll track mouse interactions with the Handle using Unity's HandleUtility API. This lets us detect when the mouse is over the Handle and trigger a selection on click.

Full Implementation Code

Create a new Editor script (place it in an Editor folder to ensure Unity recognizes it as editor-only code):

using UnityEditor;
using UnityEngine;

// Replace YourTargetBehaviour with the name of your MonoBehaviour script
[CustomEditor(typeof(YourTargetBehaviour))]
public class PersistentHandleEditor : Editor
{
    private YourTargetBehaviour _target;
    private int _handleControlId;

    private void OnEnable()
    {
        _target = (YourTargetBehaviour)target;
        // Generate a unique control ID for our Handle to track interactions
        _handleControlId = GUIUtility.GetControlID(FocusType.Passive);
    }

    public override void OnSceneGUI()
    {
        base.OnSceneGUI();

        // Set Handle color based on selection/hover state
        Handles.color = GetHandleDisplayColor();

        // Draw your desired Handle (example: a sphere at the object's position)
        Vector3 handlePos = _target.transform.position;
        Handles.SphereHandleCap(
            _handleControlId,
            handlePos,
            Quaternion.identity,
            0.5f, // Adjust size as needed
            EventType.Repaint
        );

        // Handle mouse interaction logic
        ProcessHandleInteractions();
    }

    private Color GetHandleDisplayColor()
    {
        // Check if the GameObject is selected OR the mouse is hovering over the Handle
        bool isObjectSelected = Selection.activeGameObject == _target.gameObject;
        bool isHandleHovered = HandleUtility.nearestControl == _handleControlId;

        return (isObjectSelected || isHandleHovered) ? Color.yellow : Color.gray;
    }

    private void ProcessHandleInteractions()
    {
        Event currentEvent = Event.current;

        // If the mouse is over our Handle
        if (HandleUtility.nearestControl == _handleControlId)
        {
            // Make this Handle the default control to capture mouse input
            HandleUtility.AddDefaultControl(_handleControlId);

            // Handle left-click to select the GameObject
            if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0)
            {
                Selection.activeGameObject = _target.gameObject;
                currentEvent.Use(); // Consume the event to prevent unintended actions
            }
        }
    }
}

Key Details Explained

  • Always Visible Handles: We draw the Handle directly in OnSceneGUI, which runs every frame regardless of whether the GameObject is selected. No conditional checks for selection state here—we just render it every time.
  • Highlight Logic: The GetHandleDisplayColor method checks two states: if the parent GameObject is selected, or if the mouse is hovering over the Handle (via HandleUtility.nearestControl). We switch to a bright yellow for these states, gray otherwise.
  • Hover-to-Select: In ProcessHandleInteractions, we listen for left-click events when the mouse is over the Handle. When detected, we set the parent GameObject as the active selection and consume the event to avoid selecting other objects in the scene.

Customization Tips

  • Change Handle Shape: Replace Handles.SphereHandleCap with other built-in Handles like Handles.CubeHandleCap, Handles.ArrowHandleCap, or even custom mesh/line drawing with Handles.DrawMesh or Handles.DrawLine.
  • Adjust Sizes/Colors: Tweak the size parameter in SphereHandleCap or modify the color values in GetHandleDisplayColor to match your project's style.
  • Multiple Handles: If you need multiple Handles per object, generate a unique control ID for each one (use GUIUtility.GetControlID for each Handle) to avoid interaction conflicts.

内容的提问来源于stack exchange,提问作者Bane

火山引擎 最新活动