最近写了一个Unity优化工具,主要是搜索某一个文件夹中所有的场景和预设。如果是场景的话,就遍历场景中的所有对象,观察对象身上是否绑定了AudioListener组件,如果有的话移除该组件并保存场景。如果是预设的话,就遍历预设中的所有对象,观察预设中的对象是否绑定AudioListener组件,如果有的话移除该组件。

脚本如下:

增加:过滤非指定资源的执行(动画代码修改:)

using ML_Animation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;class BlendAnimation : EditorWindow
{public static string[] saveLimitKey = new string[] {//"Bip001 Footsteps","Bip001 Pelvis","Bip001 Spine","Bip001 L Thigh","Bip001 R Thigh","Bip001 L Calf", "Bip001 R Calf",//"Bip001 L Foot", "Bip001 R Foot",//"Bip001 L Toe0","Bip001 R Toe0", "Bip001 L Toe0Nub","Bip001 R Toe0Nub",//"Bip001 Spine1","Bone017","Bone021",//"Bip001 Prop1","Dummy001"};private static StringBuilder strBuilder;private static OptimizeAnimationClipProperty optAnimProperty = null;[MenuItem("Assets/优化/动画/选中AnimationClip-ModifyHeroCameraFOV", true, 0)]public static bool AnimationAddProperty_(){AnimationClip clip = Selection.activeObject as AnimationClip;if (clip == null)return false;elsereturn true;}[MenuItem("Assets/优化/动画/选中AnimationClip-ModifyHeroCameraFOV", false, 0)]public static void AnimationAddProperty(){UnityEngine.Object[] objs = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.DeepAssets);int count = 0;foreach (UnityEngine.Object obj in objs){++count;EditorUtility.DisplayProgressBar("正在修改动画,请勿操作Unity!!!", count + "/" + objs.Length, count * 1.0f / objs.Length);AnimationClip clip = obj as AnimationClip;EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);for (int i = 0; i < curveBindings.Length; i++){EditorCurveBinding curveBind = curveBindings[i];if (curveBind.type == typeof(Camera)){AnimationCurve animCurve = AnimationUtility.GetEditorCurve(clip, curveBind);AnimationUtility.SetEditorCurve(clip, curveBind, null);curveBind.path = "cam/m_3DHeroCamera";AnimationUtility.SetEditorCurve(clip, curveBind, animCurve);AnimationCurve addCurve = new AnimationCurve();addCurve.AddKey(0, 0);addCurve.AddKey(clip.length, 0);clip.SetCurve("cam/m_3DHeroCamera", typeof(Transform), "m_LocalRotation.x", addCurve);clip.SetCurve("cam/m_3DHeroCamera", typeof(Transform), "m_LocalRotation.y", addCurve);clip.SetCurve("cam/m_3DHeroCamera", typeof(Transform), "m_LocalRotation.z", addCurve);}}}AssetDatabase.Refresh();EditorUtility.ClearProgressBar();}[MenuItem("Assets/优化/动画/选中AnimationClip-优化动画", false, 1)]public static void AnimOptimizeTrilogy(){int count = 0;UnityEngine.Object[] objs = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.DeepAssets);foreach (UnityEngine.Object o in objs){count++;EditorUtility.DisplayProgressBar("优化动画三部曲...", AssetDatabase.GetAssetPath(o), count * 1.0f / objs.Length);AnimationClip clip = RemoveAnimationSameKeyframe(o as AnimationClip);ExecuteOptimaze_(clip);ReduceAnimationCurve(ref clip);}AssetDatabase.SaveAssets();EditorUtility.ClearProgressBar();}[MenuItem("Assets/优化/动画/选中Prefab-优化动画", false, 2)]public static void OptimizeAnimation(){strBuilder = new StringBuilder();optAnimProperty = new OptimizeAnimationClipProperty();UnityEngine.Object[] objs = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.DeepAssets);for (int i = 0; i < objs.Length; i++){EditorUtility.DisplayProgressBar("优化动画三部曲...", AssetDatabase.GetAssetPath(objs[i]), i * 1.0f / objs.Length);string path = AssetDatabase.GetAssetPath(objs[i]);string suffix = Path.GetExtension(path);if (suffix == ".prefab"){optAnimProperty.AllPrefabNum++;OptimizeAnimationClips(path);}}PrintLog();AssetDatabase.SaveAssets();EditorUtility.ClearProgressBar();}public static void OptimizeAnimationClips(string path){bool isModifyAnimClip = false;List<string> optAnims = new List<string>();string[] depends = AssetDatabase.GetDependencies(path);for (int i = 0; i < depends.Length; i++){if (Path.GetExtension(depends[i]) == ".anim"){if (optAnimProperty.hadOperation.Contains(depends[i])){continue;}else{optAnimProperty.hadOperation.Add(depends[i]);optAnims.Add(depends[i]);}AnimationClip clip = AssetDatabase.LoadAssetAtPath(depends[i], typeof(AnimationClip)) as AnimationClip;if (clip == null){Debug.LogError(depends[i] + " is not Exist");continue;}clip = RemoveAnimationSameKeyframe(clip);ExecuteOptimaze_(clip);ReduceAnimationCurve(ref clip);optAnimProperty.ModifyAnimNum++;isModifyAnimClip = true;}}if (optAnims.Count > 0){optAnimProperty.dicLog.Add(path, optAnims);}if (isModifyAnimClip)optAnimProperty.ModifyPrefabNum++;}//[MenuItem("Assets/优化/动画/精简动画小数点")]private static void AnimationDataOptimaze(){int number = 0;DateTime time = DateTime.Now;foreach (UnityEngine.Object o in Selection.GetFiltered(typeof(AnimationClip), SelectionMode.DeepAssets)){number++;ExecuteOptimaze(Instantiate(o) as AnimationClip, AssetDatabase.GetAssetPath(o));}AssetDatabase.SaveAssets();Debug.Log("一共压缩了" + number + "个动画文件!");Debug.Log("耗时:" + (DateTime.Now - time).TotalMilliseconds / 1000 + "秒.");}//[MenuItem("Assets/优化/动画/优化动画小数点,不对动画重新创建")]public static void OptimazeAnimationDecimalPoint(){int count = 0;UnityEngine.Object[] objs = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.DeepAssets);foreach (UnityEngine.Object o in objs){count++;EditorUtility.DisplayProgressBar("优化动画小数点,不重新创建动画", count + "/" + objs.Length, count * 1.0f / objs.Length);ExecuteOptimaze_(o as AnimationClip);}EditorUtility.ClearProgressBar();}private static AnimationClip ExecuteOptimaze_(AnimationClip clip){EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);for (int i = 0; i < curveBindings.Length; i++){AnimationCurve animCurve = AnimationUtility.GetEditorCurve(clip, curveBindings[i]);var keyFrames = animCurve.keys;for (int j = 0; j < keyFrames.Length; j++){var key = keyFrames[j];key.value = float.Parse(key.value.ToString("f4"));key.inTangent = float.Parse(key.inTangent.ToString("f4"));key.outTangent = float.Parse(key.outTangent.ToString("f4"));keyFrames[j] = key;}animCurve.keys = keyFrames;AnimationUtility.SetEditorCurve(clip, curveBindings[i], animCurve);}//AssetDatabase.SaveAssets();return clip;}private static AnimationClip ExecuteOptimaze(AnimationClip clip, string clipName){EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);AnimationClipCurveData[] curves = new AnimationClipCurveData[curveBindings.Length];for (int index = 0; index < curves.Length; ++index){curves[index] = new AnimationClipCurveData(curveBindings[index]);curves[index].curve = AnimationUtility.GetEditorCurve(clip, curveBindings[index]);}foreach (AnimationClipCurveData curveDate in curves){var keyFrames = curveDate.curve.keys;for (int i = 0; i < keyFrames.Length; i++){var key = keyFrames[i];key.value = float.Parse(key.value.ToString("f4"));key.inTangent = float.Parse(key.inTangent.ToString("f4"));key.outTangent = float.Parse(key.outTangent.ToString("f4"));keyFrames[i] = key;}curveDate.curve.keys = keyFrames;clip.SetCurve(curveDate.path, curveDate.type, curveDate.propertyName, curveDate.curve);}AssetDatabase.CreateAsset(clip, clipName);return clip;}private static void ControlAnimationMetaFile(string metaPath, bool bRead){if (bRead){strBuilder = new StringBuilder();FileStream fs = new FileStream(metaPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);StreamReader sr = new StreamReader(fs, System.Text.Encoding.Default);while (!sr.EndOfStream){strBuilder.AppendLine(sr.ReadLine());}sr.Dispose();}else{if (File.Exists(metaPath))File.Delete(metaPath);StreamWriter sw = new StreamWriter(metaPath);sw.Write(strBuilder);sw.Dispose();}}//[MenuItem("Assets/优化/动画/移除相同关键帧")]public static void AnimationRemoveKeyFrame(){UnityEngine.Object[] objs = Selection.objects;for (int i = 0; i < objs.Length; i++){UnityEngine.Object obj = objs[i];if (obj.GetType() == typeof(AnimationClip)){EditorUtility.DisplayProgressBar("移除动画相同关键帧...", AssetDatabase.GetAssetPath(obj), i * 1.0f / objs.Length);RemoveAnimationSameKeyframe(obj as AnimationClip);}}AssetDatabase.SaveAssets();EditorUtility.ClearProgressBar();}public static AnimationClip RemoveAnimationSameKeyframe(AnimationClip clip){string path = AssetDatabase.GetAssetPath(clip);EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);foreach (var curve in curveBindings){AnimationCurve animCurve = AnimationUtility.GetEditorCurve(clip, curve);if (animCurve.keys.Length > 1 && !curve.isPPtrCurve){Keyframe cntKeyframe = animCurve.keys[0];List<Keyframe> m_Keyframes = new List<Keyframe>();m_Keyframes.Add(cntKeyframe);int sameIndex = 0;for (int i = 1; i < animCurve.keys.Length; ++i){Keyframe item = animCurve.keys[i];m_Keyframes.Add(item);if (Mathf.Abs(item.value - cntKeyframe.value) > 0.00001f|| i == animCurve.keys.Length - 1|| Math.Abs(item.inTangent - cntKeyframe.inTangent) > 0.00001f|| Math.Abs(item.outTangent - cntKeyframe.outTangent) > 0.00001f|| item.tangentMode != cntKeyframe.tangentMode){sameIndex = 0;}else{sameIndex += 1;}cntKeyframe = item;if (sameIndex > 1){m_Keyframes.RemoveAt(m_Keyframes.Count - 2);}}animCurve.keys = m_Keyframes.ToArray();AnimationUtility.SetEditorCurve(clip, curve, animCurve);}}return clip;}[MenuItem("Assets/优化/动画/根据FBX(原始资源)生成混合动画", false, 3)]public static void AnimationOptimization(){List<AnimationClip> animClips = new List<AnimationClip>();UnityEngine.Object[] animObjs = Selection.objects;for (int i = 0; i < animObjs.Length; i++){AnimationClip anim = animObjs[i] as AnimationClip;if (anim){animClips.Add(anim);}}UnityEngine.Object[] objs = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.DeepAssets);for (int i = 0; i < objs.Length; i++){string path = AssetDatabase.GetAssetPath(objs[i]);string suffix = Path.GetExtension(path).ToLower();if (suffix == ".fbx"){GetAnimationClip(path, animClips);}}}public static void GetAnimationClip(string fbxPath, List<AnimationClip> animClips){UnityEngine.Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(fbxPath);AnimationClip idleClip = null;for (int i = 0; i < objs.Length; i++){idleClip = objs[i] as AnimationClip;if (idleClip != null && !idleClip.name.ToLower().Contains("action")){if (animClips.Count > 0){if (animClips.Contains(idleClip))CreateBlendAnimation(idleClip, fbxPath);elsecontinue;}else{CreateBlendAnimation(idleClip, fbxPath);}}elsecontinue;}}public static void CreateBlendAnimation(AnimationClip idleClip, string fbxPath){List<AnimationClipCurveData> lstAnimClipCurve = new List<AnimationClipCurveData>();List<AnimationClipCurveData> lstAnimCompressClipCurve = new List<AnimationClipCurveData>();List<AnimationClipCurveData> lstAnimBlendClipCurve = new List<AnimationClipCurveData>();//AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(fbxPath);ModelImporter importer = AssetImporter.GetAtPath(fbxPath) as ModelImporter;if (idleClip == null || importer == null)return;if (importer.animationCompression != ModelImporterAnimationCompression.Off){importer.animationCompression = ModelImporterAnimationCompression.Off;importer.SaveAndReimport();}AnimationClip blendAnimClip = UnityEngine.Object.Instantiate(idleClip);blendAnimClip.ClearCurves();lstAnimClipCurve = RecordAnimationCurve(idleClip);importer.animationCompression = ModelImporterAnimationCompression.KeyframeReduction;importer.SaveAndReimport();lstAnimCompressClipCurve = RecordAnimationCurve(idleClip);for (int i = 0; i < lstAnimClipCurve.Count; i++){string[] splitPath = lstAnimClipCurve[i].path.Split('/');string keys = splitPath[splitPath.Length - 1];if (saveLimitKey.ToList().Contains(keys)){lstAnimBlendClipCurve.Add(lstAnimClipCurve[i]);}else{lstAnimBlendClipCurve.Add(lstAnimCompressClipCurve[i]);}}for (int i = 0; i < lstAnimBlendClipCurve.Count; i++){AnimationClipCurveData data = lstAnimBlendClipCurve[i];blendAnimClip.SetCurve(data.path, data.type, data.propertyName, data.curve);}ReduceAnimationCurve(ref blendAnimClip);string path2 = string.Format("{0}/{1}.anim", Path.GetDirectoryName(fbxPath), idleClip.name);SaveAnim(blendAnimClip, path2);}/// <summary>/// 记录AnimationClip的曲线/// </summary>/// <param name="clip"></param>/// <returns></returns>public static List<AnimationClipCurveData> RecordAnimationCurve(AnimationClip clip){EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);List<AnimationClipCurveData> curveDatas = new List<AnimationClipCurveData>();for (int i = 0; i < curveBindings.Length; i++){AnimationCurve animCurve = AnimationUtility.GetEditorCurve(clip, curveBindings[i]);AnimationClipCurveData curveData = new AnimationClipCurveData(curveBindings[i]);curveData.curve = animCurve;curveDatas.Add(curveData);}return curveDatas;}/// <summary>/// 移除动画不必要的曲线/// </summary>/// <param name="clip"></param>public static void ReduceAnimationCurve(ref AnimationClip clip){SerializedObject serializedObject = new SerializedObject(clip);serializedObject.FindProperty("m_EditorCurves").arraySize = 0;serializedObject.FindProperty("m_EulerEditorCurves").arraySize = 0;//serializedObject.FindProperty("m_FloatCurves").arraySize = 0;serializedObject.ApplyModifiedProperties();}public static void SaveAnim(AnimationClip clip, string clipName){if (!Directory.Exists(Path.GetDirectoryName(clipName))){Directory.CreateDirectory(Path.GetDirectoryName(clipName));}//clip.legacy = true;//clip.wrapMode = WrapMode.Loop;AssetDatabase.CreateAsset(clip, clipName);AssetDatabase.Refresh();}private static void PrintLog(){string path = Application.dataPath.Replace("Assets", "ProfilerData/AnimOptimize.txt");Debug.Log(path);if (!Directory.Exists(Path.GetDirectoryName(path))){Directory.CreateDirectory(Path.GetDirectoryName(path));}if (File.Exists(path))File.Delete(path);foreach (var item in optAnimProperty.dicLog){string labelName = string.Empty;for (int i = 0; i < item.Value.Count; i++){labelName += item.Value[i] + ",";}strBuilder.Append(string.Format("{0}:{1}\n", item.Key, labelName));}strBuilder.Append(string.Format("检索Prefab数量:{0}\n需要修改的Prefab数量:{1},占总量的:{2}%\n修改的Animation数量:{3}", optAnimProperty.AllPrefabNum, optAnimProperty.ModifyPrefabNum, optAnimProperty.ModifyPrefabNum * 1.0f / optAnimProperty.AllPrefabNum * 100, optAnimProperty.ModifyAnimNum));using (StreamWriter sw = new StreamWriter(path)){sw.Write(strBuilder);sw.Dispose();}}
}public class OptimizeAnimationClipProperty
{public int AllPrefabNum;public int ModifyAnimNum;public int ModifyPrefabNum;public Dictionary<string, List<string>> dicLog = null;public List<string> hadOperation = null;public OptimizeAnimationClipProperty(){dicLog = new Dictionary<string, List<string>>();hadOperation = new List<string>();}
}
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;public class SceneOptimize : Editor {#region 场景优化//某一文件夹中的所有场景的路径,复制的场景路径用于把所有场景都复制到另一个文件夹中public static List<string> optimizedScenePaths;//某一文件夹中的所有场景的路径public static List<string> optimizedOriginalScenePaths;[MenuItem("Tools/场景优化")]public static void CopyAndOptimizeScenes(){//复制的场景路径optimizedScenePaths = new List<string>();//原来的场景路径optimizedOriginalScenePaths = new List<string>();//项目的路径,eg:D:/Project/Test/Assetsstring headPath = Application.dataPath;//Debug.Log(headPath);//Debug.Log(headPath.IndexOf("Assets"));//eg:D:/Project/Test/headPath = headPath.Substring(0, headPath.IndexOf("Assets"));Debug.Log(headPath);try{//复制场景到另一个文件夹中//CopyAllScenes("Assets/Level", "Assets/Level_optimized", headPath);//获取某一文件夹中所有场景的Path信息AddRootSourcePathToList("Assets/Level", headPath, "Scene", ref optimizedOriginalScenePaths);}catch (System.Exception e){PlayerPrefs.SetInt("ModifySaving", 0);Debug.LogError(e);}//遍历出所有场景的路径for (int i = 0; i < optimizedOriginalScenePaths.Count; i++){PlayerPrefs.SetInt("ModifySaving", 0);//显示遍历场景时候的进度条EditorUtility.DisplayCancelableProgressBar("Scene Optimizing Bar", "Save And Optimize Scenes" + i + "/" + optimizedOriginalScenePaths.Count, (float)i / optimizedOriginalScenePaths.Count);try{Debug.Log(optimizedOriginalScenePaths[i]);//获取到场景的完整路径string tempPath = headPath + "Assets/Level/";Debug.Log("tempPath :" + tempPath);//只获取场景的名字(eg:Main.unity,Main场景的全称)string tempScene = optimizedOriginalScenePaths[i].Substring(tempPath.Length);Debug.Log("tempScene:" + tempScene);//增加判断条件,对于不需要做修改的场景if(tempScene == "Main.unity"){Debug.Log("Continue");continue;}//打开场景EditorSceneManager.OpenScene(optimizedOriginalScenePaths[i], OpenSceneMode.Single);//开始优化AudioListenerOptimize();PlayerPrefs.SetInt("ModifySaving", 1);//保存修改之后的场景EditorSceneManager.SaveScene(SceneManager.GetActiveScene());}catch (System.Exception e){PlayerPrefs.SetInt("ModifySaving", 0);//如果发生错误,要关闭加载时候显示的滚动条EditorUtility.ClearProgressBar();Debug.Log(e);}}//加载完毕,关闭滚动条EditorUtility.ClearProgressBar();Debug.Log("finished");PlayerPrefs.SetInt("ModifySaving", 0);}//对于要修改的内容public static void AudioListenerOptimize(){//获取一个场景中所有的绑定了AudioListener对象AudioListener[] audios = FindObjectsOfType<AudioListener>();for (int i = 0; i < audios.Length; i++){if (audios[i] is AudioListener){//移除对象身上的AudioListener组件DestroyImmediate(audios[i].GetComponent<AudioListener>(),true);}}}/// <summary>/// 复制场景到另一个文件夹中/// </summary>/// <param name="rootPath"></param>/// <param name="targetPath"></param>/// <param name="headPath"></param>public static void CopyAllScenes(string rootPath, string targetPath, string headPath){if (Directory.Exists(rootPath)){string[] guids;guids = AssetDatabase.FindAssets("t:Scene", new[] { rootPath });foreach (string guid in guids){Debug.Log("guid: " + guid);string source = AssetDatabase.GUIDToAssetPath(guid);Debug.Log("source: " + source);string dest = source;Debug.Log("dest: " + dest);for (int i = 0; i < CountSubString("Level", "/") + 2; i++){Debug.Log("dest.IndexOf: " + dest.IndexOf("/"));dest = dest.Substring(dest.IndexOf("/") + 1);}dest = "/" + dest;Debug.Log("dest: " + dest);dest = targetPath + dest;Debug.Log("dest: " + dest);CopySingleScene(source, dest, headPath);}}else{Debug.Log("No source path");}}public static void CopySingleScene(string source, string dest, string headPath){source = headPath + source;dest = headPath + dest;string destDirectory = dest.Substring(0, dest.LastIndexOf("/"));if (!Directory.Exists(destDirectory)){Directory.CreateDirectory(destDirectory);}dest = dest.Substring(0, dest.LastIndexOf(".")) + "_Optimized.unity";File.Copy(source, dest, true);optimizedScenePaths.Add(dest);}public static int CountSubString(string targetString, string subString){int p = 0;while (targetString.Contains(subString)){p++;targetString = targetString.Substring(targetString.IndexOf(subString) + 1);}Debug.Log("p:" + p);return p;}#endregion/// <summary>/// 根据在固定文件夹中的路径,根据类型(type)搜索该文件夹中的所符合的对象,然后把这些对象的路径添加到array中/// </summary>/// <param name="rootPath">目标文件路径(eg:Assets/Scenes)</param>/// <param name="headPath">项目路径(eg:D:Project/Test/)</param>/// <param name="searchType">搜索类型(Scene(搜索的是场景),Prefab(搜多的是预设))</param>/// <param name="array"></param>public static void AddRootSourcePathToList(string rootPath, string headPath, string searchType, ref List<string> array){if (Directory.Exists(rootPath)){string[] guids;//搜索guids = AssetDatabase.FindAssets("t:" + searchType, new[] { rootPath });foreach (string guid in guids){string source = AssetDatabase.GUIDToAssetPath(guid);//path:(D:Project/Test/Assets/Scenes/Main.unity)string path = headPath + source;array.Add(path);}}else{Debug.LogError("No Find Source Path");}}#region Prefab优化public static List<string> optimizePrefabsList;[MenuItem("Tools/预设优化")]public static void OptimizePrefabs(){optimizePrefabsList = new List<string>();string headPath = Application.dataPath;headPath = headPath.Substring(0, headPath.IndexOf("Assets"));Debug.Log(headPath);try{AddRootSourcePathToList("Assets/CurPrefabs", headPath,"Prefab",ref optimizePrefabsList);}catch (System.Exception e){Debug.LogError(e);}Debug.Log("optimizePrefabsList:" + optimizePrefabsList.Count);for (int i = 0; i < optimizePrefabsList.Count; i++){Debug.Log(optimizePrefabsList[i]);EditorUtility.DisplayCancelableProgressBar("Prefabs Optimizing Bar", "Save And Optimize Prefabs" + i + "/" + optimizePrefabsList.Count, (float)i / optimizePrefabsList.Count);//tempPath(eg:Assets/Prefabs/Cube.prefab)string tempPath = optimizePrefabsList[i].Substring(headPath.Length);//根据路径找到对象GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(tempPath);//Debug.Log(tempPath);//Debug.Log(prefab.name);OptimizePrefabRemoveAudioListener(prefab);}EditorUtility.ClearProgressBar();Debug.Log("finished");}public static void OptimizePrefabRemoveAudioListener(GameObject prefab){AudioListener[] audios = prefab.GetComponentsInChildren<AudioListener>();Debug.Log(audios.Length);for (int i = 0; i < audios.Length; i++){Debug.Log(audios[i].name);DestroyImmediate(audios[i].GetComponent<AudioListener>(),true);}}#endregion
}

下面分析Editor中的问题:

1,Unity中的Editor的基础篇:

Unity Editor 基础篇(十一):MenuItem属性_鳄鱼泪的博客-CSDN博客_menuitem属性

2,Unity编辑器不用实例化Prefab获取,删除,更新组件:

Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五) | 雨松MOMO程序研究院

