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在很多場景中都引用了,那麼這樣是找不到了,為了美術我決定寫一個小小的工具,嘿嘿。
[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的時候,執行一下連帶的看看某些場景上是否正常的顯示了?嘿嘿嘿嘿。