unity--------prefab嵌套prefab

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

最近在做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

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

时间: 2024-10-03 20:51:14

unity--------prefab嵌套prefab的相关文章

[Unity工具]嵌套Prefab

在父Prefab中嵌套子Prefab,那么如果对这个嵌套Prefab进行修改,改变将不会应用到子Prefab中:同理,对子Prefab的修改,也不会应用到这个嵌套Prefab中.因此,就会出现一些问题,例如子Prefab已经是最新的了,但是嵌套Prefab却是旧的.在unity2018.3中,已经有新功能来处理嵌套Prefab的问题了,但是之前的版本还是得要处理这个问题. 原文地址:https://www.cnblogs.com/lyh916/p/10428609.html

Unity Sprite转Prefab

新项目使用Unity5.X,遇到了一些问题,其中就有Sprite的管理更新问题,查了一些资料,Mono推荐的是转为Prefab处理. 看了一些国外同行的处理方法,分析了一个编辑器插件脚本.学到了一些技巧,使用的话依然放在Editor目录下.总结在这里吧: using UnityEngine; using UnityEditor; using System.Collections; using System.Linq; public class SpriteToPrefab { /// <summ

Unity加载prefab时调用脚本函数顺序

加载prefab时使用两个接口: GameObject objPrefab = Resources.Load(pathName) as GameObject; GameObject frame = NGUITools.AddChild(parent, objPrefab); //parent为对象需要挂载到的父节点对象 对象在被挂载到父节点上时,会调用脚本,分为两种情况: 1.prefab初始保存为Active状态 立刻按顺序触发 Awake, OnEnable 函数, 下一帧触发Start函数

unity, 保存prefab时material丢失问题

在程序运行时用replacePrefab(gameObj,prefab)或createPrefab(gameObj,prefab)保存prefab,遇到保存出来的prefab中material丢失的问题. 最后查到原因是gameObj的material成员引用的是一个material实例,而非material资源,所以保存成prefab后引用会丢失. 而导致gameObj的material成员实例化的原因是某处调用了gameObj.meshRenderer.material.

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

Unity研究院之Prefab和GameObject的正向和逆向查找引用 我发现很多美工兄弟都爱问程序Unity3d为什么总丢材质? 我不排除U3d有BUG的情况下会丢材质?但是其实很多时候是人为操作而引起的. 1.不保存就在上传 这个操作太恐怖了,切记!!在 U3D里面你无论操作了什么,当你要上传svn的时候一定要先保存场景,Ctrl+S 切记切记!!如果不保存就上传很有可能就会丢材质. 2.我的电脑明明没事,怎么你哪里就丢材质? 我发现一个很有意思的现象,每次走到美术电脑前看它的svn工程时

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

最近在做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

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

http://www.xuanyusong.com/archives/3727 感谢楼下的牛逼回复更正一下,我表示我也是才知道.. 其实不需要实例化也能查找,你依然直接用GetComponentsInChildren<>(true),对传true即可...这样搞还很麻烦...唯一关注是能否把Missing的脚本序列化找出来?? 使用 GetComponentsInChildren<>(true) 可以直接把Project视图里的子对象找出来!!!! return; 代码是这样的 1

[Unity-21] Prefab详解

1.什么是Prefab? Prefab又被称为预设,下面部分来自官网:预置是一种资源类型--存储在项目视图中的一种可重复使用的游戏对象.预置可以多次放入到多个场景中.当你添加一个预置到场景中,就创建了它的一个实例.所有的预置实例链接到原始预置,基本上是它的克隆.不管你的项目存在多少实例,当你对预置进行任何更改,你将看到这些更改将应用于所有实例. 当预置源发生变化,这些变化将应用于所有已链接的游戏对象.例如,如果添加一个新的脚本到预置,所有已链接的游戏对象都将立刻包含该脚本.但是,它有可能改变一个

使用Unity3D50个技巧-50 Tips for Working with Unity (Best Practices)

原文: 50 Tips for Working with Unity (Best Practices) About these tips These tips are not all applicable to every project. They are based on my experience with projects with small teams from 3 to 20 people. There's is a price for structure, re-usabilit