https://www.assetstore.unity3d.com/en/#!/content/11134
本文参考Fast Platform Switch,开发所使用的Unity版本为5.3.4f1。
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
public class FastBuildPlayerWindow : EditorWindow
{
private EditorWindow buildPlayerWindow;
void Awake()
{
var unityEditor = Assembly.LoadFile(EditorApplication.applicationContentsPath + "/Managed/UnityEditor.dll");
var buildPlayerWindowType = unityEditor.GetType("UnityEditor.BuildPlayerWindow");
var array = Resources.FindObjectsOfTypeAll(buildPlayerWindowType);
var noBuildPlayerWindow = array == null || array.Length <= 0;
buildPlayerWindow = GetWindow(buildPlayerWindowType, true);
minSize = buildPlayerWindow.minSize;
maxSize = buildPlayerWindow.maxSize;
position = buildPlayerWindow.position;
titleContent = buildPlayerWindow.titleContent;
if(noBuildPlayerWindow)
buildPlayerWindow.Close();
}
void OnDestroy()
{
}
static BuildTarget GetSelectedBuildTarget()
{
switch (EditorUserBuildSettings.selectedBuildTargetGroup)
{
case BuildTargetGroup.WebPlayer:
if(EditorUserBuildSettings.webPlayerStreamed)
return BuildTarget.WebPlayerStreamed;
return BuildTarget.WebPlayer;
case BuildTargetGroup.Standalone:
return EditorUserBuildSettings.selectedStandaloneTarget;
case BuildTargetGroup.iOS:
return BuildTarget.iOS;
case BuildTargetGroup.Android:
return BuildTarget.Android;
case BuildTargetGroup.tvOS:
return BuildTarget.tvOS;
case BuildTargetGroup.Tizen:
return BuildTarget.Tizen;
case BuildTargetGroup.XBOX360:
return BuildTarget.XBOX360;
case BuildTargetGroup.XboxOne:
return BuildTarget.XboxOne;
case BuildTargetGroup.PS3:
return BuildTarget.PS3;
case BuildTargetGroup.PSP2:
return BuildTarget.PSP2;
case BuildTargetGroup.PS4:
return BuildTarget.PS4;
case BuildTargetGroup.WSA:
return BuildTarget.WSAPlayer;
case BuildTargetGroup.WebGL:
return BuildTarget.WebGL;
case BuildTargetGroup.SamsungTV:
return BuildTarget.SamsungTV;
default:
return EditorUserBuildSettings.activeBuildTarget;
}
}
static void DirectoryMerge(string sourceDirName, string destDirName)
{
if (!Directory.Exists(sourceDirName))
return;
const string title = "Hold On";
string info = "Delete files from dest not in source";
float progress = 0;
if (Directory.Exists(destDirName))
{
var destFiles = Directory.GetFiles(destDirName, "*.*", SearchOption.AllDirectories);
foreach (var file in destFiles)
{
if (!File.Exists(sourceDirName + file.Remove(0, destDirName.Length)))
File.Delete(file);
progress += 1.0f / destFiles.Length;
EditorUtility.DisplayProgressBar(title, info, progress);
}
}
info = "Copy changed and new files from source to dest";
progress = 0;
// Then copy changed and new files from source to dest
var sourceFiles = Directory.GetFiles(sourceDirName, "*.*", SearchOption.AllDirectories);
foreach (var file in sourceFiles)
{
var destFile = destDirName + file.Remove(0, sourceDirName.Length);
progress += 1.0f / sourceFiles.Length;
EditorUtility.DisplayProgressBar(title, info, progress);
if (File.Exists(destFile) && File.GetLastWriteTimeUtc(file) == File.GetLastWriteTimeUtc(destFile) && new FileInfo(file).Length == new FileInfo(destFile).Length)
continue;
Directory.CreateDirectory(Path.GetDirectoryName(destFile));
File.Copy(file, destFile, true);
File.SetCreationTime(destFile, File.GetCreationTime(file));
File.SetLastAccessTime(destFile, File.GetLastAccessTime(file));
File.SetLastWriteTime(destFile, File.GetLastWriteTime(file));
}
EditorUtility.ClearProgressBar();
}
void OnGUI()
{
try
{
buildPlayerWindow.Invoke("OnGUI");
}
catch (Exception)
{
}
var activeBuildTarget = EditorUserBuildSettings.activeBuildTarget;
var selectedBuildTarget = GetSelectedBuildTarget();
GUI.enabled = selectedBuildTarget != activeBuildTarget && typeof(BuildPipeline).Invoke("IsBuildTargetSupported", selectedBuildTarget);
GUILayout.BeginVertical();
if (GUILayout.Button("Fast Switch Platform"))
{
const string metadataPath = "Library/metadata";
var activeBuildTargetCachePath = "Fast Switch Platform/" + activeBuildTarget + "_metadata";
var selectedBuildTargetCachePath = "Fast Switch Platform/" + selectedBuildTarget + "_metadata";
DirectoryMerge(metadataPath, activeBuildTargetCachePath);
DirectoryMerge(selectedBuildTargetCachePath, metadataPath);
EditorUserBuildSettings.SwitchActiveBuildTarget(selectedBuildTarget);
// Look for missing metadata files
var currentAsset = 0;
var assetPaths = AssetDatabase.GetAllAssetPaths();
var assetCount = assetPaths.Length;
AssetDatabase.StartAssetEditing();
foreach (var path in assetPaths.Where(path => path.StartsWith("Assets")))
{
EditorUtility.DisplayProgressBar("Hold on", "Reimporting changed assets...", currentAsset / (float)assetCount);
var filename = Path.GetFileName(path);
var guid = AssetDatabase.AssetPathToGUID(path);
if (!string.IsNullOrEmpty(guid) && !File.Exists(metadataPath + "/" + guid.Substring(0, 2) + "/" + guid))
{
EditorUtility.DisplayProgressBar("Hold on", "Reimporting changed assets... (" + filename + ")", currentAsset / (float)assetCount);
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
}
currentAsset++;
}
EditorUtility.DisplayProgressBar("Hold on", "Reimporting changed assets... (processing batch)", 1.0f);
AssetDatabase.StopAssetEditing();
EditorUtility.ClearProgressBar();
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();
}
GUILayout.Space(10f);
GUILayout.EndVertical();
}
[DidReloadScripts]
static void ReopenBuildPlayerWindow()
{
var array = Resources.FindObjectsOfTypeAll(typeof(FastBuildPlayerWindow));
if (array == null || array.Length <= 0)
return;
GetWindow(true).Close();
ShowBuildPlayerWindow();
}
[MenuItem("Window/Fast Switch Platform")]
static void ShowBuildPlayerWindow()
{
GetWindow(true).Show();
}
}
using System;
using System.Reflection;
public static class AccessExtensions
{
public static T InvokeConstructor(this Type type, Type[] paramTypes = null, object[] paramValues = null)
{
return (T)type.InvokeConstructor(paramTypes, paramValues);
}
public static object InvokeConstructor(this Type type, Type[] paramTypes = null, object[] paramValues = null)
{
if (paramTypes == null || paramValues == null)
{
paramTypes = new Type[] { };
paramValues = new object[] { };
}
var constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, paramTypes, null);
return constructor.Invoke(paramValues);
}
public static T Invoke(this object o, string methodName, params object[] args)
{
var value = o.Invoke(methodName, args);
if (value != null)
{
return (T)value;
}
return default(T);
}
public static T Invoke(this object o, string methodName, Type[] types, params object[] args)
{
var value = o.Invoke(methodName, types, args);
if (value != null)
{
return (T)value;
}
return default(T);
}
public static object Invoke(this object o, string methodName, params object[] args)
{
Type[] types = new Type[args.Length];
for (int i = 0; i < args.Length; i++)
types[i] = args[i] == null ? null : args[i].GetType();
return o.Invoke(methodName, types, args);
}
public static object Invoke(this object o, string methodName, Type[] types, params object[] args)
{
var invaild = Array.FindIndex(types, item => item == null) != -1;
var type = o is Type ? (Type)o : o.GetType();
var method = invaild ? type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, types, null);
if(method != null)
return method.Invoke(o, args);
return null;
}
public static T GetFieldValue(this object o, string name)
{
var value = o.GetFieldValue(name);
if (value != null)
{
return (T)value;
}
return default(T);
}
public static object GetFieldValue(this object o, string name)
{
var field = o.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
return field.GetValue(o);
}
return null;
}
public static void SetFieldValue(this object o, string name, object value)
{
var field = o.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(o, value);
}
}
public static T GetPropertyValue(this object o, string name)
{
var value = o.GetPropertyValue(name);
if (value != null)
{
return (T)value;
}
return default(T);
}
public static object GetPropertyValue(this object o, string name)
{
var property = o.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null)
{
return property.GetValue(o, null);
}
return null;
}
public static void SetPropertyValue(this object o, string name, object value)
{
var property = o.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null)
{
property.SetValue(o, value, null);
}
}
}