早期做敌人时,血量、移速、攻击间隔都直接写在 MonoBehaviour 的字段里。同一种怪有十二个预制体变体,改一个移速要改十二次。后来改成配置资源:Prefab 只引用一份数据,场景里十个实例共享同一份静态数值。
[CreateAssetMenu(menuName = "Game/Enemy Stats")]
public class EnemyStats : ScriptableObject
{
public string displayName;
public float maxHealth = 100f;
public float moveSpeed = 3f;
public float attackCooldown = 1.2f;
}
脚本里不要复制这些值到一堆散落字段,运行时当前血量可以留在实例上,上限和冷却仍读配置:
public class Enemy : MonoBehaviour
{
[SerializeField] EnemyStats stats;
float _hp;
void OnEnable()
{
_hp = stats.maxHealth;
}
}
两件容易混的事
- 编辑器里改 ScriptableObject,会写回资源文件;真机构建里改它,通常不会持久化,而且所有引用者都会看到这次修改。
- 不要把场景里的具体物体引用存进 SO。场景一换,引用就失效,还可能把场景对象拖进资源依赖里。
备忘:SO 适合静态配置和事件通道,不适合当玩家存档。存档仍用 JSON、二进制或官方提供的持久化方式。