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可能用了如下代码,



BuildPipeline.BuildPlayer( levels, "WebPlayerBuild", 
                   BuildTarget.WebPlayer, BuildOptions.None);


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

        } 

    }