转自http://www.xuanyusong.com/archives/3042

最近在做UI部分中遇到了这样的问题,就是Prefab里面预制了Prefab。可是在Unity里面一旦Prefab预制了Prefab那么内部的Prefab就失去关联。导致与如果要改内部的Prefab需要把所有引用的地方全部改一遍。今天在逛国外网站看到了一个老外的思路,原文在这里 http://framebunker.com/blog/poor-mans-nested-prefabs/
下面直接上代码

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Callbacks;
#endif
using System.Collections.Generic;
 
[ExecuteInEditMode]
public class PrefabInstance : MonoBehaviour
{
public GameObject prefab;
 
#if UNITY_EDITOR
// Struct of all components. Used for edit-time visualization and gizmo drawing
public struct Thingy {
public Mesh mesh;
public Matrix4x4 matrix;
public List<Material> materials;
}
 
[System.NonSerializedAttribute] public List<Thingy> things = new List<Thingy> ();
 
void OnValidate () {
things.Clear();
if (enabled)
Rebuild (prefab, Matrix4x4.identity);
}
 
void OnEnable () {
things.Clear();
if (enabled)
Rebuild (prefab, Matrix4x4.identity);
}
 
void Rebuild (GameObject source, Matrix4x4 inMatrix) {
if (!source)
return;
 
Matrix4x4 baseMat = inMatrix * Matrix4x4.TRS (-source.transform.position, Quaternion.identity, Vector3.one);
 
foreach (MeshRenderer mr in source.GetComponentsInChildren(typeof (Renderer), true))
{
things.Add(new Thingy () {
mesh = mr.GetComponent<MeshFilter>().sharedMesh,
matrix = baseMat * mr.transform.localToWorldMatrix,
materials = new List<Material> (mr.sharedMaterials)
});
}
 
foreach (PrefabInstance pi in source.GetComponentsInChildren(typeof (PrefabInstance), true))
{
if (pi.enabled && pi.gameObject.activeSelf)
Rebuild (pi.prefab, baseMat * pi.transform.localToWorldMatrix);
}
}
 
// Editor-time-only update: Draw the meshes so we can see the objects in the scene view
void Update () {
if (EditorApplication.isPlaying)
return;
Matrix4x4 mat = transform.localToWorldMatrix;
foreach (Thingy t in things)
for (int i = 0; i < t.materials.Count; i++)
Graphics.DrawMesh (t.mesh, mat * t.matrix, t.materials[i], gameObject.layer, null, i);
}
 
// Picking logic: Since we don't have gizmos.drawmesh, draw a bounding cube around each thingy
void OnDrawGizmos () { DrawGizmos (new Color (0,0,0,0)); }
void OnDrawGizmosSelected () { DrawGizmos (new Color (0,0,1,.2f)); }
void DrawGizmos (Color col) {
if (EditorApplication.isPlaying)
return;
Gizmos.color = col;
Matrix4x4 mat = transform.localToWorldMatrix;
foreach (Thingy t in things)
{
Gizmos.matrix = mat * t.matrix;
Gizmos.DrawCube(t.mesh.bounds.center, t.mesh.bounds.size);
}
}
 
// Baking stuff: Copy in all the referenced objects into the scene on play or build
[PostProcessScene(-2)]
public static void OnPostprocessScene() {
foreach (PrefabInstance pi in UnityEngine.Object.FindObjectsOfType (typeof (PrefabInstance)))
     BakeInstance (pi);
}
 
public static void BakeInstance (PrefabInstance pi) {
if(!pi.prefab || !pi.enabled)
return;
pi.enabled = false;
GameObject go = PrefabUtility.InstantiatePrefab(pi.prefab) as GameObject;
Quaternion rot = go.transform.localRotation;
Vector3 scale = go.transform.localScale;
go.transform.parent = pi.transform;
go.transform.localPosition = Vector3.zero;
go.transform.localScale = scale;
go.transform.localRotation = rot;
pi.prefab = null;
foreach (PrefabInstance childPi in go.GetComponentsInChildren<PrefabInstance>())
BakeInstance (childPi);
}
 
#endif
}

用法比较简单,比如我有两个Prefab,inside嵌入在Big里面。如下图所示,把PrefabInstance脚本挂在Big上,然后把inside拖入下方。

OK 无论怎么修改inside这个Prefab,当实例化Big的时候都能得到最新修改的Inside这个Prefab。

持续思考:

界面预览问题,就是我在布界面的时候,我需要把子集Prefab界面控件拖进来预览效果。如果用上述思路UI的Prefab就必须通过脚本自动生成。一份是预览用的也就是不需要脚本的,一份是只带脚本运行时动态生成的。在处理自动生成UIPrefab的时候可以利用tag 比如像这种需要内嵌的Prefab标记一个特殊的tag,在Editor下完成Prefab的导出。另外布界面的时候不需要绑定脚本,而上述脚本的绑定也应该由Editor导出Prefab的时候完成。

