Skip to content

Latest commit

 

History

History
454 lines (362 loc) · 12.9 KB

File metadata and controls

454 lines (362 loc) · 12.9 KB

快捷指令

一个强大的Unity编辑器扩展,提供圆形按钮界面来快速访问自定义操作。使用Ctrl+Q热键在鼠标位置显示径向菜单。

基础预览

English Documentation

功能特性

  • 圆形界面: 以鼠标位置为中心的直观径向按钮布局
  • 热键激活: 按Ctrl+Q立即打开操作菜单
  • 分层组织: 将操作组织到类别和子类别中
  • 动态分页: 自动处理大量操作的分页显示
  • 条件操作: 根据当前上下文启用/禁用操作
  • 状态管理: 可视化状态指示器(选中/未选中,可见/隐藏)
  • 优先级系统: 通过优先级值控制操作显示顺序
  • 简易集成: 基于特性的简单操作注册
  • 动态指令: 在运行时以编程方式注册指令,实现上下文感知功能

快速开始

1. 导入包

您可以通过以下方法之一将Quick Action包导入到Unity项目中:

方法1:VRChat Creator Companion (VCC)

对于VRChat开发者:通过VPM Listing添加到VCC

方法2:Git URL(推荐)

  1. 打开Unity,转到 Window > Package Manager
  2. 点击左上角的 + 按钮
  3. 选择 Add package from git URL...
  4. 输入以下URL:
    https://github.com/Yueby/QuickAction.git
    
  5. 点击 Add 并等待包导入完成

方法3:手动下载

  1. GitHub仓库下载包
  2. 将文件解压到项目的 Packages 文件夹中
  3. Unity会自动检测并导入包

2. 创建您的第一个操作

创建一个新脚本并添加简单操作:

using UnityEngine;
using UnityEditor;
using Yueby.QuickActions; // 不要忘记导入命名空间

public class MyActions
{
    [QuickAction("Tools/Hello World", "显示问候消息")]
    public static void HelloWorld()
    {
        Debug.Log("来自Quick Action的问候!");
    }
    
    [QuickAction("Tools/Create Cube", "在场景中创建立方体", Priority = -100)]
    public static void CreateCube()
    {
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.name = "Quick Action立方体";
        Selection.activeGameObject = cube;
    }
}

3. 使用系统

基本操作

  1. 打开菜单: 在Unity编辑器中按Ctrl+Q
  2. 选择操作: 鼠标移动到对应角度会自动选择选项
  3. 执行操作:
    • 松开Ctrl+Q键自动执行选中的操作
    • 或者鼠标左键点击执行操作
  4. 取消操作: 鼠标右键点击关闭窗口不执行任何操作

操作流程

  • 按住Ctrl+Q打开菜单
  • 鼠标移动到不同角度选择不同选项
  • 松开按键或左键点击执行
  • 右键点击取消操作

操作配置

QuickAction特性

QuickActionAttribute用于标记方法为快速操作:

[QuickAction(path, description, Priority = priority, ValidateFunction = nameof(ValidationMethod))]

参数:

  • path(必需):使用正斜杠的操作路径(例如:"Tools/My Action")
  • description(可选):操作描述,用于工具提示
  • Priority(可选):显示优先级(数字越小越靠前)
  • ValidateFunction(可选):用于条件启用的方法名

方法要求

操作方法必须是:

  • static
  • publicprivate
  • 返回void
  • 无参数

验证函数

验证函数必须是:

  • static
  • publicprivate
  • 返回bool
  • 无参数

验证函数还可以使用以下方法控制操作的可见性和选中状态:

  • QuickAction.SetVisible(path, bool): 显示/隐藏操作
  • QuickAction.SetChecked(path, bool): 设置选中状态(显示勾选标记)
  • QuickAction.GetVisible(path): 获取可见性状态
  • QuickAction.GetChecked(path): 获取选中状态

动态指令

动态指令允许您在运行时以编程方式注册指令,非常适合上下文感知功能:

// 注册动态指令
QuickAction.RegisterDynamicAction(
    "Selection/Component/Copy", 
    () => CopyComponent(), 
    "复制选中的组件", 
    -100
);

