Unity3D研究之Prefab里面的Prefab关联问题
Unity研究院之Prefab和GameObject的正向和逆向查找引用
我发现很多美工兄弟都爱问程序Unity3d为什么总丢材质? 我不排除U3d有BUG的情况下会丢材质?但是其实很多时候是人为操作而引起的。
1.不保存就在上传
这个操作太恐怖了,切记!!在 U3D里面你无论操作了什么,当你要上传svn的时候一定要先保存场景,Ctrl+S 切记切记!!如果不保存就上传很有可能就会丢材质。
2.我的电脑明明没事,怎么你哪里就丢材质?
我发现一个很有意思的现象,每次走到美术电脑前看它的svn工程时,我都会发现各种的“黄叹号”整个工程严重的冲突。然后程序和美术的对话就是:“这资源有用没?没用删了, 我重新更新。。。” 哈哈哈 我觉得可能只有程序员才会对冲突非常敏感吧,但我觉得这件事不能怪美术,美术是很抽象的东西,不向程序要具体到少一个分号就无法进行了。
3.管理好材质贴图
如果项目不管理好材质和贴图,后起你会发现有很多完全一样的图片只是名子不一样,但是还都在使用中。。这个很有可能是好几个美术同时在做,这样会造成资源的浪费。
4.特效丢材质
我举个实际的例子,我们项目场景和特效是两个人来做。之前总遇到场景特效莫名其妙丢材质的问题。原因就是做特效的人把特效修改了,但是做场景的又不知道,因为可能这个特效在好多场景上都在使用中。
如下图所示,在Preiject下面方的Prefab 如果拖入Hierarchy视图中,它俩是具有关联关系的,如果你直接在Project视图中修改了Prefab那么所有Hierarchy视图中关联它的Prefab都会得到修改。小改动这样是没问题的,如果发生一些比较大的改动,那么Hierarchy视图中Prefab可能就会丢失或者坏掉。但是假如你有很多场景都引用同一个Prefab,这么多场景会很难找到的。
正向在Hierarch视图中选择一个prefab,然后在右侧Inspector视图中点击Select会自动找到Project视图中的Prefab对象。那么反向如何从Project视图中找到Hierarchy视图中引用的Prefab呢?
如下图所示,Unity3d做了一个功能,在Project视图中选择一个Prefab,然后右键选择Find References In Scene ,那么此时Unity会自动帮你在当前场景中找到Hierarchy视图中引用这个Prefab的GameObject。
但是这个方法有点局限性,就是它只能找到当前场景的,假设你的这个Prefab在很多场景中都引用了,那么这样是找不到了,为了美术我决定写一个小小的工具,嘿嘿。
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
|
[MenuItem("Assets/Check Prefab Use ?")]
private static void OnSearchForReferences()
{
//确保鼠标右键选择的是一个Prefab
if(Selection.gameObjects.Length != 1)
{
return;
}
//遍历所有游戏场景
foreach(EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if(scene.enabled)
{
//打开场景
EditorApplication.OpenScene(scene.path);
//获取场景中的所有游戏对象
GameObject []gos = (GameObject[])FindObjectsOfType(typeof(GameObject));
foreach(GameObject go in gos)
{
//判断GameObject是否为一个Prefab的引用
if(PrefabUtility.GetPrefabType(go) == PrefabType.PrefabInstance)
{
UnityEngine.Object parentObject = EditorUtility.GetPrefabParent(go);
string path = AssetDatabase.GetAssetPath(parentObject);
//判断GameObject的Prefab是否和右键选择的Prefab是同一路径。
if(path == AssetDatabase.GetAssetPath(Selection.activeGameObject))
{
//输出场景名,以及Prefab引用的路径
Debug.Log(scene.path + " " + GetGameObjectPath(go));
}
}
}
}
}
}
public static string GetGameObjectPath(GameObject obj)
{
string path = "/" + obj.name;
while (obj.transform.parent != null)
{
obj = obj.transform.parent.gameObject;
path = "/" + obj.name + path;
}
return path;
}
|
如下图所示,我就可以找到哪个场景引用了这个Prefab。 这里我没有用GameObject和Prefab的名子来判断,我觉得最好也不要用名字,因为Hierarchy视图中的名子完全可以随意修改的,如果被改了的话就肯定找不到了,而且场景那么多完全有重名的情况。
是不是很简单呢?嘿嘿。
或者还有个办法,就是运行时动态的载入Prefab,但是有些场景特效其实万全没有任何意义,仅仅是展示而已,程序也无需对它进行操作。
有了这个小工具,那么以后美术改完Prefab的时候,运行一下连带的看看某些场景上是否正常的显示了?嘿嘿嘿嘿。
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
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不操作脚本。
如果有更好的方法欢迎各位朋友在下面给我留言,谢谢。
Unity3D研究之Prefab里面的Prefab关联问题的更多相关文章
- Unity3D研究院之Prefab里面的Prefab关联问题(转)
转自http://www.xuanyusong.com/archives/3042 最近在做UI部分中遇到了这样的问题,就是Prefab里面预制了Prefab.可是在Unity里面一旦Prefab预制 ...
- Unity3D研究院之Prefab里面的Prefab关联问题
最近在做UI部分中遇到了这样的问题,就是Prefab里面预制了Prefab.可是在Unity里面一旦Prefab预制了Prefab那么内部的Prefab就失去关联.导致与如果要改内部的Prefab需要 ...
- Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五)
http://www.xuanyusong.com/archives/3727 感谢楼下的牛逼回复更正一下,我表示我也是才知道.. 其实不需要实例化也能查找,你依然直接用GetComponentsIn ...
- UMG里没有"Prefab"怎么办?
大家知道在Unity里做UI,利用Prefab是少不了的,但是在UE4里如何做呢? 这是实际工作中遇到的问题,我Google关键词“UMG Prefab","UMG resuabl ...
- jmeter压测学习3-提取json数据里面的token参数关联
前言 现在很多接口的登录是返回一个json数据,token值在返回的json里面,在jmeter里面也可以直接提取json里面的值. 上一个接口返回的token作为下个接口的入参. 案例场景 我现在有 ...
- 父Prefab与子prefab问题
PrefabRevolution 原文:http://framebunker.com/blog/poor-mans-nested-prefabs/ (溜还是老外溜啊) 有些时候需要在Prefab里 ...
- Activity往另外一个Activity传值,Fragment获取另外一个Activity里面的值。
在oneActivity中实现跳转到MainActivity //intent 用来跳转另外一个MainActivity,bundle传值到MainActivity Intent Ma ...
- 友盟推送里面的Alias怎么用?可以理解成账号吗?
友盟推送里面的Alias怎么用?可以理解成账号吗? 我们的App有自己的账号体系的,想在每次用户登陆的时候,给用户发一个欢迎消息. 看了一下友盟推送,里面有一个概念叫做Alias(别名),但是官方文档 ...
- koa2 use里面的next到底是什么
koa2短小精悍,女人不爱男人爱. 之前一只有用koa写一点小程序,自认为还吼吼哈,知道有一天某人问我,你说一下 koa或者express中间件的实现原理.然后我就支支吾吾,好久吃饭都不香. 那么了解 ...
随机推荐
- SQL Server 收缩日志
一. SQL Server 2008 收缩日志 (1) 使用SQL管理器收缩日志 第一步执行如下命令 ALTER DATABASE platform SET RECOVERY SIMPLE GO 第二 ...
- Moqui学习Day1
运行时目录以及Moqui的xml配置文件 Moqui框架部署运行主要有三个核心部分: 可执行的war包文件 运行时目录 Moqui配置文件XML格式 不管怎么使用这个可执行的war文件,你必须拥有一个 ...
- “耐撕”团队2016.04.12站立会议
1.时间 : 19:15--19:30 共计15分钟. 2.成员 : Z 郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), P 濮成林(博客:ht ...
- 利用Ant脚本生成war包的详细步骤
使用ant脚本前的准备 1.下载一个ant安装包.如:apache-ant-1.8.4-bin.zip.解压到E盘. 2.配置环境变量.新增ANT_HOME:E:\apache-ant-1.8.4:P ...
- oracle-7参数文件的管理
参数文件的管理:1.参数文件的作用:记录数据库的配置的 (1)pfile ---> 文本文件 (2)spfile --->服务器的参数文件(二进制的) 两个参数文件的区别: pfile ...
- JMeter工具的使用-ForEach
1,Add Thread group this detail information about this panel as below link http://jmeter.apache.org/u ...
- 360极速浏览器使用postman
Postman-REST-Client_v0.8.4.14.zip文件请加群下载:74085440 步骤如下: 1.将crx文件打包成zip文件 2.解压打包的zip文件,并将_metadata文件夹 ...
- offsetLeft, offsetTop以及postion().left , postion().top有神马区别
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- knockout——官网demo
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- PLSQL导入Excel表中数据
PL/SQL 和SQL Sever导入excel数据的原理类似,就是找到一个导入excel数据的功能项,按照步骤走就是了.下面是一个些细节过程,希望对像我这样的菜鸟有帮助. www.2cto.co ...