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的更多相关文章
随机推荐
- Django开发:(1)django基础 & url控制器
HTTP请求协议 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于万维网(WWW:World Wide Web )服务器与本地浏览器之间传输超文本 ...
- Ubuntu 16.04安装RabbitVCS替代TortoiseSVN/TortoiseGit
RabbitVCS官网:http://www.rabbitvcs.org/easonjim 1.添加PPA源 sudo add-apt-repository ppa:rabbitvcs/ppa 如果导 ...
- 如何探测浏览器是否开启js功能
<body> ... ... <script type="text/javascript"> <!-- document.write("He ...
- dubbo的jmeter压测时jar包的热加载/动态加载
在做dubbo的jmeter压测时,需要把jar包放入jmeter的lib/ext目录下,但是jmeter启动的时候会自动加载这个目录lib目录及lib/ext目录,这样启动后放入这些目录下的jar包 ...
- 手把手教你编写一个简单的PHP模块形态的后门
看到Freebuf 小编发表的用这个隐藏于PHP模块中的rootkit,就能持久接管服务器文章,很感兴趣,苦无作者没留下PoC,自己研究一番,有了此文 0×00. 引言 PHP是一个非常流行的web ...
- 条款十: 如果写了operator new就要同时写operator delete
为什么有必要写自己的operator new和operator delete? 答案通常是:为了效率.缺省的operator new和operator delete具有非常好的通用性,它的这种灵活性也 ...
- DELL T110II Server如何通过RAID 级别迁移的方式在OMSA下实现磁盘阵列扩容?
目录: RAID 转移规则说明 操作步骤 本文介绍了 通过RAID 级别转换来实现扩容的方法注意:本文相关RAID的操作,仅供在测试环境里学习和理解戴尔PowerEdge服务器RAID控制卡的功能和使 ...
- Outlook2010 没有Exchange Server,怎么自动回复邮件?
步骤 1:创建邮件模板 单击“开始”>“新建邮件”. 在邮件正文中,键入要作为自动答复发送的邮件. 在邮件窗口中,单击“文件”>“另存为”. 在“另存为”对话框中的“保存类型”列表中,单击 ...
- [Unity3D]Unity3D游戏开发之从Unity3D到Eclipse
---------------------------------------------------------------------------------------------------- ...
- 贪吃蛇 c++ ncurses
近期学ncurses.用贪吃蛇训练下 思路:不构造链表.蛇头向前进方向打点,蛇尾逐点消失,形成移动. 须要记录蛇头方向,蛇尾方向.并用list仿造队列,增加拐点信息(空间比链表每一个结点开辟空间节省非 ...