动态指令特性:

  • 运行时注册: 在面板打开时添加指令
  • 自动清理: 面板关闭时自动移除指令
  • 上下文感知: 非常适合依赖于当前选择的指令

使用方式:

// 注册事件(在类初始化时)
[InitializeOnLoadMethod]
private static void RegisterDynamicActions()
{
    QuickAction.OnBeforeOpen += OnQuickActionOpen;
}

// 在事件中注册动态指令
private static void OnQuickActionOpen()
{
    QuickAction.RegisterDynamicAction(
        "路径/指令名称", 
        () => { /* 指令逻辑 */ }, 
        "指令描述", 
        优先级
    );
}

// 带验证的动态指令
QuickAction.RegisterDynamicAction(
    "路径/指令名称", 
    () => { /* 指令逻辑 */ }, 
    "指令描述", 
    优先级,
    () => { /* 验证逻辑,返回bool */ }
);

示例

基础操作

using UnityEngine;
using UnityEditor;
using Yueby.QuickActions;

public class BasicActions
{
    [QuickAction("Debug/Hello World", "显示问候消息")]
    public static void HelloWorld()
    {
        Debug.Log("Hello from Quick Action!");
    }
    
    [QuickAction("GameObject/Create Cube", "在场景中创建立方体")]
    public static void CreateCube()
    {
        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.name = "Quick Action Cube";
        Selection.activeGameObject = cube;
    }
}

条件操作

using UnityEngine;
using UnityEditor;
using Yueby.QuickActions;

public class ConditionalActions
{
    [QuickAction("Selection/Delete Selected", "删除选中的GameObject", ValidateFunction = "HasSelection")]
    public static void DeleteSelected()
    {
        if (Selection.gameObjects.Length > 0)
        {
            foreach (var go in Selection.gameObjects)
            {
                Undo.DestroyObjectImmediate(go);
            }
        }
    }
    
    private static bool HasSelection()
    {
        bool hasSelection = Selection.gameObjects.Length > 0;
        // 只有在选中对象时才显示此操作
        QuickAction.SetVisible("Selection/Delete Selected", hasSelection);
        return hasSelection;
    }
    
    [QuickAction("Play Mode/Stop Play", "停止播放模式", ValidateFunction = "IsPlaying")]
    public static void StopPlay()
    {
        EditorApplication.isPlaying = false;
    }
    
    private static bool IsPlaying()
    {
        return EditorApplication.isPlaying;
    }
}

状态管理操作

状态管理演示

using UnityEngine;
using UnityEditor;
using Yueby.QuickActions;

public class StateActions
{
    private static bool _featureEnabled = false;
    
    [QuickAction("Settings/Toggle Feature", "启用/禁用功能", ValidateFunction = "ValidateFeature")]
    public static void ToggleFeature()
    {
        _featureEnabled = !_featureEnabled;
        Debug.Log($"功能{(_featureEnabled ? "已启用" : "已禁用")}");
    }
    
    private static bool ValidateFeature()
    {
        // 功能启用时显示勾选标记
        QuickAction.SetChecked("Settings/Toggle Feature", _featureEnabled);
        return true;
    }
    
    [QuickAction("Tools/Debug Mode", "切换调试模式", ValidateFunction = "ValidateDebugMode")]
    public static void ToggleDebugMode()
    {
        Debug.unityLogger.logEnabled = !Debug.unityLogger.logEnabled;
    }
    
    private static bool ValidateDebugMode()
    {
        // 显示当前调试模式状态
        QuickAction.SetChecked("Tools/Debug Mode", Debug.unityLogger.logEnabled);
        return true;
    }
}

分层组织

分类演示

using UnityEngine;
using UnityEditor;
using Yueby.QuickActions;

public class HierarchicalActions
{
    [QuickAction("Tools/Utilities/Screenshot", "截取屏幕截图")]
    public static void TakeScreenshot()
    {
        ScreenCapture.CaptureScreenshot("screenshot.png");
        Debug.Log("截图已保存为screenshot.png");
    }
    
