Unity3d Inspector面板实现set/get访问器

     简单说一下属性和字段的区别:字段就是成员变量,而属性确实提供给外部访问内部成员变量的接口。之所以会有属性的出现,就是为了避免外部对类的成员的直接访问,通俗的说就是OOP中的封装思想。

using UnityEngine;
using System.Collections;

public class DemoTest : MonoBehaviour {

    private int _score;
    public int Score
    {
        get { return _score; }
        set
        {

            if (value > 100)
            {
                value = 100;
            }
            _score = value;
        }
    }
}

     上面的示例中_score就是字段或者叫成员变量,,而Score其实是C#语法简化的方法,提供了私有成员_score对外部的访问接口,当我们通过Score更改_score的值时就会触发set{…}代码段的代码执行,这样就完成了对_score的范围限制,这里就体现了OOP中的封装的好处啦。。。。关于属性和字段的介绍就到此为止,下面说一下这篇文章的主题。

     在Unity中可以把字段使用[SerializeField]的方式序列化到Inspector面板(至于什么是序列化,读者可以自行百度),当然public 访问权限的字段是隐式添加[SerializeField],所以可以直接被序列化的,private的字段也可以手动添加[SerializeField]来实现序列化的比如上述的例子中我简单在_score上添加[SerializeField],就可以在Inspector面板上直接对_score赋值了

using UnityEngine;
using System.Collections;

public class DemoTest : MonoBehaviour {

    [SerializeField]
    private int _score;
    public int Score
    {
        get { return _score; }
        set
        {

            if (value > 100)
            {
                value = 100;
            }
            _score = value;
        }
    }
}

此时可以在Inpector面板中看到:

之所以会显示Score,而不是_score,这是unity3d在显示的时候做的一些处理,不必关注。然而此时我们如果直接修改Score的值到120,那么我们其实直接修改的_score的值,而不是通过属性Score来访问的,所以我们限定的_score<=100,就不在起作用了,那么如果在工程中有这种需求该怎么处理呢?有两种方案可供选择,先说第一种写Editor的方式实现:

using UnityEngine;
using System.Collections;

public class DemoTest : MonoBehaviour {

   // [SerializeField]
    private int _score;

    public int Score
    {
        get { return _score; }
        set
        {

            if (value > 100)
            {
                value = 100;
            }
            print("set _score value = " + value);
            _score = value;
        }
    }
}

自定义的Editor类源码(当然该类必须放在Editor目录下:

using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(DemoTest))]    //为DemoTest添加一个自定义标签
public class EditorTest : Editor {

    public override void OnInspectorGUI()   //当DemoTest在Inspector面板上显示改动时触发
    {
        DemoTest demoTest = target as DemoTest; //target是Eiditor内部封装的当前操作的对象引用
        int score = EditorGUILayout.IntField("Score", demoTest.Score);//在Inspector面板上序列化一个对象,并关联demoTest.Score属性
        if (demoTest.Score != score)//如果该属性在改动后没有触发就手动触发
        {
            demoTest.Score = score;
        }
        base.DrawDefaultInspector();//重回Inspector面板
    }
}

这样当我们修改Socre时就可以在Console中看到相应的输出了,也就解决了set、get方法封装性问题。当然这种方式很有局限性,使用起来十分不方便,还有一种简便的方式,使用SetProperty标签,当然我个人由于unity版本过低,SetProperty还不支持,,应该要5.0以后的版本吧,这里附上链接:https://github.com/LMNRY/SetProperty

时间: 2024-10-15 11:49:26

Unity3d Inspector面板实现set/get访问器的相关文章

Unity3D之如何扩展脚本的Inspector面板

关于扩展编辑器 Unity给我们提供了很好的可视化编程环境,但对于我们有些更懒蛋的程序猿来说,还不够方便.所以Unity也给我们提供了很友好的扩展方式. 今天来说一下如何自定义一个脚本的inspector面板. unity中所有编辑器相关的脚本,都放在Editor文件夹,所以建一个先. 假设有个脚本ABC.cs 我们想自定义它的Inspector面板. 现在上代码: // 要自定义的脚本 public class ABC : Monobehaviour{ public bool a; publi

