469 lines
20 KiB
C#
469 lines
20 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Playables;
|
|
|
|
namespace Thousandto.Launcher.ExternalLibs
|
|
{
|
|
/// <summary>
|
|
/// Prefab的资源持续化脚本处理
|
|
/// </summary>
|
|
public class PrefabAssetData: UnityEngine.ScriptableObject
|
|
{
|
|
/// <summary>
|
|
/// 当前对象的名字
|
|
/// </summary>
|
|
public string Name;
|
|
/// <summary>
|
|
/// Prefab对象
|
|
/// </summary>
|
|
public GameObject PrefabObject;
|
|
|
|
/// <summary>
|
|
/// 渲染的资源信息
|
|
/// </summary>
|
|
public RenderAssetData[] RendererArray;
|
|
|
|
//动作资源信息
|
|
public AnimationAssetData[] AnimArray;
|
|
|
|
//动作资源信息
|
|
public AnimatorAssetData[] AnimtorArray;
|
|
|
|
//Timeline资源信息
|
|
public TimelineAssetData[] TimelineArray;
|
|
|
|
#region //运行时执行
|
|
//卸载资源
|
|
public void Unload()
|
|
{
|
|
/*
|
|
Debug.LogError("UnloadStart:" + Name + ";;内存:"
|
|
+ Profiler.GetTotalAllocatedMemory() / (1024 * 1024)
|
|
+ ";trm;" + Profiler.GetTotalReservedMemory() / (1024 * 1024)
|
|
+ ";turm;" + Profiler.GetTotalUnusedReservedMemory() / (1024 * 1024)
|
|
+ ";mus;" + Profiler.GetMonoUsedSize() / (1024 * 1024)
|
|
+ ";mhs;" + Profiler.GetMonoHeapSize() / (1024 * 1024)
|
|
);
|
|
var start = Time.realtimeSinceStartup;
|
|
*/
|
|
if (PrefabObject != null)
|
|
{
|
|
//删除Prefab
|
|
GameObject.DestroyImmediate(PrefabObject, true);
|
|
PrefabObject = null;
|
|
}
|
|
|
|
//删除资源
|
|
if (RendererArray != null)
|
|
{
|
|
for (int i = 0; i < RendererArray.Length; i++)
|
|
{
|
|
if (RendererArray[i] != null)
|
|
RendererArray[i].Unload();
|
|
}
|
|
}
|
|
RendererArray = null;
|
|
|
|
|
|
if (AnimArray != null)
|
|
{
|
|
for (int i = 0; i < AnimArray.Length; i++)
|
|
{
|
|
if (AnimArray[i] != null)
|
|
{
|
|
AnimArray[i].Unload();
|
|
}
|
|
}
|
|
}
|
|
AnimArray = null;
|
|
|
|
if(TimelineArray != null)
|
|
{
|
|
var cnt = TimelineArray.Length;
|
|
for (int i = 0; i < cnt; i++)
|
|
{
|
|
if (TimelineArray[i] != null)
|
|
{
|
|
TimelineArray[i].Unload();
|
|
}
|
|
}
|
|
}
|
|
TimelineArray = null;
|
|
|
|
/*
|
|
var duration = (Time.realtimeSinceStartup - start) * 1000;
|
|
Debug.LogError("UnloadFinished:" + Name + ";;;" + duration+ ";;内存:"
|
|
+ Profiler.GetTotalAllocatedMemory() / (1024 * 1024)
|
|
+ ";trm;" + Profiler.GetTotalReservedMemory() / (1024 * 1024)
|
|
+ ";turm;" + Profiler.GetTotalUnusedReservedMemory() / (1024 * 1024)
|
|
+ ";mus;" + Profiler.GetMonoUsedSize() / (1024 * 1024)
|
|
+ ";mhs;" + Profiler.GetMonoHeapSize() / (1024 * 1024)
|
|
);
|
|
*/
|
|
}
|
|
|
|
//获取预制对象
|
|
public GameObject ToPrefabGo()
|
|
{
|
|
if (PrefabObject != null)
|
|
{
|
|
/*
|
|
Debug.LogError("ToPrefabGo:" + Name + ";;内存:"
|
|
+ Profiler.GetTotalAllocatedMemory() / (1024 * 1024)
|
|
+ ";trm;" + Profiler.GetTotalReservedMemory() / (1024 * 1024)
|
|
+ ";turm;" + Profiler.GetTotalUnusedReservedMemory() / (1024 * 1024)
|
|
+ ";mus;" + Profiler.GetMonoUsedSize() / (1024 * 1024)
|
|
+ ";mhs;" + Profiler.GetMonoHeapSize() / (1024 * 1024)
|
|
);
|
|
|
|
var start = Time.realtimeSinceStartup;
|
|
*/
|
|
try
|
|
{
|
|
var root = PrefabObject.transform;
|
|
if (RendererArray != null)
|
|
{
|
|
//Debug.Log("RenderCount:" + RendererArray.Length);
|
|
for (int i = 0; i < RendererArray.Length; i++)
|
|
{
|
|
var rai = RendererArray[i];
|
|
if (rai != null )
|
|
{
|
|
|
|
var renderTrans = root;
|
|
if (!string.IsNullOrEmpty(rai.Path))
|
|
{
|
|
renderTrans = root.Find(rai.Path);
|
|
}
|
|
|
|
if (renderTrans != null)
|
|
{
|
|
rai.ToRenderer(renderTrans);
|
|
}
|
|
//rai.ToRenderer(rai.TheTransform);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (AnimArray != null)
|
|
{
|
|
//Debug.Log("AnimationCount:" + AnimArray.Length);
|
|
for (int i = 0; i < AnimArray.Length; i++)
|
|
{
|
|
var anim = AnimArray[i];
|
|
if (anim != null)
|
|
{
|
|
var animTrans = root;
|
|
if (!string.IsNullOrEmpty(anim.Path))
|
|
{
|
|
animTrans = root.Find(anim.Path);
|
|
}
|
|
|
|
if (animTrans != null)
|
|
{
|
|
anim.ToAnimation(animTrans);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (AnimtorArray != null)
|
|
{
|
|
//Debug.Log("AnimationCount:" + AnimArray.Length);
|
|
for (int i = 0; i < AnimtorArray.Length; i++)
|
|
{
|
|
var anim = AnimtorArray[i];
|
|
if (anim != null)
|
|
{
|
|
var animTrans = root;
|
|
if (!string.IsNullOrEmpty(anim.Path))
|
|
{
|
|
animTrans = root.Find(anim.Path);
|
|
}
|
|
|
|
if (animTrans != null)
|
|
{
|
|
anim.ToAnimator(animTrans);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(TimelineArray != null)
|
|
{
|
|
var length = TimelineArray.Length;
|
|
//Debug.Log("TimelineCount:" + length);
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
var timeline = TimelineArray[i];
|
|
if(timeline != null)
|
|
{
|
|
var animTrans = root;
|
|
if (!string.IsNullOrEmpty(timeline.Path))
|
|
{
|
|
animTrans = root.Find(timeline.Path);
|
|
}
|
|
|
|
if (animTrans != null)
|
|
{
|
|
timeline.ToPlayableDirector(animTrans);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//设置名字
|
|
PrefabObject.name = Name;
|
|
}
|
|
catch(System.Exception ex)
|
|
{
|
|
Debug.LogException(ex);
|
|
}
|
|
/*
|
|
var duration = (Time.realtimeSinceStartup - start) * 1000;
|
|
Debug.LogError("ToPrefabGo:" + Name + ";;;" + duration + ";;内存:"
|
|
+ Profiler.GetTotalAllocatedMemory() / (1024 * 1024)
|
|
+ ";trm;" + Profiler.GetTotalReservedMemory() / (1024 * 1024)
|
|
+ ";turm;" + Profiler.GetTotalUnusedReservedMemory() / (1024 * 1024)
|
|
+ ";mus;" + Profiler.GetMonoUsedSize() / (1024 * 1024)
|
|
+ ";mhs;" + Profiler.GetMonoHeapSize() / (1024 * 1024)
|
|
);*/
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("当前资源不是一个有效资源,清除:"+ Name);
|
|
Unload();
|
|
}
|
|
return PrefabObject;
|
|
}
|
|
#endregion
|
|
|
|
#region//编辑器时执行--打包之前数据准备用
|
|
#if UNITY_EDITOR
|
|
//从预制对象创建资源信息
|
|
public PrefabAssetData FromPrefabGo(GameObject prefabGo,bool isUseTexName, string texDir, string savePath, System.Action<AnimListScript, string, string> checkAnim)
|
|
{
|
|
var go = GameObject.Instantiate(prefabGo);
|
|
go.name = prefabGo.name;
|
|
|
|
try
|
|
{
|
|
//删除播放脚本
|
|
var playScripts = go.GetComponentsInChildren<AnimPlayScript>(true);
|
|
for (int i = 0; playScripts != null && i < playScripts.Length; ++i)
|
|
{
|
|
GameObject.DestroyImmediate(playScripts[i]);
|
|
}
|
|
|
|
//处理AnimListScript --先处理Animation的原因是,节点可能会改名,导致路径不对.
|
|
var anims = go.GetComponentsInChildren<AnimListScript>(true);
|
|
if ((anims == null || anims.Length <= 0) && savePath.Contains("Prefab"))
|
|
{
|
|
//添加一个脚本,用于存储插槽数据
|
|
go.RequireComponent<AnimListScript>();
|
|
anims = go.GetComponentsInChildren<AnimListScript>(true);
|
|
}
|
|
//删除动作资源目录,用以重新生成动作
|
|
var animPath = savePath.Substring(0, savePath.LastIndexOf("/"));
|
|
animPath = string.Format("{0}/{1}", animPath, go.name);
|
|
if (System.IO.Directory.Exists(animPath))
|
|
{
|
|
System.IO.Directory.Delete(animPath, true);
|
|
}
|
|
List<AnimationAssetData> animList = new List<AnimationAssetData>();
|
|
{
|
|
AnimationAssetData curAnim = new AnimationAssetData();
|
|
for (int i = 0; i < anims.Length; i++)
|
|
{
|
|
var animTrans = anims[i].transform;
|
|
var animator = animTrans.GetComponent<Animator>();
|
|
|
|
//这里把runtimeAnimatorContorller给去除掉,为后来的Animator检查做准备
|
|
//只要使用AnimListScript,就表明这个模型的动作播放使用Playable的方式处理
|
|
if (animator != null && animator.runtimeAnimatorController != null)
|
|
{
|
|
animator.runtimeAnimatorController = null;
|
|
}
|
|
if (checkAnim != null)
|
|
{
|
|
//检查动作,将动作进行优化后重新挂载
|
|
checkAnim(anims[i], go.name, savePath);
|
|
}
|
|
if (curAnim.FromAnimation(anims[i], true))
|
|
{
|
|
curAnim.Path = GetFindPath(go.transform, animTrans);
|
|
curAnim.TheTransform = animTrans;
|
|
//判断之前有没有这个路径名称
|
|
foreach (var a in animList)
|
|
{
|
|
if (a.TheTransform == curAnim.TheTransform)
|
|
break;
|
|
if (a.Path == curAnim.Path)
|
|
{//如果有的话,就重新命名,并把gameobject中的也重新命名
|
|
curAnim.Path = curAnim.Path + "[AAD" + i + "]";
|
|
animTrans.gameObject.name = animTrans.gameObject.name + "[AAD" + i + "]";
|
|
break;
|
|
}
|
|
}
|
|
//Debug.Log("AnimationFindPath:" + curAnim.Path);
|
|
animList.Add(curAnim);
|
|
curAnim = new AnimationAssetData();
|
|
}
|
|
}
|
|
}
|
|
//Animator --先处理Animation的原因是,节点可能会改名,导致路径不对.
|
|
var animtors = go.GetComponentsInChildren<Animator>(true);
|
|
List<AnimatorAssetData> animorList = new List<AnimatorAssetData>();
|
|
{
|
|
AnimatorAssetData curAnim = new AnimatorAssetData();
|
|
for (int i = 0; i < animtors.Length; i++)
|
|
{
|
|
var animTrans = animtors[i].transform;
|
|
if (animtors[i].runtimeAnimatorController != null)
|
|
{
|
|
if (curAnim.FromAnimator(animtors[i]))
|
|
{
|
|
curAnim.Path = GetFindPath(go.transform, animTrans);
|
|
curAnim.TheTransform = animTrans;
|
|
//判断之前有没有这个路径名称
|
|
foreach (var a in animorList)
|
|
{
|
|
if (a.TheTransform == curAnim.TheTransform)
|
|
break;
|
|
if (a.Path == curAnim.Path)
|
|
{//如果有的话,就重新命名,并把gameobject中的也重新命名
|
|
curAnim.Path = curAnim.Path + "[AAD" + i + "]";
|
|
animTrans.gameObject.name = animTrans.gameObject.name + "[AAD" + i + "]";
|
|
break;
|
|
}
|
|
}
|
|
Debug.Log("AnimatorFindPath:" + curAnim.Path);
|
|
animorList.Add(curAnim);
|
|
curAnim = new AnimatorAssetData();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//处理Renderer
|
|
var renders = go.GetComponentsInChildren<Renderer>(true);
|
|
List<RenderAssetData> renderList = new List<RenderAssetData>();
|
|
{
|
|
RenderAssetData curRender = new RenderAssetData();
|
|
for (int i = 0; i < renders.Length; i++)
|
|
{
|
|
if (curRender.FromRenderer(renders[i], true, isUseTexName, texDir))
|
|
{
|
|
curRender.Path = GetFindPath(go.transform, renders[i].transform);
|
|
curRender.TheTransform = renders[i].transform;
|
|
//判断之前有没有这个路径名称
|
|
foreach (var r in renderList)
|
|
{
|
|
if (r.TheTransform == curRender.TheTransform)
|
|
break;
|
|
if (r.Path == curRender.Path)
|
|
{//如果有的话,就重新命名,并把gameobject中的也重新命名
|
|
curRender.Path = curRender.Path + "[PAD" + i + "]";
|
|
renders[i].gameObject.name = renders[i].gameObject.name + "[PAD" + i + "]";
|
|
break;
|
|
}
|
|
}
|
|
//Debug.Log("RenderFindPath:" + curRender.Path);
|
|
renderList.Add(curRender);
|
|
curRender = new RenderAssetData();
|
|
}
|
|
}
|
|
}
|
|
|
|
//处理Timeline
|
|
var playableDirectors = go.GetComponentsInChildren<PlayableDirector>(true);
|
|
List<TimelineAssetData> timelineAssetDataList = new List<TimelineAssetData>();
|
|
HashSet<string> timelinePaths = new HashSet<string>();
|
|
{
|
|
TimelineAssetData curTimeline = new TimelineAssetData();
|
|
for (int i = 0; i < playableDirectors.Length; i++)
|
|
{
|
|
if (curTimeline.FromPlayableDirector(playableDirectors[i]))
|
|
{
|
|
var path = GetFindPath(go.transform, playableDirectors[i].transform);
|
|
if (timelinePaths.Contains(path))
|
|
{
|
|
path = path + "[AAD" + i + "]";
|
|
playableDirectors[i].gameObject.name = path;
|
|
}
|
|
timelinePaths.Add(path);
|
|
curTimeline.Path = path;
|
|
//Debug.Log("TimelinePathFindPath:" + path);
|
|
timelineAssetDataList.Add(curTimeline);
|
|
curTimeline = new TimelineAssetData();
|
|
}
|
|
}
|
|
}
|
|
|
|
//处理粒子特效,隐藏会报错的粒子
|
|
var particles = go.GetComponentsInChildren<ParticleSystem>(true);
|
|
for (int i = 0; i < particles.Length; ++i)
|
|
{
|
|
if (particles[i].shape.enabled && particles[i].shape.shapeType == ParticleSystemShapeType.Mesh && particles[i].shape.mesh == null)
|
|
{
|
|
//隐藏报错粒子
|
|
particles[i].gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
//赋值
|
|
AnimtorArray = animorList.ToArray();
|
|
AnimArray = animList.ToArray();
|
|
RendererArray = renderList.ToArray();
|
|
TimelineArray = timelineAssetDataList.ToArray();
|
|
Name = go.name;
|
|
|
|
//需要先把go保存成预制
|
|
string saveAssetPath = savePath;
|
|
//var prefabGoIns = UnityEditor.PrefabUtility.InstantiatePrefab(prefabGo) as GameObject;
|
|
if(UnityEditor.PrefabUtility.SaveAsPrefabAsset(go, saveAssetPath) == null)
|
|
{
|
|
//保存失败,抛出异常
|
|
throw new System.Exception(string.Format("保存Prefab预制失败 go = {0}", go.name));
|
|
}
|
|
UnityEditor.AssetDatabase.ImportAsset(saveAssetPath);
|
|
DestroyImmediate(go);
|
|
PrefabObject = UnityEditor.AssetDatabase.LoadAssetAtPath(saveAssetPath, typeof(GameObject)) as GameObject;
|
|
}
|
|
catch(System.Exception ex)
|
|
{
|
|
DestroyImmediate(go);
|
|
throw ex;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
//获取查找路径
|
|
private string GetFindPath(Transform root, Transform curr)
|
|
{
|
|
string result = string.Empty;
|
|
List<string> nameList = new List<string>();
|
|
while (curr != null && curr != root)
|
|
{
|
|
nameList.Add(curr.name);
|
|
curr = curr.parent;
|
|
}
|
|
if (nameList.Count > 0)
|
|
{
|
|
nameList.Reverse();
|
|
for (int i = 0; i < nameList.Count; i++)
|
|
{
|
|
result += "/" + nameList[i];
|
|
}
|
|
result = result.Substring(1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|