3,根据对象名字,标签或者类型查找某一个文件夹中所有对象的路径

AssetDatabase-FindAssets的解析:AssetDatabase-FindAssets_京畿小李_新浪博客

4,游戏运行的时候对场景中对象的修改,通过代码控制保存的方法

[Unity]保存运行时对Scene中GameObject属性的修改_tlrainty的专栏-CSDN博客_unity运行时保存场景文件

5,脚本自动定位选择Hierarchy或Project下的对象

[UnityEditor基础]脚本自动定位选择Hierarchy或Project下的对象_鳄鱼泪的博客-CSDN博客

6,Unity编辑器扩展(自动保存当前打开的场景)

https://blog.csdn.net/crazyape/article/details/78803549

7,移除某个对象身上绑定的组件:

DestroyImmediate(audios[i].GetComponent<AudioListener>());

为了安全起见,我们移除的时候要添加一个参数:

对于Prefab身上的组件我们不能用DestroyImmediate(audios[i].GetComponent<AudioListener>());

方法,会报错。用DestroyImmediate(audios[i].GetComponent<AudioListener>(), true);方法

Unity编辑器(Editor)的问题全解以及使用相关推荐

  1. Unity:编辑器Editor常用命令

    因为Unity的编辑器一些方法,是项目中不常用到的,为了避免以后忘记 今天特意抽时间把最近使用和一些不常用的Editor用到的方法都列举出来 有些写了注释,后面就懒得写注释了,不过看预览效果,都能找得 ...

  2. Unity编辑器AssetDatabase函数API用法中文详解-Chinar教程

    Chinar blog :www.chinar.xin AssetDatabase 函数用法汇总 本文提供全流程,中文翻译 助力快速理解 AssetDatabase API 用法 为初学者节省宝贵的时 ...

  3. Unity 编辑器开发实战【Custom Editor】- AudioDatabase Editor 音频库编辑器

    本文实现一个音频库的自定义编辑器,效果如图: 开始实现之前,首先简单介绍该音频库模块,音频库类Audio Database继承自Scriptable Object类,是一个可配置的资源文件: 包含的内 ...

  4. Unity编辑器Unity Editor基础(一)

    Unity编辑器Unity Editor基础(一)               关于 Unity 内置属性可以从到官方文档中查询,本篇文章只介绍一些常用的内置属性,如下图所示: 接下来进行项目设置,创 ...

  5. 七日杀unity报错_七日杀游戏闪退及各种游戏报错解决攻略全解

    七日杀是一款人称的丧尸生存类游戏,现在有非常多的游戏都是丧尸生存题材的,但是要找到比较精品的游戏,我还是推荐大家玩这款,这里跟大家分享一下七日杀游戏闪退及各种游戏报错解决攻略全解,大家如果有遇到问题可 ...

  6. Unity编辑器类中文教程汇总-Chinar(一个默默无闻分享知识的人)

    Chinar blog :www.chinar.xin Unity 编辑器资料汇总 本文提供全流程,中文翻译 统计我所有编辑器 Unity Editor 教程资料,便于查询学习 为初学者节省宝贵的时间 ...

  7. 安卓数据读写全解:SharedPreferences公共数据的读写,SQLiteDatabase数据库,mysql数据库

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓数据存储和读取全解. SharedPreferences读写共享数据 //写入共享数据public void set_data(Context c ...

  8. 64位 Fedora 11 硬盘安装 配置全解

    64位 Fedora 11 硬盘安装 配置全解 转贴: http://www.ubuntuchina.com/viewthread.php?tid=7428&extra=page%3D1 硬盘 ...

  9. 《Unity 3D 游戏开发技术详解与典型案例》——1.1节Unity 3D基础知识概览

    本节书摘来自异步社区<Unity 3D 游戏开发技术详解与典型案例>一书中的第1章,第1.1节Unity 3D基础知识概览,作者 吴亚峰 , 于复兴,更多章节内容可以访问云栖社区" ...

  10. 【Unity编辑器扩展】(二)PSD转UGUI Prefab, 图层解析和碎图导出

    书接上回:[Unity编辑器扩展](一)PSD转UGUI Prefab, Aspose.PSD和Harmony库的使用_TopGames的博客-CSDN博客 工具使用预览: 工具目标: 1. 实现将p ...

