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

时间:2023-03-08 17:10:45

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

using UnityEngine;
using System.Collections; public class DemoTest : MonoBehaviour { private int _score;
public int Score
{
get { return _score; }
set
{ if (value > )
{
value = ;
}
_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 > )
{
value = ;
}
_score = value;
}
}
}

此时可以在Inpector面板中看到:Unity3d  Inspector面板实现set/get访问器

之所以会显示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 > )
{
value = ;
}
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