Unity可视化工具链基础

前言

本文主要讲解unity中的部分可视化调试与编辑器工具,主要是面向想要做工具链的程序,较为基础,后续如果想要进阶,可以自行学习Unity的UIToolkit与GraphView

基础

Gizmos

Gizmos是在Scene界面用于辅助画图的工具,一般情况下,我们可以用它绘制范围(比如攻击范围,敌人仇恨范围等);

它的使用也很简单,在Mono脚本中有两个方法:OnDrawGizmos与OnDrawGizmosSelected,前者会始终在Scene界面绘制,而后者只有你选中挂载该脚本的物体时才会绘制,一般的绘制流程如下:

挑选喜欢的颜色->选中对应的图形与范围->结束

请注意,范围是你自己设置的,并不能像UE的轨道检测一样自动绘制范围大小

复制代码
 public class MyGizmos : MonoBehaviour
 {
     public float attackRange = 5f;
     public float viewAngle = 60f;
     public Transform target;

     // 始终显示(选中不选中都画)
     void OnDrawGizmos()
     {
         // 设置颜色
         Gizmos.color = Color.yellow;

         // 画线
         Gizmos.DrawLine(transform.position, transform.position + Vector3.up * 2);

         // 画立方体
         Gizmos.DrawWireCube(transform.position + Vector3.up, Vector3.one);
     }

     // 只在选中时显示
     void OnDrawGizmosSelected()
     {
         // 攻击范围 - 红色球体
         Gizmos.color = new Color(1, 0, 0, 0.3f);
         Gizmos.DrawSphere(transform.position, attackRange);

         Gizmos.color = Color.red;
         Gizmos.DrawWireSphere(transform.position, attackRange);

         // 视野扇形(用线模拟)
         if (target != null)
         {
             Gizmos.color = Color.cyan;
             Gizmos.DrawLine(transform.position, target.position);
         }
     }
 }

Inspector

检查器是我们平时打交道比较多的,当然我们可以利用一些特性将部分字段显示出来

  1. SerializeField :序列化字段,顾名思义就是将字段序列化,使其显示在检查器面板上,注意,私有字段也能序列化,属性不能序列化
  2. Header("") :同样放在字段上,括号中填上你需要的字符串,会在该字段上放加一个大大的标题,一般用它来区分相同组件上不同功能的字段
  3. Tooltip(""):放在字段上,用于在检查器介绍该字段的功能,需要你把鼠标放到对应的字段上
  4. TextArea(4,4):放在string的字段上,两个数字可以自行选择,用于控制输入框的大小,
  5. HideInInspector:将该字段在检查器中隐藏

tip:关于序列化,c#的值类型或者string,Unity中的GameObject,Mono和SO都是可以默认序列化的,但是如果你想序列化自定义的类,应该为它添加上System.Serializable的标签

以下是一个例子,相信看过之后你就能明白这些标签的作用

复制代码
public class Test1 : MonoBehaviour
{
    public int Value1;//public 变量默认会序列化
    protected int Value2;
    private int Value3;

    public int A_mode1;
    public int A_mode2;
    public int B_mode1;//不同模块不会区分
    public int B_mode2;

    public string Tool;
    public string MyName;
}
复制代码
public class Test2 : MonoBehaviour
{
    [HideInInspector]
    public int Value1;//public 变量默认会序列化
    [SerializeField]
    protected int Value2;
    [SerializeField]
    private int Value3;
    [Header("A模块")]
    public int A_mode1;
    public int A_mode2;
    [Header("B模块")]
    public int B_mode1;//不同模块不会区分
    public int B_mode2;
    [Tooltip("这是一个工具")]
    public string Tool;
    [TextArea(5, 5)]
    public string MyName;
}

EditorWindow

我们在Unity中能看到各种各样的窗口,它们都继承自EditorWindow类,我们同样能自己写出这样的窗口。首先需要注意的:脚本放在Assets文件夹的Editor文件夹(没有就新建)中,并引入UnityEditor命名空间

以下是一个例子,我们绕着这个例子处理

复制代码
public class NativeWindow :EditorWindow
{
	//这是核心打开方式,你可以在编辑器的对应目录下打开对应的窗口了
    [MenuItem("Tools/EditorWindows/原生窗口")]
    static void Open() => GetWindow<NativeWindow>("原生").Show();

    string playerName = "Player";//窗口字段,可通过输入框修改其值
    int level = 1;
    float hp = 100f;
    bool isActive = true;
    GameObject test;