总之一切布界面的时候只操作Prefab不操作脚本。

最近造了个轮子可以批量替换prefab里的prefab,欢迎大家测试~  https://bitbucket.org/xuanyusong/prefab-replace

如果有更好的方法欢迎各位朋友在下面给我留言,谢谢。

Unity3D研究院之Prefab里面的Prefab关联问题(转)的更多相关文章

  1. Unity3D研究之Prefab里面的Prefab关联问题

    Unity研究院之Prefab和GameObject的正向和逆向查找引用 我发现很多美工兄弟都爱问程序Unity3d为什么总丢材质? 我不排除U3d有BUG的情况下会丢材质?但是其实很多时候是人为操作 ...

  2. Unity3D研究院之Prefab里面的Prefab关联问题

    最近在做UI部分中遇到了这样的问题,就是Prefab里面预制了Prefab.可是在Unity里面一旦Prefab预制了Prefab那么内部的Prefab就失去关联.导致与如果要改内部的Prefab需要 ...

  3. Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五)

    http://www.xuanyusong.com/archives/3727 感谢楼下的牛逼回复更正一下,我表示我也是才知道.. 其实不需要实例化也能查找,你依然直接用GetComponentsIn ...

  4. jmeter压测学习3-提取json数据里面的token参数关联

    前言 现在很多接口的登录是返回一个json数据,token值在返回的json里面,在jmeter里面也可以直接提取json里面的值. 上一个接口返回的token作为下个接口的入参. 案例场景 我现在有 ...

  5. UMG里没有"Prefab"怎么办?

    大家知道在Unity里做UI,利用Prefab是少不了的,但是在UE4里如何做呢? 这是实际工作中遇到的问题,我Google关键词“UMG Prefab","UMG resuabl ...

  6. (转)Unity3D研究院之Assetbundle的原理(六十一)

    Assetbundle 是Unity Pro提供提供的功能,它可以把多个游戏对象或者资源二进制文件封装到Assetbundle中,提供了封装与解包的方法使用起来很便利. 1.预设          A ...

  7. (转)MoMo的Unity3D研究院之Assetbundle的原理(六十一)

    http://www.xuanyusong.com/archives/2373 Assetbundle 是Unity Pro提供提供的功能,它可以把多个游戏对象或者资源二进制文件封装到Assetbun ...

  8. Unity3D研究院之Assetbundle的原理(六十一)

    www.xuanyusong.com/archives/2373 Assetbundle 是Unity Pro提供提供的功能,它可以把多个游戏对象或者资源二进制文件封装到Assetbundle中,提供 ...

  9. Unity3D研究院之Jenkins的使用(七十八)

    长夜漫漫无心睡眠,来一篇嘿嘿.我相信如果已经用Shell脚本完成IOS和Android打包的朋友一定需要Jenkins 怎么才能让策划打包ipa和apk?怎么才能彻底省去程序的时间,只要在同一局域网内 ...

随机推荐

  1. sqlserver2008 R2 创建作业(定时任务)

    如题: 第一步: 第二步: 第三步: 第四步: 第五步: 第六步: 第七步: 完成!!! 记得把服务打开.设置为自动启动,别重启服务器后没用了.

  2. android-获取当前屏幕尺寸信息

    方法有两种一: DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMet ...

  3. 用eclipse导入jar包并使其在一个文件夹下

    步骤如下:1.右键点击你需要添加jar包的项目. 2.选择“Properties”. 3.然后选择对话框中的“Java Build Path”. 4.选择“Libraries”选项卡,然后点击右边的“ ...

  4. linux脚本编程(shell)浅介 (转载)

    linux脚本(shell)编程 啊,昨天上网看到一篇讲 linux/unix shell 的文章,想想自己最后写这东西也是一年前的事了,想想都快忘光了. 还是整理一下,做一次回顾,以后说不定还用得上 ...

  5. 自动去除nil的NSDictionary和NSArray构造方法

    http://www.jianshu.com/p/a1e8d8d579c7 极分享 http://www.finalshares.com/

  6. PHP基础之 数组(二)

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  7. UI第三节——UIView详解

    - (void)viewDidLoad { [super viewDidLoad]; UIView *redView = [[UIView alloc] initWithFrame:CGRectMak ...

  8. cocos2d-x内存管理(见解)

    cocos2d-x 延续了cocos2d 和OC的引用计数的内存管理机制! 下面我们来看看CCDriectro类 CCPoolManager::sharedPoolManager()->push ...

  9. 关于Dijkstra最短路径算法

    Dijkstra算法,不是很明白,今天找了一些博客看了一下,决定自己也写一个为以后忘记的时候可以看做准备. 实际上,如果理解没错的话,该算法实际上和枚举法有点像,只不过,在选取出发路径的路径都是最短路 ...

  10. CentOS-6.5-NFS部署

                      nfs-server与nfs-client端配置一样   NFS(network file system)网络文件系统:用于在网络上共享存储. 服务端-192.16 ...