    [QuickAction("Tools/Utilities/Open Persistent Data", "打开持久数据路径")]
    public static void OpenPersistentData()
    {
        EditorUtility.RevealInFinder(Application.persistentDataPath);
    }
    
    [QuickAction("Tools/Scene/Save Scene", "保存当前场景")]
    public static void SaveScene()
    {
        EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
    }
}

动态组件指令

动态指令非常适合上下文感知指令,如组件管理:

using UnityEngine;
using UnityEditor;
using Yueby.QuickActions;

public class ComponentActions
{
    [InitializeOnLoadMethod]
    private static void RegisterDynamicActions()
    {
        QuickAction.OnBeforeOpen += OnQuickActionOpen;
    }

    private static void OnQuickActionOpen()
    {
        if (Selection.activeGameObject != null)
        {
            var components = Selection.activeGameObject.GetComponents<Component>();
            
            foreach (var component in components)
            {
                if (component == null) continue;
                
                var componentName = component.GetType().Name;
                var componentKey = $"{componentName}_{component.GetInstanceID()}";
                
                // 为每个组件注册复制和移除操作
                QuickAction.RegisterDynamicAction(
                    $"Selection/Component/{componentName}/Copy",
                    () => CopyComponent(componentKey),
                    $"复制{componentName}组件",
                    -850
                );
                
                QuickAction.RegisterDynamicAction(
                    $"Selection/Component/{componentName}/Remove",
                    () => RemoveComponent(componentKey),
                    $"移除{componentName}组件",
                    -849
                );
            }
        }
    }

    private static void CopyComponent(string componentKey)
    {
        // 复制组件的实现
        Debug.Log($"已复制组件: {componentKey}");
    }

    private static void RemoveComponent(string componentKey)
    {
        // 移除组件的实现
        Debug.Log($"已移除组件: {componentKey}");
    }
}

主要优势:

  • 自动上下文检测: 根据当前选择创建指令
  • 临时指令: 面板关闭时自动清理指令
  • 可扩展: 适用于任意数量的组件或对象
  • 性能优化: 仅在需要时创建指令

SceneView集成

SceneView功能演示

Quick Action提供了专门的SceneView集成功能,包括:

  • 视图切换: 快速切换到前/后/左/右/顶/底视图
  • 正交/透视模式: 切换SceneView的投影模式
  • 上下文感知: 只有在SceneView窗口活跃时才显示相关操作

界面使用

导航

  • 中心圆圈: 将鼠标移离中心以激活选择
  • 操作按钮: 悬停选择,释放热键或点击执行
  • 返回按钮(↑): 返回上一级类别或第一页
  • 下一页按钮(←): 当有更多页面时导航到下一页

返回和下一页演示

分页

  • 每页最多8个按钮
  • 对具有大量操作的类别自动分页
  • 动态按钮分配(返回按钮、操作、下一页按钮)

可视化状态指示器

  • 选中状态: 显示彩色左边框表示"开启"状态
  • 未选中状态: 显示灰色左边框并降低透明度表示"关闭"状态
  • 无状态: 没有状态管理的操作不显示边框指示器
  • 隐藏操作: 操作可以根据上下文动态隐藏

背景显示

  • 圆形界面会捕获其后面的背景内容,创造无缝的视觉效果
  • 背景不是透明的,而是使用界面位置处编辑器内容的截图
  • 这创造了透明的错觉,同时保持适当的UI渲染

最佳实践

操作组织

  • 使用描述性路径:"Tools/Build/Build Player"而不是"Build"
  • 分组相关操作:"GameObject/Primitives/Create Cube"
  • 保持操作名称简洁但清晰

性能

  • 避免在验证函数中进行重操作
  • 使用验证函数防止错误
  • 考虑为可逆操作使用Undo操作

错误处理

  • 在处理前验证输入
  • 提供有意义的错误消息
  • 对风险操作使用try-catch块

API参考

QuickActionAttribute

[QuickAction(string path, string description = null)]

属性

  • Path: 操作路径(必需)
  • Description: 操作描述(可选)
  • Priority: 显示优先级(可选,默认:0)
  • ValidateFunction: 验证方法名(可选)

开发说明: 本项目使用 Cursor 辅助开发。