首页 > Unity3D频道 > 【Unity3D研究院之游戏开发】 > Unity3D研究院之预设的使用细节(五十一)
2013
03-26

Unity3D研究院之预设的使用细节(五十一)

今天有个刚入门的朋友问我了几个问题,大概都是有关预设的问题,我想想我还是在博客里面总结一下吧,预设的原理我就不说了它比较简单而且网上例子也很多。

1.预设怎么取消

如下图所示,创建一个普通的立方体对象Cube ,Hierarchy视图中名子的颜色是“白色”的。同样在创建一个Prefabe ,你会发现此时立方体对象在Hierrchy视图中名子的颜色成“蓝色”了。


Unity3D研究院之预设的使用细节(五十一) - 雨松MOMO程序研究院 - 1

接着问题就来了,这个朋友就问怎么才能让Prefab(蓝色名子)的游戏对象还原成Cube(白色名子),这确实是个很细节的问题,他目前的作法是把Cube(预设)删除,从新在创建一个新的Cube对象。这样的作法确实没问题,但是多少让人感觉有点不符合逻辑。如下图所示,正确的作法应该是先选择预设的Cube对象,然后在Unity导航菜单栏中选择GameObject-> Break Prefab Instance 。

Unity3D研究院之预设的使用细节(五十一) - 雨松MOMO程序研究院 - 2

 

 

继续如下图所示,立方体对象的名子是不是变成“白色”拉? 此时如果说你想将预设还原,那么在导航菜单栏中选择GameObject -> Apply Changes To Prefab ,在看看你的Cube的名子就由变成“蓝色”。仔细观察还是有问题,请看右侧Inspector视图中下面有一个“Prefab”的标志,这说明它并没有清理干净。


Unity3D研究院之预设的使用细节(五十一) - 雨松MOMO程序研究院 - 3

 

 

如果你想彻底的还原Cube对象,那么只有一个办法就是在Project视图中删除原始Prefab对象。此时删除你会发现你的立方对象已经和新创建的没什么两样了,还有一种情况是你并没有先将立方体对象Break Prefab Instance  而是直接在Hierarchy视图中删除。如下图所,此时你会发现你的Cube颜色成红色,它表示你的Prefab已经丢失。

 

Unity3D研究院之预设的使用细节(五十一) - 雨松MOMO程序研究院 - 4

 

此时选中“红色的”Cube对象,继续在Unity导航菜单栏中选择GameObject->Break Prefab Instance ,你会发现你的立方体对象已经和新创建的完全一样拉。

然后是Prefabe的批量应用,在Hierarchy视图中可能会有很多相同的Prefab对象,此时如果想给所有的Prefabe对象添加或删除一个组件该如何?在Project视图中找到Prefabe原始对象,直接在这个对象上添加或删除组件,它会全部应用所有Hierarchy视图中的Prefab对象们。但是这样还有问题,就是Project视图中的Prefab原始对象它并不可以在Scene视图中去预览,所以我推荐大家使用另外一种方式来批量应用Prefabe对象。

先在Hierarchy视图中选择Prefab对象中的其中一个。在右侧Inspector视图中,如下图所示,Prefab对象都有三个常用的按钮.

Select:点击后会立即定位到Project视图中的原始Prefab对象。

Revert:如果你不小心破坏了Hierarchy视图中当前这个Prefab对象,点击它可以还原至Project视图中原始Prefab对象。

Apply: 主要想说的就是这个, 如果你想批量修改所有Prefab对象,比如添加一个新的组件后,点击这个按钮可以把所有对象还有原始Prefabe对象都应用成你现在编辑的对象。还有一种方法也可以达到这种效果,就在在Unity导航菜单栏中选择GameObject -> Apply Changes To Prefab 。

Unity3D研究院之预设的使用细节(五十一) - 雨松MOMO程序研究院 - 5

 

立方体、球体、圆柱体、胶囊体、面这几个是Unity自身提供的原始模型,如果你的模型是由美术自行创建的Fbx文件该如何?

.Fbx模型属于资源对象,和贴图、材质、声音属于同样类型的资源。。但是.Fbx更加的特殊,因为它可以直接拖入Hierarchy视图中并生成游戏对象。此时你会发现Hierarchy视图中它也是蓝颜色的字,但是它并不是Prefab对象,它是Mode对象。它也可以使用导航菜单栏中的 Break Prefab Instance ,我建议使用的时候最好把.fbx模型对象转成Prefab对象来使用。

上面说的很多都是在编辑器模式下,下面在说说程序运行时。在脚本中可以这样动态的生成Prefab 。

 也可以通过Resource动态的加载Prefab原始对象,AssetBundle.load()也可以。。

 

如果你想编辑器拓展Prefab插件的话可以使用 PrefabUtility类,它属于Editor下的类,只能在编辑时运行。比如创建Prefab对象, 替换Prefab对象,克隆Prefab对象。等等,都可以使用它。 使用起来有问题的话欢迎留言给我。

 

