【狂雲歌のunity_vr】unityプロジェクト持続統合cibuild&dailybuild


【狂雲歌のunity_vr】unityプロジェクト持続的統合dailybuildおよびマルチプラットフォームパッケージ管理


前言


継続的な統合の意味は多くない.unityは通常、パッケージ化は直接build&runですが、実際のプロジェクトでは、サーバbuildパッケージに直接使用されることが多いので、コマンドラインのパッケージ化は欠かせません.ここではunityパッケージを共有して持続的な統合を行う一方で、unity管理マルチプラットフォームパッケージを共有します.例えば、vrappはgearバージョンをサポートし、小米バージョンをサポートし、cardboardバージョンをサポートする必要があります.
 我们做vr相关的app,需要支持gear、cardboard、小米、vivo、大朋、暴风、Idealens、pico、nibiru、酷开等一大堆平台,曾经还有lg和htcvive、oculus平台,未来还会有更多的平台,所以关于unity项目的多平台管理是很重要的,在这方面我们也在探索,积累了一点经验.ここで紹介するのは主にunityのc#に書かれたパッケージとマルチプラットフォーム管理に基づいており、その一部の機能をpythonや他のプロファイルで実現することもできますが、c#で直接行うだけで便利です.

jenkins


https://jenkins.io/index.html
 jenkinsは言うまでもなく、知っている人は何をしているのかを知っています.hudsonに由来し、svnやgitなどのバージョン管理をサポートする持続的な統合サーバを簡単に構築することができます.bashはサポートされているので、bash、pythonなどのほとんどのスクリプトでパッケージスクリプトと前後の処理を書くことができます.

unityコマンドラインパッケージ


 unityはどのようにコマンドラインパッケージを行いますか.実はunityはコマンドラインで起動することをサポートしていますが、editorサポート実行コマンドを閉じる必要があります.以下のようにします.
${unity } -projectPath ${ } 
-executeMethod CloudBuild.PerformBuildAndroidCloudAlphaRelease 
-batchmode -quit -logFile ${ log } 
-ForceExitEditor

 全体的に理解しやすいが、CloudBuild.PerformBuildAndroidCloudAlphaReleaseはクラスの静的メソッドであり、このメソッドにパッケージ関連論理を書けばよい.
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.Android);
string[] scenes = { "Assets/Scenes/Init.unity", "Assets/Scenes/Main.unity" };
BuildPipeline.BuildPlayer(scenes, buildpath, BuildTarget.Android, BuildOptions.None);

コアロジックがこれだけ多いとandroidパッケージが作成されbuildpathの下に生成されます

マルチプラットフォームパッケージ管理


準備作業


 unityプラグインに詳しくない場合は、unityプラグインの開発を見ることができます.unityエディタの一般的な機能を一度に解決します.
 ここではグローバルなプロファイルを用意しています.もちろん、これは外部プロファイルを使用してプロファイルを管理することができます.ここでは、2つのプラットフォームバージョンを定義します.1つはalphaで、1つはbetaで、マクロを使用して異なるプラットフォームのバージョン番号を区別します.
using UnityEngine;
using System.Collections;

public class GlobalConfig {
#if CLOUD_ALPHA
    public const int ClientVersionCode = 1;
    public const string ClientVersion = "1.0";
#elif CLOUD_BETA
    public const int ClientVersionCode = 2;
    public const string ClientVersion = "1.1";
#endif
}

 ファイルディレクトリの組織は、CloudBuildがエディタツールであり、メニュー項目とパッケージ機能を含み、2つのプラットフォームはそれぞれ異なるsoファイルとmanifestファイルに依存している.
 はmenuを作成し、主にalphaとbetaプラットフォームの間で切り替えることができ、alphaプラットフォームのapkパッケージを打つことができ、もちろんbetaプラットフォームのパッケージを打つには簡単な修正しか必要ありません.

manifest管理


 簡単なスクリプトを書いてmanifest置換すればいいです.alphaプラットフォームとbetaプラットフォームにはそれぞれ独自のmanifestファイルがあり、プラットフォームを切り替えるときに対応するmanifestをコピーして置換します.
/// 
///   androidmanifest
/// 
static void UseAndroidManifest(string filename)
{
    string src_filename = string.Format("AndroidManifest-{0}.xml", filename);
    string dst_filename = "AndroidManifest.xml";
    string path = Application.dataPath + "/Plugins/Android/";
    File.Copy(path + src_filename, path + dst_filename, true);
    AssetDatabase.Refresh();// manifest , unity assets
}

