注意,编辑器模式下可使用的大量代码在运行时无法使用。
//--加载资源
在编辑器模式下,Unity提供了一个标志性的类AssetDatabase,它专门负责读取工程内的资源。
必须保证资源放在项目的Assets目录下,不然AssetDatabase是无法读取的,只能使用File类或者第三方工具类来读取。
using UnityEditor;
using UnityEngine;
public class EditorModeAssetLoadMyTools
{
[MenuItem("Assets/My Tools/Load", false)]
static void MyLoad()
{
if (Selection.activeTransform)
{
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/MyCube.prefab");
GameObject go = Object.Instantiate(prefab);
go.transform.SetParent(Selection.activeTransform);
}
}
}
提供一个Assets内的相对路径,使用AssetDatabase.LoadAssetAtPath()方法即可读取任意对象。
MyCube预制体被实例化到Root节点下。
可以看见它不是“蓝色”的,坐标没有归原点。
因为Object.Instantiate()只能创建新对象,这样将丢失Prefab的引用。
因为transform.SetParent()会继承世界坐标。
//--实例化Prefab
using UnityEditor;
using UnityEngine;
public class EditorModePrefabUtilityMyTools
{
[MenuItem("Assets/My Tools/LoadPrefab", false)]
static void MyLoadPrefab()
{
if (Selection.activeTransform)
{
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/MyCube.prefab");
GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
go.transform.SetParent(Selection.activeTransform, false);
}
}
}
“蓝色”
坐标归原点。
在编辑器模式下,实例化Prefab需要使用PrefabUtility.InstantiatePrefab()方法。实例化的Prefab是“蓝色”的。
除了Prefab以外,FBX也属于一种特殊的引用关系的资源,也可以使用这种方法实例化,也会保持它的一些引用关系。
transform.SetParent()第二个参数传false表示不被它的父坐标影响,就会归远点。
//--创建Prefab
using UnityEditor;
using UnityEngine;
public class EditorModeCreatePrefabMyTools
{
[MenuItem("Assets/My Tools/Create Prefab", false)]
static void MyCreatePrefab()
{
if (Selection.activeTransform)
{
string path = "Assets/Prefab.prefab";
if (AssetDatabase.LoadAssetAtPath<GameObject>(path))
{
AssetDatabase.DeleteAsset(path);
}
PrefabUtility.CreatePrefab(path, Selection.activeGameObject, ReplacePrefabOptions.ConnectToPrefab);
AssetDatabase.Refresh();
}
}
}
PrefabUtility.CreatePrefab()方法可以创建Prefab,此时需要提供保存的目录以及当前的游戏对象。
ReplacePrefabOptions.ConnectToPrefab表示创建Prefab的同时自动关联创建它的这个游戏对象。
//--更新/保存Prefab
using UnityEditor;
using UnityEngine;
public class EditorModeApplyPrefabMyTools
{
[MenuItem("Assets/My Tools/Apply Prefab", false)]
static void MyApplyPrefab()
{
if (Selection.activeTransform)
{
Object prefab = PrefabUtility.GetCorrespondingObjectFromSource(Selection.activeGameObject);
if (prefab)
{
PrefabUtility.ReplacePrefab(Selection.activeGameObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
}
AssetDatabase.Refresh();
}
}
}
注意,要选中预制体的根节点。(要是选中子节点,子节点会代替整个预制体)。
//--卸载资源
using UnityEditor;
using UnityEngine;
public class EditorModeDeleteMyTools
{
[MenuItem("Assets/My Tools/Delete", false)]
static void MyDelete()
{
if (Selection.activeTransform)
{
Object.DestroyImmediate(Selection.activeGameObject, true);
}
}
}
在编辑器模式下只能使用Object.DestroyImmediate()方法来卸载游戏对象。
如果要卸载游戏对象引用的资源,第二个参数用true,默认是false。
//--游戏对象与资源的关系
游戏对象与资源是一种引用关系。
例如,一个模型是由贴图和Mesh组成,将它拖入场景中时,生成的游戏对象就会引用这两种资源。当程序调用GameObject.Destroy()或者GameObject.DestroyImmediate()方法时,只会卸载掉它的对象,它身上引用的贴图和Mesh还在内存中。
Unity这么做是有原因的:很多游戏对象的加载与卸载是很频繁的,如果每次卸载都将引用的资源清理掉,无疑会造成IO的阻塞。但是如果长时间不卸载这些资源,那么内存必然涨上去。
所以Unity又提供了一个方法来自动卸载无用资源。其中,无用资源表示没有被别的对象或代码引用的资源。
EditorUtility.UnloadUnusedAssetsImmediate()方法即可卸载编辑器下无用资源了。
using UnityEditor;
public class EditorModeUnloadUnusedMyTools
{
[MenuItem("Assets/My Tools/UnloadUnusedAssetsImmediate", false)]
static void MyUnloadUnused()
{
EditorUtility.UnloadUnusedAssetsImmediate();
}
}