2.运行时修改游戏对象

我们知道游戏在运行的时候你在编辑器中对游戏对象做的任何操作,等停止运行时会自动重置。比如你运行的时候把某个对象的坐标重新调了一遍,停止运行的时候你会发现这个坐标又重置了。有一个比较巧妙的办法能处理这个问题, 当游戏运行的时候你把坐标调节完以后,这时Command + c 复制需要修改的所有游戏对象。然后关闭运行,Command + v 粘帖对象。 (但是要把之前的对象删除)。

最后欢迎大家一起讨论与学习。

雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!

--

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。

  1. 目前实现一个替换UIprefab中图集和图集中的spritename的编辑器,在替换后由于修改了预设体,拥有该预设体引用的其他预设体会丢失该预设体的引用,请问有什么解决办法?或者是有什么编辑器类提供的api能实现如Unity预设体中改变预设体后Apply保证持有该预设体引用的其他预设体不丢失引用的功能?我修改预设体属性的思路是建一个新的预设体然后用PrefabUtility中替换预设体的方法替换新的预设体,然后保存本地。

  2. 前辈请教一下,我想知道scene存档前/存档后以及prefab apply前/apply后的事件,我想介入这四个时间点做动态元件的置换,你知道UnityEditor是否有提供这4个事件吗?或是有什么技巧可以用得上的?谢谢了

  3. “还有一种情况是你并没有先将立方体对象Break Prefab Instance 而是直接在Hierarchy视图中删除”应该是直接在Project里删除吧?如果直接在Hierarchy里删除的话,场景中的立方体都没有了,怎么显示红色呢?

  4. momo,我看了你很多资料,非常感谢你的付出。我想请教个问题,就是程序里面如何判断一个物体是否有预设,并获取预设所在的文件路径(project里面的相对路径)。谢谢你

    • 我自己解决这个问题了,这里发出来方便其他需要的朋友。Debug.Log(EditorUtility.GetPrefabType (Selection.activeGameObject));上面语句能判断是预设还是预设实例还是其他;下面两个能获得路径:Debug.Log(AssetDatabase.GetAssetPath(EditorUtility.GetPrefabParent (Selection.activeGameObject))); Debug.Log(AssetDatabase.GetAssetPath(EditorUtility.FindPrefabRoot (Selection.activeGameObject)));

  5. 你好,请问我想获取一个还没有实例化 预设的大小该怎么办? 我用tranform.collider.bounder.size 来获取正常的物件是没有问题的,获取预设的大小都为0.

  6. 你好,请问我想获取一个还没有实例化 预设的大小该怎么办? 我用tranform.collider.bounder.size 来获取正常的物件是没有问题的,获取预设的大小都为0.

  7. 一个很纠结的问题。我在弄物体的储存,首先想到的是xml和二进制文件,于是就去看了你的博文,但我要储存的物体上面脚本关联比较厉害,作为一个程序员果断想偷懒,于是我去看了下unity自己的场景和预制文件大小发现。把你那个项目里的场景做成预制后,binary 803字节json 3kbxml 5kb整个场景的预制 325字节。。。。。。于是就蛋疼了,关于预制的创建都是编辑器模式下的,那么如何在运行是动态的创建以及关联预制呢?

    • 完全可以动态创建的。。 unity中有两个类 Resourch 和 assetbundle 就可以在程序运行中去读取本地的模型 或预制 贴图 等资源 然后载入游戏

  8. 你好大神啊,我想请你给点指示,公司现在做的一款游戏是单机的,运行在iPhone手机上,现在想做成网络上可以玩家对杀的,用的是unity3D 开发,现在想进行网络对战,请问如何入手啊,好像photon服务器什么的,如果直接在unity上进行socket通讯可以实现吗,如果做成网络游戏的话,有书籍或者网站可以介绍吗,请大神指示额

  9. 你好,我最近在读你的书,里面的9.3.6~7中讲的是有关于多人会话的客户端和服务器。我再PC上测试是可以对话的,想问一下,你用android或者IOS的机器测试过吗,我这边用android测试服务器连接不上,请问知道原因吗?我个人感觉有可能是android的player settings里面的设置有问题,或者是我的服务器的IP有问题。

    • 找到问题了,是IP的问题,我用电脑的IP手机就可以联机我电脑的服务器了。还有个问题,我电脑的服务器是属于局域网吗,如果我想在家,再公司都能连接我的服务器的话应该用什么方法啊?

  10. 嗨,MoMo大神,我遇到个麻烦,我用Debug.Log()读一个AnimationClip.length的return value,在Unity3d中返回正确,一旦build到XCode上面去,所有的Clip长度返回值都变成了1.为什么?请指教。如定义 public AnimationClip IdleClip; IdleClip是直接拖到脚本中去的。