IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity3D Editor ControlID 简单介绍 -> 正文阅读

[游戏开发]Unity3D Editor ControlID 简单介绍

环境:Unity2021.1.14 Odin3.0.4 语言:C#

面向:Editor开发人员

总起

当我在工具代码中看到这行代码时:

GUIUtility.hotControl = id;

我产生了一个疑问,ControlID是什么?

第19章 GUI を自作する - エディター拡張入門中的介绍也只是寥寥几笔:

为每个GUI分配一个ControlID,此ID使每个GUI独立,如果没有正确分配这个ID,你最终会遇到多个GUI操作的冲突。比如当鼠标拖动GUI.Window时,范围选择工具起作用了。

生成/获取ControlID:

int id = GUIUtility.GetControlID(FocusType.Passive, rect);

通过ControlID控制样式:

EditorStyles.objectFieldThumb.Draw(rect, content, id);

而使用GUIUtility.hotControl可以找出当前处于焦点的ControlID,或者使用GUIUtility.keyboardControl你可以知道键盘的焦点。

一个例子

在Odin的使用中我发现了以下的bug(或者说设计如此):

?

我设计了这么个界面,Data中显示Datas的其中一个数据,然后选择显示哪个数据,由ChooseIndex决定。

代码如下:

using System;
using Sirenix.OdinInspector;
using UnityEngine;

public class TestControlID : MonoBehaviour
{
    [Serializable]
    public class Data
    {
        [ShowIf("@this.mode == Mode.Show")]
        public int testInt;

        public Mode mode = Mode.Show;
    }

    public enum Mode
    {
        Show,
        DontShow,
    }

    [OnValueChanged("Choose")]
    public int chooseIndex;

    public void Choose()
    {
        if (chooseIndex >= 0 && chooseIndex < datas.Length)
        {
            data = datas[chooseIndex];
        }
    }

    public Data data;

    public Data[] datas;
}

先把数据全选成NotShow,之后选择第一个Data将 Mode选择Show,再切到第二个,这时会神奇的发现第二个Data也“粘连”修改成了Show。

这个问题最终原因就是出在ControlID上:

  1. Odin使用的enum popup有两段操作,鼠标按下和抬起都会使值触发变化;
  2. 鼠标按下已经使值从DontShow改成了Show,造成了TestInt被隐藏,这导致了当前Mode框的ControlID发生了变化;
  3. 鼠标抬起也会触发值的变化,但此时的ControlID已经发生了变化,所以OdinSelector<T>.confirmedPopupControlId虽然被记录下来,但并没有触发;
  4. 等到我们改换显示第二个数据,因为计算出来ControlID是一致的,所以第二段此时才进行触发;

产生“粘连”修改问题,也很好解决:

  1. 禁用这种二段触发的popup,可以使用Unity原生popup;
  2. ControlID在计算的时候可以率先分配一个不共用的id段;
  3. 会被隐藏的属性都放到mode下面,这样ControlID不会发生变化。

这个例子直接放到InspectorWindow上进行切换是不会有问题的,Unity的处理方式实际就是第2种。

不过落到具体的方式上Unity2021和Unity2017还有所不同,2021采用了切换时会一直增长的方式,而2017则会为每个GameObject分配单独的ControlID。

总结

ControlID的具体算法因为是写在C++层的,我还是不是很了解,有大佬知道的话可以指引一下。

大体的作用实际就是标明每个控件的唯一ID,但是这种做法也会有局限,就是缓存下来的这个ID可能会随时变换,这是一个不稳定的ID。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-11-09 19:56:40  更:2021-11-09 19:58:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 0:56:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码