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,技能树,对话系统,行为树与状态机等,这里不再赘述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值