-
写法1:只读属性(仅get,基于私有字段)—— 外部只能读,内部可赋值
-
写法2:自动实现属性(get;set;)—— 编译器自动生成私有字段,外部可读写
-
写法3:自定义set属性(get; set=>value;)—— 语法冗余(等价于自动实现),正确自定义set需加逻辑
-
核心原则1:非自身脚本调用(跨脚本访问),优先用属性,禁止直接暴露公有字段
-
核心原则2:仅类内部使用,用私有字段;需要控制访问权限/加逻辑/跨脚本访问,用属性
场景 1
“我只给自己用”——纯 private 字段,够用
public class Player : MonoBehaviour
{
private int _hp = 100; // 1. 纯内部状态,外部谁也不给碰
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
_hp -= 10; // 2. 自己脚本里随便改
Debug.Log($"内部扣血,当前 _hp = {_hp}");
}
}
}
-
外部脚本 完全看不见 _hp;
场景 2
“现在只读,但保不齐以后想加断点/日志”——顺手写个只读属性
public class Player : MonoBehaviour
{
private int _hp = 100;
// 只读属性:今天只是透传,明天就能加料
public int Hp => _hp; // 表达式体,零成本
}
// 外部脚本(比如 UIController)
public class UIController : MonoBehaviour
{
private void Update()
{
Player p = GameObject.FindWithTag("Player").GetComponent<Player>();
Debug.Log("UI 读到血量:" + p.Hp); // ✅ 只能看,不能改
}
}
明天策划说「每次读血量都写日志」,你只需改一处:
public int Hp
{
get
{
Debug.Log($"血量被读取,当前={_hp}");
return _hp;
}
}
场景 3
“外部想改,但我要拦 null”——private 字段 + public 带校验属性
public class Spawner : MonoBehaviour
{
[SerializeField] private GameObject _enemyPrefab; // ① 拖
public GameObject EnemyPrefab // ② 对外读写通道
{
get => _enemyPrefab;
set
{
if (value == null) // ③ 拦空
{
Debug.LogWarning("禁止设空,已忽略");
return;
}
_enemyPrefab = value;
Debug.Log($"模板已更换为:{value.name}");
}
}
}
Spawner spawner = GetComponent<Spawner>();
spawner.EnemyPrefab = bossPrefab; // ✅ 走 set,会被校验
spawner.EnemyPrefab = null; // ❌ 被拦截 + 打印警告

纯内部状态 → private int _foo; 完全够用。
只要跨出脚本门 → 第一时间包属性,哪怕今天只是 => _foo;。
属性写第一天 = 给未来的自己留一把万能钥匙,成本 = 一对大括号。
网硕互联帮助中心


评论前必须登录!
注册