Unity插件开发:PrefabUtility--Prefab实例引用断开和替换

在Unity使用Prefab过程中,我们有时候需要进行Prefab实例断开引用和替换引用的需求。实现这些需求,使用到的核心的类是PrefabUtility。PrefabUtility是一个静态类,主要用于进行Prefab的相关处理。 这里主要使用以下几种方法

  • PrefabUtility.CreateEmptyPrefab
  • PrefabUtility.ReplacePrefab
  • PrefabUtility.DisconnectPrefabInstance
  • PrefabUtility.GetPrefabParent
  • PrefabUtility.ConnectGameObjectToPrefab

断开引用

断开Prefab引用的代码如下

[MenuItem("Tools/Prefab/去除引用")]

public static void BreakPrefabRef()

{

var select = Selection.activeGameObject;

if (select.activeInHierarchy)

{

PrefabUtility.DisconnectPrefabInstance(select);

Selection.activeGameObject = null;

var prefab = PrefabUtility.CreateEmptyPrefab("Assets/empty.prefab");

PrefabUtility.ReplacePrefab(select, prefab, ReplacePrefabOptions.ConnectToPrefab);

PrefabUtility.DisconnectPrefabInstance(select);

AssetDatabase.DeleteAsset("Assets/empty.prefab");

}

}

虽然PrefabUtility.DisconnectPrefabInstance有断开Prefab的含义,但是如果仅仅使用这个函数会出现下面这个情况,名字的颜色从蓝变白,看起来已经不是一个prefab,但是从Inspector面板中还是能够看到Prefab标记以及Prefab实例才会出现的那三个Select、Revert、Apply按钮。

如果尝试在这个时候删除掉Project里面的源prefab,发现这个prefab标记就消失了。

因此,这里采用以下方法实现整个断开引用

  • 使用Selection.activeGameObject获取当前选中的物体
  • 使用PrefabUtility.CreateEmptyPrefab先创建一个空的prefab
  • 使用PrefabUtility.ReplacePrefab将场景中选中的Prefab实例制作成一个Prefab并覆盖到之前的空prefab上
  • 使用PrefabUtility.DisconnectPrefabInstance断开引用
  • 使用AssetDatabase.DeleteAsset删除Project中新建的prefab

至此就完成了断开引用的功能。这里在函数加上[menuitem]标签,将这个功能放在unity菜单“Tools->Prefab->去除引用”上。

替换引用

替换引用的代码如下

[MenuItem("Tools/Prefab/替换引用")]

public static void RelocalPrefabRef()

{

var select = Selection.activeGameObject;

if (select.activeInHierarchy)

{

var ab = PrefabUtility.GetPrefabParent(select);

if (ab == null)

return;

var oripath = AssetDatabase.GetAssetPath(ab);

var filters = new[] { "prefab file", "prefab" };

var tar = EditorUtility.OpenFilePanelWithFilters("select target", Application.dataPath, filters);

if (string.IsNullOrEmpty(tar))

return;

tar = FileUtil.GetProjectRelativePath(tar);

var tarprefab = AssetDatabase.LoadAssetAtPath<GameObject>(tar);

if (tarprefab == null)

return;

var gname = select.name;

var enable = select.activeInHierarchy;

var pos = select.transform.localPosition;

var rot = select.transform.localRotation;

var scale = select.transform.localScale;

var go = PrefabUtility.ConnectGameObjectToPrefab(select, tarprefab);

go.transform.localPosition = pos;

go.transform.localRotation = rot;

go.transform.localScale = scale;

go.name = gname;

go.SetActive(enable);

Debug.LogFormat("Replace Prefab From:{0} to {1}", oripath, tar);

}

}

代码中主要的流程为

  • 使用Selection.activeGameObject获取选中的物体
  • 使用PrefabUtility.GetPrefabParent获取这个物体在project中的源prefab
  • 使用AssetDatabase.GetAssetPath获取源prefab在project中的路径(后面用于log)
  • 使用EditorUtility.OpenFilePanelWithFilters打开一个文件选择窗口让玩家选择一个源prefab
  • 使用FileUtil.GetProjectRelativePath获取这个源prefab相对于工程的路径
  • 使用将这个源prefab加载到内存中
  • 为了保持替换后的位置关系,这里记录了原来的位置信息
  • 使用PrefabUtility.ConnectGameObjectToPrefab重新将选中的物体链接到玩家选择的源prefab上,完成prefab引用替换
  • 还原原来的位置关系