Unity定制,将属性暴露在Inspector面板上

孙广东   2015.7.12 Unity的很多编辑器功能都是通过特性Attribute实现. 那么我们要自己扩展Inspector也是要自己写Attribute. 先说说为什么要这样做? 为了编写面向对象程序,封装特性 更优雅.下面的脚本使 属性 (即有 getter/setter 的成员) 的内容可以在Unity的Inspector上显示.这样就可以保密类的 字段,并限制所有的外部访问,只能通过 属性 访问, 看看代码吧! using System; [AttributeUsage(Attr

讲解如何在Unity的Inspector面板实现类似摄像机层次遮罩的多选效果

首先,我们现在的需求是这样的,我定义了一个脚本,里面有一个枚举,还有一个Public的枚举类型变量,现在我们就可以在Unity的工程里的Inspector面板中通过手动的选择来控制这个枚举变量到底选择什么了,就像我们Unity中的摄像机自带的那种可以选择遮罩层次的感觉,但是现在的问题是,我们只能选择一个,并不能多选,现在我们要解决的就是,给这个枚举变量写一段让它可以多选的代码. 效果图如下: 这里的变量名我改成了自定义的中文,其实在代码中大家可以根据自己的需求更改 和上一篇一样,我先说一下这个工

Js中的数据属性和访问器属性

Js中的数据属性和访问器属性 在javaScript中,对象的属性分为两种类型:数据属性和访问器属性. 一.数据属性 1.数据属性:它包含的是一个数据值的位置,在这可以对数据值进行读写. 2.数据属性包含四个特性,分别是: configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为true enumerable:表示能否通过for-in循环返回属性 writable:表示能否修改属性的值 value:包含该属性的数据值.默

访问器模式

访问器(visitor)模式 意图:主要将数据结构与数据操作分离.主要解决:稳定的数据结构和易变的操作耦合问题. 代码: #include <iostream> #include <list> using namespace std; class ComputerPartVisitor; class ComputerPart { public: virtual ~ComputerPart() {} public: virtual void accept(ComputerPartVi

14.C#属性访问器、命名空间、pragma指令(七章7.3-7.5)

看到一些零星的知识片,今天就用自己的理解说明下,也是因为太简单了,一下就过的,也是我们日常开发中常用.留下一个脚印,当书不在手上的,也能翻出来看看.说下属性访问器.命名空间和pragma指令. 属性访问器在01.C#数据类型.排序.过滤(一章1.1-1.2)有所提到,在C#3后可以使用修饰符去修饰属性的取值和赋值,也可以使用加入一些验证,如下: 1 class Plant 2 { 3 private double Height = 0.0; 4 5 //是否需要修剪 6 public bool

WorldWind源码剖析系列:地形访问器类TerrainAccessor

地形访问器类TerrainAccessor提供了对地形(高程)Terrain (elevation)访问的各种接口interface,是NltTerrainAccessor类的基类.该类类图如下. 基类TerrainAccessor提供的主要处理方法简要描述如下: protected string m_name; //地形模型名称 protected double m_north; //地形北部边界 protected double m_south; //地形南部边界 protected dou

JS之访问器

1.在对象中定义get,set访问器属性 <script> var test = { _name:"pmx", _age:18, _born:1990, get name(){ return "name is "+this._name; }, set name(value){ this._name = value; }, get born(){ return this._born; }, set born(value){ this._born = val

属性类型:数据类型,访问器类型的坑

ECMA5弄了一个新东西, 就是用户可以通过Object.defineProperty配置属性的可写,可配置,可枚举, 让我们开发者可以定义一些属性,这些属性有点像native的赶脚 比如,我们平常定义一个对象这样子就可以了: var obj0 = { name : "nono" }; 我们也可以用新的方式,Object的属性设置方法defineProperty设置属性, 如果用户没有传enumberable, configurable, writable的值, 默认是false, 也