依存パッケージ管理


 なぜ依存パッケージ管理をするのか.異なるプラットフォームsdkを使用する場合、多くのsdkが導入される可能性があるため、各sdkには自分のso、jar、aarパケットなどが含まれており、何も管理せずに直接パッケージ化すると、これらの依存するファイルはすべてのapkパケットに打ち込まれ、簡単に言えばパケットの体積が増加し、さらに深刻な場合、これらの異なるプラットフォームsdkの依存ライブラリは衝突する可能性があり、同じapkパケットに打ち込むと、結果は想像にたえない~
 做依赖包管理主要依赖unity自己的assetimport管理如下图,那么只要在需要的时候勾选不需要的时候取消勾选就好了,我们要做的就是用代码来自动实现这个功能.
 各プラットフォームの依存パッケージパスを準備する
static string[] Plugins_Alpha = new string[] {
    "Assets/Plugins/Android/libs/armeabi-v7a/alpha.so",
};

static string[] Plugins_Beta = new string[] {
    "Assets/Plugins/Android/libs/armeabi-v7a/beta.so",
};

 その後、異なるプラットフォームを切り替える際にこれらの依存パッケージのimportを処理します.このAssetはpluginに属するので、pluginimporterを使用してチェックの問題を管理します.
static void ChangePluginToAlpha()
{
    SetEnablePluginImport(Plugins_Alpha, true);
    SetEnablePluginImport(Plugins_Beta, false);
}

static void ChangePluginToBeta()
{
    SetEnablePluginImport(Plugins_Alpha, false);
    SetEnablePluginImport(Plugins_Beta, true);
}

static void SetEnablePluginImport(string[] plugins, bool enable = true)
{
    foreach(var path in plugins)
    {
        PluginImporter vrlib = AssetImporter.GetAtPath(path) as PluginImporter;
        vrlib.SetCompatibleWithPlatform(BuildTarget.Android, enable);
    }
}

 非常に简単に见れば分かるので、试してみれば分かります.

