Unity不同平臺生成中預處理的注意點
Unity3D的專案,這周吃虧在巨集上了。大背景是專案需要在Unity中用Hudson自動生成不同平臺的版本。
程式設計語言的預處理的概念:在編譯之前進行的處理。
#if UNITY_WEBPLAYER
BuildTarget target = BuildTarget.WebPlayer;
#elif UNITY_STANDALONE_WIN && UNITY_EDITOR
BuildTarget target = BuildTarget.StandaloneWindows;
#elif UNITY_ANDROID
BuildTarget target = BuildTarget.Android;
#else
BuildTarget target = BuildTarget.iPhone;
#endif
#if UNITY_WEBPLAYER
public const string AssetRootPath = AutomaticBuild.WebPlatFormDataPath + "/";
#elif UNITY_STANDALONE_WIN && UNITY_EDITOR
public const string AssetRootPath = AutomaticBuild.WinPlatFormDataPath + "/";
#elif UNITY_ANDROID
public const string AssetRootPath = AutomaticBuild.AndRoidPlatFormDataPath + "/";
#else
public const string AssetRootPath = AutomaticBuild.IOSPlatFormDataPath + "/";
#endif
如上面兩段程式碼,開啟Unity專案(例如PC & Mac Standalone儲存的)之後,再開啟專案的Script(這裡用VS2008+VA),會發現上述加粗行高亮。即Target和AssetRootPath在編譯前已然確定,且之後不能對其做出變更。
當採用Unity支援的命令編譯時C:\program files\Unity\Editor>Unity.exe -quit -batchmode -executeMethod MyEditorScript.MyMethod
此時MyMethod可能用瞭如下程式碼,
但Target和AssetRootPath並沒有賦予應有的Web相應值,會造成生成的Unity3D檔案能生成但不對,執行BuildPlayer時會報Runtime Error錯。不禁讓我想起Effective C++裡的第2個條款:儘量以const, enum, inline替換 #define。果然金科玉律……
我的解決方式如下:
1.在MyMethod中先呼叫
SwitchActiveBuildTarget (target : BuildTarget)函式。
private static string AssetRootPath = null;
public static string GetAssetRootPath()
{
if (AssetRootPath != null)
return AssetRootPath;
if (EditorUserBuildSettings.activeBuildTarget==BuildTarget.WebPlayer)
{
AssetRootPath = "WebData/LatestData/";
}
else if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
{
AssetRootPath = "AndroidData/LatestData/";
}
else if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows)
{
AssetRootPath = "WinData/LatestData/";
}
else
{
AssetRootPath = "IOSData/LatestData/";
}
return AssetRootPath;
}
public static BuildTarget GetBuildTarget()
{
return EditorUserBuildSettings.activeBuildTarget;
}
由於需求的小變更,小小地重構了上次的程式碼:
ClearISingleFileSeries();ClearDirectorySeries();
/// <summary>
/// 刪除單個檔案的陣列
/// </summary>
static void ClearISingleFileSeries()
{
string[] SingleFileSeries = { Application.dataPath + "/Plugins/I18N.dll", Application.dataPath + "/Plugins/I18N.CJK.dll", Application.dataPath + "/Plugins/I18N.West.dll" };
ClearFiles(SingleFileSeries);
}
/// <summary>
/// 刪除filesPath陣列內指向的檔案
/// </summary>
/// <param name="filesPath"></param>
static void ClearFiles(string[] filesPath)
{
foreach (string singleFilePath in filesPath)
{
if (File.Exists(singleFilePath))
{
try
{
File.Delete(singleFilePath);
}
catch (System.Exception ex)
{
//catch ex
}
}
}
}
/// <summary>
/// 刪除目前做Web版本會出現記憶體問題的Audio資源
/// </summary>
static void ClearDirectorySeries()
{
string[] audioPath = { Application.dataPath + "/Game/Audio/Resources", Application.dataPath + "/Game/Audio/SFX", Application.dataPath + "/Game/MyGUI" };
foreach (string audioDirectory in audioPath)
{
if (Directory.Exists(audioDirectory)) //保護,避免檔案目錄不存在跳異常
ClearFilesAndDirectory(audioDirectory);
}
}
/// <summary>
/// 刪除dataPath檔案目錄下的所有子檔案及子資料夾
/// </summary>
/// <param name="DirectoryPath"></param>
static void ClearFilesAndDirectory(string DirectoryPath)
{
DirectoryInfo dir = new DirectoryInfo(DirectoryPath);
//檔案
foreach (FileInfo fChild in dir.GetFiles("*"))
{
if (fChild.Attributes != FileAttributes.Normal)
fChild.Attributes = FileAttributes.Normal;
fChild.Delete();
}
//資料夾
foreach (DirectoryInfo dChild in dir.GetDirectories("*"))
{
if (dChild.Attributes != FileAttributes.Normal)
dChild.Attributes = FileAttributes.Normal;
ClearFilesAndDirectory(dChild.FullName);
dChild.Delete();
}
}