日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【狂云歌之unity_vr】unity项目持续集成dailybuild以及多平台打包管理

發布時間:2023/12/29 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【狂云歌之unity_vr】unity项目持续集成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編輯器常用功能

?我這里準備了一個全局的配置文件,當然這個可以使用外部配置文件來管理配置,是一個道理的。這里定義了兩個平臺版本一個是alpha一個是beta,使用宏來區分不同平臺的版本號。

using UnityEngine; using System.Collections;public class GlobalConfig { #if CLOUD_ALPHApublic const int ClientVersionCode = 1;public const string ClientVersion = "1.0"; #elif CLOUD_BETApublic const int ClientVersionCode = 2;public const string ClientVersion = "1.1"; #endif }

?文件目錄組織大概如下,其中CloudBuild是編輯器工具,包含菜單項和打包功能,兩個平臺分別依賴不同的so文件和manifest文件。

?制作了一個menu,主要包含的功能是可以在alpha和beta平臺之間切換,可以打alpha平臺的apk包,當然想打beta平臺的包只需要簡單修改。

manifest管理

?寫個簡單的腳本進行manifest替換就好,對于alpha平臺和beta平臺各有自己的manifest文件,在切換平臺的時候將對應的manifest復制替換。

/// <summary> /// 使用相應的androidmanifest /// </summary> 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不一樣,那么在最后問用戶是否保存當前場景,然后打開對應平臺的場景。

/// <summary> /// 切換alpha平臺 /// </summary> [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所在文件夾,方便使用
/// <summary> /// </summary> [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_WINSystem.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; /// <summary> /// </summary> 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 folderstatic string GetBuildPathAndroid(){string dirPath = Application.dataPath + "/../build/android/";if (!System.IO.Directory.Exists(dirPath)){System.IO.Directory.CreateDirectory(dirPath);}return dirPath;}/// <summary>/// </summary>[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_WINSystem.Diagnostics.Process.Start("explorer.exe", "\"" + dir + "\""); #endif}/// <summary>/// 切換alpha平臺/// </summary>[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");}/// <summary>/// 切換beta平臺/// </summary>[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");}/// <summary>/// 使用相應的androidmanifest/// </summary>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的管理比較實用。

總結

以上是生活随笔為你收集整理的【狂云歌之unity_vr】unity项目持续集成dailybuild以及多平台打包管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。