最新文章

  1. point-to-point(点对点) 网口
  2. 兴趣点推荐代码_推荐系统模型阿里用户兴趣模型(附完整代码)
  3. 微软或允许 Android 应用运行于 Windows 和 WP
  4. jpa 原生sql 查询返回一个实体_spring data系列之jpa
  5. 各位数字之和——一个神奇的结论
  6. Red Hat 发布新 logo:“没有脸了”
  7. SSH三大框架的整合(实例)
  8. 使用Word批量删除换行和空白行
  9. Ubuntu16.04关闭笔记本触摸板
  10. 框架协议、合同的下达
  11. iphone微信用计算机隐身,苹果手机使用微信不能换行?原来隐藏键在这,网友:冷知识...
  12. 使用阿里云镜像加速器
  13. Orcad与PADS交互设计技巧一
  14. 病毒木马查杀实战第013篇:一个基于.NET的“敲竹杠”病毒研究
  15. 使用telnet命令,报错:无法打开主机的连接在端口23连接失败
  16. c/c++ 秦九昭算法
  17. go 服务接入短信验证码功能(对接阿里云平台)
  18. 关于JS的20多个小技巧
  19. 出海现金贷还有未来吗?
  20. 【个人网站搭建】GitHub pages+hexo框架下为next主题添加菜单分类页面

热门文章

  1. Kuma是什么? Kuma1.0 GA 发布了包含70+新特性和改进
  2. 港股相关交易规则与业务知识
  3. SSH基础:ssh首次连接的公钥认证
  4. vue-symbol
  5. ASEMI肖特基二极管1N5819压降是什么意思
  6. boost | 线程与并发(一)atomic
  7. springBoot-Quartz 定时任务
  8. 使用JavaScript 实现简单的移动和缓动的动画效果
  9. 三消游戏算法图文详解
  10. 怎么在计算机上面掉出CMD,电脑没有cmd怎么办