プラットフォーム切り替え


 プラットフォーム切替機能は主にeditorで各プラットフォーム機能をデバッグする際に使用するメニュー項目で、機能も簡単で、以下のことをしました.
  • 切プラットフォームとマクロ定義
  • 切playersettingパラメータ
  • 切buildscene構成
  • 切manifestと依存パッケージ
  • 対応するプラットフォームのシーンを保存および開く(シーンが多重でない場合)
  • .
     コードの例は、vr関連のappを行うため、gearプラットフォームではvrsupportがtrue、他のプラットフォームではfalseとなり、異なるプラットフォームのsceneが異なる場合は、最後にユーザーに現在のシーンを保存するかどうかを聞いて、対応するプラットフォームのシーンを開きます.
    /// 
    ///  alpha 
    /// 
    [UnityEditor.MenuItem("CloudBuild/SwitchToAlpha", priority = 50)]
    static void SwitchToAlpha()
    {
        PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, DEFINES_ALPHA);
        PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, DEFINES_ALPHA);
        PlayerSettings.virtualRealitySupported = true;
        EditorBuildSettings.scenes = new EditorBuildSettingsScene[] {
            new EditorBuildSettingsScene("Assets/Scenes/Init.unity", true),
            new EditorBuildSettingsScene("Assets/Scenes/Main.unity", true)
        };// 
        UseAndroidManifest("Alpha");
        ChangePluginToAlpha();
        EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
        EditorSceneManager.OpenScene("Assets/Scenes/Main.unity");
    }

    梱包する


    では、最後にパッケージ化されたスクリプトは以下の通りです.情報量が大きいかもしれませんが、実際にはいくつかのことしかしていません.
  • 梱包するscene
  • を用意
  • 現在のeditorの状態を保存して、パケットの回復を完了します.これは開発の使用を便利にするためです.そうしないと、開発機でパケットを打つとeditorの多くの属性が変わったことに気づきます.
  • androidの署名問題を処理する
  • パッケージ
  • 最後にwindowsなら、一般的に開発機で、buildの良いapkのあるフォルダを直接開いて、
  • を使いやすいです.
    /// 
    /// 
    [UnityEditor.MenuItem("CloudBuild/CloudAlpha-Release")]
    static void PerformBuildAndroidCloudAlphaRelease()
    {
        EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.Android);
        string[] scenes = { "Assets/Scenes/Init.unity", "Assets/Scenes/Main.unity" };
        string path = GetBuildPathAndroid();
        if (scenes == null || scenes.Length == 0 || path == null)
        {
            Debug.LogError("error scene is null");
            return;
        }
        string tempid = PlayerSettings.bundleIdentifier;
        string name = PlayerSettings.productName;
        bool virtualRealitySupported = PlayerSettings.virtualRealitySupported;
        PlayerSettings.virtualRealitySupported = true;
        PlayerSettings.bundleIdentifier = "net.itsong.vralpha";
        PlayerSettings.productName = PRODUCT_NAME;
        PlayerSettings.Android.keystoreName = "";
        PlayerSettings.Android.keyaliasName = "";
        PlayerSettings.Android.keyaliasPass = "";
        PlayerSettings.Android.keystorePass = "";
        PlayerSettings.Android.bundleVersionCode = GlobalConfig.ClientVersionCode;
        PlayerSettings.bundleVersion = GlobalConfig.ClientVersion;
        string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
        UseAndroidManifest("Alpha");
        ChangePluginToAlpha();
        PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, DEFINES_ALPHA + DEFINES_RELEASE);
        string buildpath = path + string.Format("cloudvr_alpha_release_{0}.apk", DateTime.Now.ToString("MMddHHmm", DateTimeFormatInfo.InvariantInfo));
        BuildPipeline.BuildPlayer(scenes, buildpath, BuildTarget.Android, BuildOptions.None);
        PlayerSettings.virtualRealitySupported = virtualRealitySupported;
        PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, defines);
        PlayerSettings.bundleIdentifier = tempid;
        PlayerSettings.productName = name;
        PlayerSettings.Android.keystoreName = "";
        PlayerSettings.Android.keyaliasName = "";
        PlayerSettings.Android.keyaliasPass = "";
        PlayerSettings.Android.keystorePass = "";
        string dir = path.Replace('/', '\\');
    #if UNITY_EDITOR_WIN
        System.Diagnostics.Process.Start("explorer.exe", "\"" + dir + "\"");
    #endif
    }

    完全なCloudBuildファイルは次のとおりです.
    using UnityEngine;
    using UnityEditor;
    using System.Collections.Generic;
    using System.IO;
    using System;
    using System.Globalization;
    using UnityEditor.SceneManagement;
    /// 
    /// 
    partial class CloudBuild
    {
        const string PRODUCT_NAME = " VR";
        const string DEFINES_ALPHA  = "CROSS_PLATFORM_INPUT;MOBILE_INPUT;CLOUD_ALPHA;";
        const string DEFINES_BETA = "CROSS_PLATFORM_INPUT;MOBILE_INPUT;CLOUD_BETA;";
        const string DEFINES_RELEASE = "CLOUD_RELEASE";
    
        static string[] Plugins_Alpha = new string[] {
            "Assets/Plugins/Android/libs/armeabi-v7a/alpha.so",
        };
    
        static string[] Plugins_Beta = new string[] {
            "Assets/Plugins/Android/libs/armeabi-v7a/beta.so",
        };
    
        // Build the Android APK and place into main project folder
        static string GetBuildPathAndroid()
        {
            string dirPath = Application.dataPath + "/../build/android/";
            if (!System.IO.Directory.Exists(dirPath))
            {
                System.IO.Directory.CreateDirectory(dirPath);
            }
            return dirPath;
        }
    
        /// 
        /// 
        [UnityEditor.MenuItem("CloudBuild/CloudAlpha-Release")]
        static void PerformBuildAndroidCloudAlphaRelease()
        {
            EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.Android);
            string[] scenes = { "Assets/Scenes/Init.unity", "Assets/Scenes/Main.unity" };
            string path = GetBuildPathAndroid();
            if (scenes == null || scenes.Length == 0 || path == null)
            {
                Debug.LogError("error scene is null");
                return;
            }
            string tempid = PlayerSettings.bundleIdentifier;
            string name = PlayerSettings.productName;
            bool virtualRealitySupported = PlayerSettings.virtualRealitySupported;
            PlayerSettings.virtualRealitySupported = true;
            PlayerSettings.bundleIdentifier = "net.itsong.vralpha";
            PlayerSettings.productName = PRODUCT_NAME;
            PlayerSettings.Android.keystoreName = "";
            PlayerSettings.Android.keyaliasName = "";
            PlayerSettings.Android.keyaliasPass = "";
            PlayerSettings.Android.keystorePass = "";
            PlayerSettings.Android.bundleVersionCode = GlobalConfig.ClientVersionCode;
            PlayerSettings.bundleVersion = GlobalConfig.ClientVersion;
            string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
            UseAndroidManifest("Alpha");
            ChangePluginToAlpha();
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, DEFINES_ALPHA + DEFINES_RELEASE);
            string buildpath = path + string.Format("cloudvr_alpha_release_{0}.apk", DateTime.Now.ToString("MMddHHmm", DateTimeFormatInfo.InvariantInfo));
            BuildPipeline.BuildPlayer(scenes, buildpath, BuildTarget.Android, BuildOptions.None);
            PlayerSettings.virtualRealitySupported = virtualRealitySupported;
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, defines);
            PlayerSettings.bundleIdentifier = tempid;
            PlayerSettings.productName = name;
            PlayerSettings.Android.keystoreName = "";
            PlayerSettings.Android.keyaliasName = "";
            PlayerSettings.Android.keyaliasPass = "";
            PlayerSettings.Android.keystorePass = "";
            string dir = path.Replace('/', '\\');
    #if UNITY_EDITOR_WIN
            System.Diagnostics.Process.Start("explorer.exe", "\"" + dir + "\"");
    #endif
        }
    
        /// 
        ///  alpha 
        /// 
        [UnityEditor.MenuItem("CloudBuild/SwitchToAlpha", priority = 50)]
        static void SwitchToAlpha()
        {
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, DEFINES_ALPHA);
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, DEFINES_ALPHA);
            PlayerSettings.virtualRealitySupported = true;
            EditorBuildSettings.scenes = new EditorBuildSettingsScene[] {
                new EditorBuildSettingsScene("Assets/Scenes/Init.unity", true),
                new EditorBuildSettingsScene("Assets/Scenes/Main.unity", true)
            };// 
            UseAndroidManifest("Alpha");
            ChangePluginToAlpha();
            EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
            EditorSceneManager.OpenScene("Assets/Scenes/Main.unity");
        }
    
        /// 
        ///  beta 
        /// 
        [UnityEditor.MenuItem("CloudBuild/SwitchToBeta", priority = 50)]
        static void SwitchToBeta()
        {
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, DEFINES_BETA);
            PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, DEFINES_BETA);
            PlayerSettings.virtualRealitySupported = true;
            EditorBuildSettings.scenes = new EditorBuildSettingsScene[] {
                new EditorBuildSettingsScene("Assets/Scenes/Init.unity", true),
                new EditorBuildSettingsScene("Assets/Scenes/Main.unity", true)
            };// 
            UseAndroidManifest("Beta");
            ChangePluginToBeta();
            EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
            EditorSceneManager.OpenScene("Assets/Scenes/Main.unity");
        }
    
        /// 
        ///   androidmanifest
        /// 
        static void UseAndroidManifest(string filename)
        {
            string src_filename = string.Format("AndroidManifest-{0}.xml", filename);
            string dst_filename = "AndroidManifest.xml";
            string path = Application.dataPath + "/Plugins/Android/";
            File.Copy(path + src_filename, path + dst_filename, true);
    
            PlayerSettings.Android.bundleVersionCode = GlobalConfig.ClientVersionCode;
            PlayerSettings.bundleVersion = GlobalConfig.ClientVersion;
            AssetDatabase.Refresh();
        }
    
        static void ChangePluginToAlpha()
        {
            SetEnablePluginImport(Plugins_Alpha, true);
            SetEnablePluginImport(Plugins_Beta, false);
        }
    
        static void ChangePluginToBeta()
        {
            SetEnablePluginImport(Plugins_Alpha, false);
            SetEnablePluginImport(Plugins_Beta, true);
        }
    
        static void SetEnablePluginImport(string[] plugins, bool enable = true)
        {
            foreach(var path in plugins)
            {
                PluginImporter vrlib = AssetImporter.GetAtPath(path) as PluginImporter;
                vrlib.SetCompatibleWithPlatform(BuildTarget.Android, enable);
            }
        }
    }
    

    に続く


     这里没写build ios ipa包的过程,ios的build过程会稍微长一些,要先build好xcode project然后再通过xcode的命令行去打包,所以前半部分与android是可以复用的,只要稍加修改就可以支持ios的build.また、私たちは今vr関連のappをしています.ほとんどがandroidバージョンなので、apkの管理は実用的です.
    VR開発またはunity関連コミュニケーションはメールで可能[email protected]転載は原文リンクを明記してくださいhttp://blog.csdn.net/madcloud...