Unity中使用代码将预制加载到场景
Posted 拂面清风三点水
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity中使用代码将预制加载到场景相关的知识,希望对你有一定的参考价值。
Unity中使用代码将预制加载到场景
大家知道, 在日常修改预制的时候很方便, 我们将预制从资源文件夹往场景上"一拖", 然后就可以进行修改, 然后应用保存即可.
但是如果某些需求下, 我们想要使用代码来完成这个操作就比较麻烦.
比如需求为: 查找某个文件夹下所有预制, 如果其中有使用了RectMask2D组件的, 需要全部替换成Mask, 并且在替换完成后需要人工确定是否正确.
如果不需要人工确定, 其实很简单, 配合AssetDataBase
相关的接口将预制加载出来, 然后替换组件后保存预制即可.
但是最后需要人工确定, 有问题还需要手动修改一部分, 那么就需要将预制加载到场景, 然后自动选中发生修改的节点来确定修改的正确.
按照正常的逻辑, 我可以像正常使用预制, 实例化对象的线路去思考, 但是实践下来发现, 加载到场景的是实例化之后的对象, 修改后无法应用保存, 和手动拖预制的结果不一致.
这时我们就需要使用另一个接口来达到目的了:
using UnityEditor;
// 将给定场景中的给定预制件实例化
// 第一个参数target是预制资源
// 第二个参数destinationScene是目标场景, 如果不传就默认是当前场景
public static Object PrefabUtility.InstantiatePrefab (Object target , SceneManagement.Scene destinationScene);
首先需要遍历选中目录, 查找预制并加载:
// Selection.activeObject是当前选中的目录
var dir = AssetDatabase.GetAssetPath(Selection.activeObject);
if (!Directory.Exists(dir))
Debug.LogError("选中的不是目录!" + dir);
return;
var allPrefabLst = AssetDatabase.FindAssets("t:Prefab", new []dir);
foreach (var guid in allPrefabLst)
var path = AssetDatabase.GUIDToAssetPath(guid);
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
var find = go.GetComponentInChildren<RectMask2D>(true);
if (!find) continue;
// ...
预制实例化并加到场景后, 将返回的对象转换类型后就可以设置其父节点:
var obj = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
// 注意第二个参数, 如果不为false, 会导致加载出来的对象transform发生变化
obj.transform.SetParent(rootTransform, false);
我们还需要找到当前场景中指定的节点作为其统一挂载的父节点:
// 比如: 场景中的节点层级为: rootNode/xxx/parent
// 通过调用GetCurSceneObject("rootNode", "xxx/parent")完成需求
static GameObject GetCurSceneObject(string rootName, string selectPath)
var curScene = SceneManager.GetActiveScene();
foreach (var rootGameObject in curScene.GetRootGameObjects())
if (!rootName.Equals(rootGameObject.name)) continue;
var transform = rootGameObject.transform.Find(selectPath);
if (transform) return transform.gameObject;
return null;
然后是替换组件:
private static void ReplaceRectMask2D(GameObject go)
var children = rootGo.GetComponentsInChildren<RectMask2D>(true);
foreach (var rectMask2D in children)
var go = rectMask2D.gameObject;
// 非运行模式下需要使用这个接口
Object.DestroyImmediate(rectMask2D);
go.AddComponent<Mask>();
最后选中对象可以使用这里的介绍.
下面是完整的代码:
[MenuItem("Assets/PrintRectMask2DReferences", priority = 301)]
private static void PrintRectMask2DReferences()
var dir = AssetDatabase.GetAssetPath(Selection.activeObject);
if (!Directory.Exists(dir))
Debug.LogError("选中的不是目录!" + dir);
return;
var allPrefabLst = AssetDatabase.FindAssets("t:Prefab", new []dir);
var rootNode = GetCurSceneObject("rootNode", "xxx/parent");
if (!rootNode)
Debug.LogError("当前场景没有找到挂载节点: " + "rootNode/xxx/parent");
return;
var rootTransform = rootNode.transform;
var findLst = new List<GameObject>();
foreach (var guid in allPrefabLst)
var path = AssetDatabase.GUIDToAssetPath(guid);
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
var find = prefab.GetComponentInChildren<RectMask2D>(true);
if (!find) continue;
Debug.Log("find =>: " + path);
var go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
if (!go) continue;
findLst.Add(go);
go.transform.SetParent(rootTransform, false);
ReplaceRectMask2D(go);
Debug.LogError("一共找到预制: " + findLst.Count);
好了, 以上就是今天的内容, 希望对大家有所帮助.
unity 3d发布的exe程序可以从外部(比如同文件夹下的一个fbx文件)读取模型到场景中吗?
目的是动态的读取文件,而不用重新发布exe程序
参考技术A 使用AssetBundles让你通过WWW类流式加载额外的资源并在运行时实例化它们使用方式可以看看雨凇momo的这篇博文:
http://www.xuanyusong.com/archives/2405本回答被提问者和网友采纳
以上是关于Unity中使用代码将预制加载到场景的主要内容,如果未能解决你的问题,请参考以下文章
unity 3d发布的exe程序可以从外部(比如同文件夹下的一个fbx文件)读取模型到场景中吗?