1. 程式人生 > >Unity不同平臺生成中預處理的注意點

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();
        }
    }