Unity自定义编辑器中MonoBehaviour子类构造后返回null问题求助
问题根本原因
你违反了Unity引擎的核心开发规则:所有继承自MonoBehaviour的类,禁止使用new关键字手动调用构造函数实例化。
Unity对MonoBehaviour有独立的生命周期管理逻辑,直接new出来的实例没有绑定到GameObject,也没有被Unity引擎的对象系统注册,所以虽然构造函数的代码会正常执行(你能看到内部的Debug输出),但Unity的自定义空值判断逻辑会将这个非法实例判定为null,打印输出自然为null,调用方法也会抛出空引用异常。
正确的实现步骤
你需要先创建承载组件的GameObject,再挂载ComponentSlot组件,最后手动赋值参数替代原有构造函数逻辑:
- 删除
ComponentSlot类中自定义的带参构造函数,MonoBehaviour使用自定义带参构造函数会导致序列化逻辑异常。 - 将Editor代码中创建实例的逻辑替换为如下代码:
[CustomEditor(typeof(ComponentMasterBase), true)] public class ComponentMasterEditor : Editor { public override void OnInspectorGUI() { ComponentMasterBase cmb = (ComponentMasterBase)target; // 无关逻辑保留 if(GUILayout.Button("Add " + cmb.GetComponentType().DisplayName + " Slot")) { // 先创建承载ComponentSlot的GameObject GameObject slotObj = new GameObject("Component Slot"); // 挂载组件获取合法实例 ComponentSlot c = slotObj.AddComponent<ComponentSlot>(); // 手动赋值参数替代原有构造函数逻辑 c.Size = 1; c.SetComponent(null); c.ComponentType = cmb.GetComponentType(); c.Owner = cmb; // 此时c为合法非空实例 Debug.Log(c); cmb.AttachComponentSlot(c); // 可选补充:如果需要支持编辑器撤销、修改能保存到场景,加入以下代码 Undo.RegisterCreatedObjectUndo(slotObj, "Add Component Slot"); EditorUtility.SetDirty(slotObj); EditorUtility.SetDirty(cmb); } } }
小提示:如果
ComponentSlot需要通用的初始化逻辑,可以将原来构造函数内的逻辑封装为独立的Init公共方法,避免多处赋值重复代码。
内容的提问来源于stack exchange,提问作者user10619713
相关产品推荐
相关产品推荐