    void OnGUI()
    {
        // 1. Label - 纯文本显示
        GUILayout.Label("=== 基础信息 ===", EditorStyles.boldLabel);
        GUILayout.Label("这是一个普通文本标签");

        // 2. 输入框
        playerName = EditorGUILayout.TextField("玩家名称", playerName);
        level = EditorGUILayout.IntField("等级", level);
        hp = EditorGUILayout.FloatField("血量", hp);
		test = (GameObject)EditorGUILayout.ObjectField("测试对象", test, typeof(GameObject), true);
        // 3. Slider - 滑条
        hp = EditorGUILayout.Slider("血量滑条", hp, 0f, 200f);

        GUILayout.Space(20);  // 留空

        // 4. 水平布局
        GUILayout.Label("操作按钮:", EditorStyles.boldLabel);
        GUILayout.BeginHorizontal();//有开始就要有结束

        if (GUILayout.Button("打印你好", GUILayout.Height(30)))
        {
        		Debug.Log("你好");
        }

        if (GUILayout.Button("打印你坏", GUILayout.Height(30)))
        {
        		Debug.Log("你坏");
        }

        GUILayout.EndHorizontal();

        // 5. 垂直布局
        GUILayout.Space(10);
        GUILayout.BeginVertical("box");  // 带边框的垂直组

        GUILayout.Label("高级设置:");

        GUILayout.BeginHorizontal();
        GUILayout.Label("是否激活:", GUILayout.Width(60));
        isActive = EditorGUILayout.Toggle(isActive);//bool变量用toggle框
        GUILayout.EndHorizontal();

        GUILayout.EndVertical();

        GUILayout.Space(10);
    }
}

编辑器窗口使用流程如下:该窗口类有一些成员变量(通常是bool,int,float,string,GameObject)等,在OnGUI函数中画出输入框或者滑条等,设置完这些值再通过 if (GUILayout.Button("按钮名", GUILayout.Height(30)))绘制按钮并判断是否按下来调用方法,需要注意OnGUI()中的各种绘制的方式。

一般情况下,我们可以创建以下的窗口:

  1. 关卡编辑器窗口:一般用于批量在场景中生成或销毁预制体,值得注意的是此时生成需要用PrefabUtility.InstantiatePrefab()之后再Undo.RegisterCreatedObjectUndo(go, "名称");销毁时用Undo.DestroyObjectImmediate();因为此时不是运行时
  2. 修改Asset中的资产,这里需要了解AssetDatabase和GUID,不再赘述
  3. 运行时的编辑器,在游戏运行时动态直接修改玩家的属性,用FindObjectOfType获取对应Mono组件即可,也可以获取场景信息,场景中的敌人数量等

附加内容Odin

Odin插件是一个编辑器扩展插件,里面有一些好用的特性,可以在原有的编辑器基础上扩展,这里简单介绍一下:

常用:

  1. LabelText(""):用于将字段在检查器中显示括号中的名字
  2. BoxGroup(""):用于将字段分组,括号中名字相同的将会在同一组
  3. TableList:将列表中的内容按表格展开
  4. DictionaryDrawerSettings(KeyLabel ="道具Id",ValueLabel ="数量"):放在字典上,可以序列化字典
  5. Button(""):放在方法上,会自动在检查器上创建按钮,按下后即可调用,按钮大小和颜色都可以自定义
  6. ShowInInspector:放在字典上,可以序列化属性
  7. ShowIf("")EnableIf("")HideIf(""):这三个是一套,括号中可以放布尔方法的方法名或布尔字段的字段名,满足条件才会显示或隐藏

上面是它的常用特性,另一种情况,它也可以用来做EditorWindow,可以自行处理繁琐的OnGUI布局,我们只需要填变量和方法就好,下面是一个简单的例子

复制代码
public class MyToolWindow :OdinEditorWindow//注意这里继承自OdinEditorWindow
{
    [MenuItem("Tools/Windows/测试")]
    static void Open()=>GetWindow<MyToolWindow>().Show();

    [BoxGroup("设置")]//上面提到的特性这里也可以用
    public string PlayerName;
    [BoxGroup("设置"), MinMaxSlider(0, 100)]
    public Vector2Int HpRange;

    [Button("生成"),GUIColor(0.2f,0.8f,0.2f)]
    void Generate()
    {
        Debug.Log("生成玩家");
    }
}

结语

由于GraphView过于繁杂,笔者对其不感兴趣,请读者自行学习,它的作用是利用EditorWindow创建出节点编辑器,比如ShaderGraph,技能树,对话系统,行为树与状态机等,这里不再赘述

相关推荐
guslegend2 小时前
第2节:AI编辑器底层技术全景导览
人工智能·编辑器
tealcwu3 小时前
【Unity实战】Unity IAP 4.x 在 Windows Store (UWP) 平台上的实现指南
windows·unity·游戏引擎
玉夏3 小时前
【Shader基础】CG/HLSL 基础语法
unity·shader
垂葛酒肝汤6 小时前
Unity的UGUI的坐标
unity
winlife_6 小时前
让 AI 写敌人状态机,并用脚本化场景验证状态转换正确:funplay-unity-mcp 实战
人工智能·unity·游戏引擎·ai编程·状态机·mcp
tealcwu6 小时前
【Unity实战】Unity IAP 5.3 中实现 Windows Custom Store 实战教程
windows·unity·游戏引擎
unityのkiven7 小时前
工作分享1(26.5.27):基于栈实现全局返回逻辑通用架构设计(适配异步 + 确认弹窗)
游戏·unity·c#·客户端架构
OliverH-yishuihan7 小时前
【保姆级教程】Win11 下从零部署 Claude Code:本地环境配置 + VSCode 可视化界面全流程指南
ide·vscode·编辑器
zhiSiBuYu05177 小时前
Godot 游戏引擎新手从零开发指南
游戏引擎·godot
TakeForge7 小时前
17天跑通交通行业SVG编辑器
编辑器