Unity下通过代码修改prefab的参数
问题
做Unity开发时,经常需要写一些Editor代码,用来提高开发的效率,常见的一种情况就是通过代码修改场景里Prefab的参数。一般修改后会发现一切如期望般正常,但一旦你重启Unity,或者重新加载Scene,那么就会惊喜地发现,之前做出的修改都没有生效。
由于我习惯使用新版的Unity,所以下面都是基于Unity 2019版本,其他版本是否会有这个问题,能不能用这种方式解决,就各自尝试了。
原因
假设我们有一个简单的脚本,如下
using UnityEngine; public class Test : MonoBehaviour { public int Value; }
我们把它挂接在一个空的GameObject下,做成一个Prefab,如下:
如果我们直接在Editor下修改Value的值,如下图,可以看到Value左边有一条蓝色的长条,同时Value和3都变成了粗体。(细心的读者还会注意到,Unity的标题栏最后会多了个表示Scene修改的*)
这是因为我们不是直接修改Prefab,而是在Prefab上做了一个Override。关于Override,可以理解为是一个盒子,盒子里面是它对应的Prefab,而我们的修改是修改了Override,而没有直接修改到Prfab,所以不会影响其他同一个Prefab的值。当Unity要获取Prefab的参数时,会优先找这个参数有没有被Override,有的话就用Override的值,没有则用Prefab的值。
注意就算我们把Value的值改为0,Override还是生效了,可以通过Ctrl+z撤销之前的操作,可以看到Override消失了。
我们写一个简单的Editor代码来实验下通过代码直接修改Value的值,如下:
[CustomEditor(typeof(Test))] public class TestEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); var test = target as Test; if (GUILayout.Button("Change")) { test.Value = UnityEngine.Random.Range(1, 100); }}}
这时候如果你点击Change按钮,会发现Value的值确实修改了,但没有了表示Overide的蓝条,文字没有变成粗体(标题栏的*号也没了),而且你按Ctrl+z是无法撤销这次修改的。更糟糕的是,你重启Unity后会发现值并没有生效。
这是因为Unity并不知道我们做出了修改,所以没有帮我们保存这次修改。
解决
解决方法有几种,但最推荐的是采用Undo,如下:
[CustomEditor(typeof(Test))] public class TestEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); var test = target as Test; if (GUILayout.Button("Change")) { Undo.RecordObject(test, "modify test value"); test.Value = UnityEngine.Random.Range(1, 100); EditorUtility.SetDirty(test); }}}
再次点击Change按钮,会发现和直接在Editor修改的结果是一致的。Ctrl+z也能生效。那么Undo.RecordObject的第二个参数是干嘛的?你打开菜单栏的Edit菜单会有惊喜。
友情提示,如果是一次修改大量的Prefab,可以采用Undo.RecordObjects。
友情提示2,Undo.RecordObject有时会失效,这个函数好像不太可靠,更可靠的方法是在最后加上EditorUtility.SetDirty()。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!