NestedPreb
屌丝手动版
One of the things we’re sorely missing from Unity is nested prefabs. So we rolled this little script to help us out – and figured other people could benefit as well.
You just add this script to a gameobject, and point the prefab field at the prefab you want instantiated.
This will render the prefab in the scene view while editing, and at bake time it will copy the objects into the scene so your gamecode can just work. It doesn’t allow overriding properties, and only previews the meshes, but we’ve been able to use it a lot for building props: We have a Gameobject that contains all the logic for a prop (e.g. definitions of cover points for a crate) – and then uses this script to pull in the actual FBX file that has the graphics. Now our graphic artist can just modify that and everything works.
You can also reference other prefabs, and nest these PrefabInstance scripts. While not as cool as a real system, it pretty much has solved our use cases.
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 = ; 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 (,,,)); }
void OnDrawGizmosSelected () { DrawGizmos (new Color (,,,.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(-)]
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
}
It uses the same principle as our IBakeable interface, but we want this to run before all the other IBakeable functions (so all objects are instantiated before we try to run others)


NestedPreb的更多相关文章
随机推荐
- 修改windows 2012/win8、win7远程桌面连接默认端口的方法
远程桌面连接服务基于端口3389,入侵者一般先扫描主机开放端口,一旦发现其开放了3389端口,就会进行下一步的入侵,所以我们只需要修改该务默认端口就可以避开大多数入侵者的耳目. 修改windows 2 ...
- CentOS 7.1安装GNOME,开启VNC Server
版权声明:本文为博主原创文章,未经博主允许不得转载. A.准备: 1.安装GNOME Desktop yum groupinstall 'GNOME Desktop' 2.确认GNOME Deskto ...
- android开发里跳过的坑——button不响应点击事件
昨天遇到一个头疼的问题,在手机上按钮事件都很正常,但是在平板上(横屏显示的状态),button点击事件不响应,代码简化如下: public class Test extends Activity im ...
- ZOJ 4016 Mergeable Stack 链表
Mergeable Stack Time Limit: 2 Seconds Memory Limit: 65536 KB Given initially empty stacks, the ...
- hdu_1398_Square Coins_201404260953
Square Coins Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- POJ 2431 Expedition【贪心】
题意: 卡车每走一个单元消耗一升汽油,中途有加油站,可以进行加油,问能否到达终点,求最少加油次数. 分析: 优先队列+贪心 代码: #include<iostream> #include& ...
- MongoDB小结09 - update【定位修改器】
如果要操作数组中的值,可以用值在数组中的位置当做参数来删除 db.user.update({"name":"codingwhy.com"},{"$se ...
- Why It is so hard to explain or show some thing
Why it is hard to explain something or learn something? For example, when I first know the hadoop, I ...
- mysql的时间戳说白了就俩问题,自动更新问题和不自动更新问题
mysql的时间戳timestamp说白了就俩问题,自动更新问题和不自动更新问题
- NSA开发的工控ICS/SCADA态势感知开源工具Grassmarlin(附下载地址)
工具简介 GRASSMARLIN是一款由美国国家安全局开发的,能够帮助运维工程师在IP网络上发现并编目监控和数据采集系统(SCADA)和工业控制系统(ICS)主机的开源软件工具,也被称为被动网络映射器 ...