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 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity 自定义 Inspector 面板时检测属性被修改 -> 正文阅读

[游戏开发]Unity 自定义 Inspector 面板时检测属性被修改

方法

public override void OnInspectorGUI()
{
    // (前文)
    
    EditorGUI.BeginChangeCheck()// ... 待监控代码块(如绘制各种属性框) ...
    
    if (EditorGUI.EndChangeCheck()) // 代码块内绘制的属性框被修改
    {
        // ... 立即应用修改,或标记场景已脏
    }
    
	// (后文)
}

效果

  1. 对用户手动在 Inspector 上造成的改变,发生响应;
  2. 若其他脚本修改了该脚本的变量,使其在 Inspector 上造成改变,则不发生响应。

至于为何会产生该效果,我手动实现了一下,参考下列等效代码。

等效示例

protected SerializedProperty count; // 背景:在 Runtime 脚本中有 int 型字段 _count 

protected virtual void OnEnable()
{
    count = serializedObject.FindProperty("_count");
}

public override void OnInspectorGUI() // 要理解 Inspector 也是逐帧绘制的
{
    // (前文)
    
    // SerializedProperty 在当前帧的值
    // 若用户手动造成了改变,其实此时还没有进行(下一句才进行),SerializedProperty 内部还是原值;
    // 若是外部脚本造成的改变,则在之前(serializedObject.Update() 时)就完成了,此时 SerializedProperty 内部已经是新值
    int countValue = count.intValue; 
    
    // 将 SerializedProperty 绘制成供用户观察和修改的属性框
    // 用户手动造成的修改,实际上是在此时完成的;SerializedProperty 被更新为新值
    EditorGUILayout.PropertyField(count, new GUIContent("Count", ""));
    
    // 对比 SerializedProperty 当前值和属性框绘制前的值
    // 若不同,则一定是因为用户造成了修改(而不是外部脚本造成的修改)
    if (countValue != count.intValue)
    {
        // 采取相应方法提前应用修改
        // 因为此时 SerializedProperty 的新值还没有反序列化到 _count 字段中,直到 serializedObject.ApplyModifiedProperties()
        // 执行前 _count 都还是原值;若这个期间内 Runtime 脚本(继承 MonoBehavior 的脚本)内使用了 _count 则都是基于原值的,
        // 可能造成错误,因此存在提前应用修改的必要
        // ...
    }
    
    // (后文)
}

提前应用修改

假设上例中的 count 属性在 Runtime 脚本(即继承了 MonoBehavior 而非 Editor 的脚本)中是这样定义的:

public int count
{
    get => _count;
    set => _count = Mathf.Max(0, value); // Setter 可被用于提前更新用户修改
}
[SerializeField]
protected int _count = 0;

则可以利用其 Setter 提前应用修改,如下:

public override void OnInspectorGUI()
{
    // (前文)
    
    EditorGUI.BeginChangeCheck();
    EditorGUILayout.PropertyField(count, new GUIContent("Count", ""));
    if (EditorGUI.EndChangeCheck())
    {
        // SerializedProperty 的值此时是新的,利用 Runtime 脚本 count 属性的
        // Setter 将其存入字段 _count 实现提前更新,而不必等待最后的反序列化
        ((ExampleScript)target).count = count.intValue;
    }
    
	// (后文)
}
  游戏开发 最新文章
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-27 10:14:05  更:2021-11-27 10:14:53 
 
开发: 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/27 22:33:43-

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