至此完成了Prefab实例替换引用的功能。在Unity中选择菜单Tools->Prefab->替换引用,选择一个prefab即可实现替换

转载保留:http://www.cnblogs.com/CodeGize http://www.codegize.com

时间: 2024-10-04 23:49:50

Unity插件开发:PrefabUtility--Prefab实例引用断开和替换的相关文章

Unity插件开发:SerializedObject/SerializedProperty&mdash;&mdash;查找引用的资源

        Unity有一个Find References in Scene功能非常好用.在Project面板中右键一个文件,选择Find References in Scene就可以在场景中找到所有存在对这个文件有引用的物体.但是很多时候,我们更加需要知道的是,这个场景里面到底引用了哪些文件,比如做优化的时候.         这里有一个插件叫做ResourceChecker,它可以列举出所有引用到的texture/mesh/mat等.但是他也有一个小小的问题,对于自定义脚本的引用没有效果

Asp.Net MVC学习记录之“一个实体对象不能由多个 IEntityChangeTracker 实例引用”

原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. ? 1 2 3 4 5 var re = /\d/; console.log( re.test("1") ); console.log( re.test("1") ); console.log( re.test("1") ); console.log( re.test("1"

一个实体对象不能由多个 IEntityChangeTracker 实例引用。

错误代码 public bool addSubOptionItem(csModel.cs_Answer answers) { bool result = false; wpe = new csWeiPlatformEntities();//实例化entity对象 try { wpe.CreateObjectSet<cs_Answer>().AddObject(answers); wpe.SaveChanges(); result = true; } catch (Exception) { re

Linux之变量引用与命令替换

在bash脚本编写中,我们时常需要引用变量与替换命令,为规范操作,现对其做简单的总结说明. 引用 引用就是指将字符串用引用符号括起来,以防止特殊字符被shell脚本解释为其他意义.引用时屏蔽特殊字符的特殊意义,而将其解释为字面意义. 引用符.名称.意义说明表 引用符 名称 意义说明 '' 单引号 称全引用或弱引用,引用所有的字符:单引号中字符除单引号本身之外都解释为字面意义,单引号不具备引用变量的功能..单引号用于保持引号内所有字符的字面值,即使引号内的\和回车也不例外. "" 双引号

Unity Sprite转Prefab

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

unity插件开发——Selection

Selection是一个静态类,它的主要功能是获取在project窗口中鼠标选择的对象或者是inspector窗口的当前显示的对象.它的字段有 activeGameObject activeInstanceID activeObject activeTransform gameObjects instanceIDs objects transforms 其中activeGameObject和activeTransform是inspector窗口的当前显示对象对应的GameObject和Trans

unity插件开发——一个例子:简单的svn集成

在unity开发过程中,通常我们习惯性地在Windows操作系统下使用svn进行版本管理,而每次提交更新,都需要回到文件夹下的这种操作让人无法忍受.是不是可以集成svn到unity中呢?查了一圈unity store可以看到很多svn的第三方插件.考虑到我们只需要简单的功能,而且不希望加入额外复杂的代码,最后还是自己写一个插件.功能就是更新或者提交assets文件夹. 如果还没有svn对项目进行管理的,按照以下2步操作:     1.下载svn客户端,安装.     2.从svn版本库check

unity插件开发——MenuItem

有unity中的菜单栏是我们经常使用到的地方,如下图: MenuItem的作用就是增加一个自己的菜单 使用方法: 在工程中Assets目录下任意一个Editor目录(以后简称Editor目录,如果不存在,请自行创建)中创建任意脚本,比如我创建了叫做MenuTest .cs,双击进入代码编辑,创建一个静态函数,(代码来自官方文档http://docs.unity3d.com/Documentation/ScriptReference/MenuItem.html)如下: public class M

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

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