简单说一下属性和字段的区别:字段就是成员变量,而属性确实提供给外部访问内部成员变量的接口。之所以会有属性的出现,就是为了避免外部对类的成员的直接访问,通俗的说就是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