[Unity] Créer une build personnalisée pour WP8/W8
Si vous développez un jeu qui cible Windows Phone 8 ou Windows Store Apps, vous allez probablement utiliser certaines fonctionnalités comme le partage, les tuiles dynamiques, …
Cela peut être fait en utilisant certains mécanismes que j’ai expliqué dans un article précédent et il serait plutôt cool de pouvoir inclure automatiquement dans notre build les fichiers que l’on a modifié (MainPage, splashscreen, tuiles, …)
Créer un menu personnalisé
La première étape consiste à créer une entrée dans le menu pour accéder à notre build plus facilement.
using System.Linq; using System.Security.Policy; using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using System; public class AutoBuilderMenu : MonoBehaviour { [MenuItem("AutoBuilder/WP8")] private static void PerformBuild() { // TODO : Build and replace files } }
Pour plus d’informations sur les MenuItem : http://blogs.infinitesquare.com/b/unity-creer-des-menus-personnalises
Build simple
Ce script va simplement compiler le projet Unity et le convertir en projet WP8 ou W8.
Le nouveau projet sera créé dans le dossier : [PROJECT_BASE_UNITY]/../Builds/{ProjectName}/{BundleVersion}/{TargetPlatform}/{BundleIdentifier} afin de garder un historique de chaque version dans un dossier spécifique.
using System.Linq; using System.Security.Policy; using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using System; public class AutoBuilderMenu : MonoBehaviour { [MenuItem("AutoBuilder/WP8")] private static void PerformBuild() { // Save current editor build target var currentTarget = EditorUserBuildSettings.activeBuildTarget; EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.WP8Player); var buildPath = GetBuildPath(target); var path = Path.GetDirectoryName(buildPath); var folderExists = Directory.Exists(path); if (!folderExists) Directory.CreateDirectory(path); // Create solution folder and project files BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None); // Set saved build target EditorUserBuildSettings.SwitchActiveBuildTarget(currentTarget); } private static string GetProjectName() { string[] s = Application.dataPath.Split('/'); return s[s.Length - 2]; } private static string[] GetScenePaths() { return EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(); } private static string GetBuildPath(BuildTarget target) { var extension = String.Empty; return String.Format("../Builds/{0}/{1}/{2}/{3}", GetProjectName(), PlayerSettings.bundleVersion, target.ToString(), PlayerSettings.bundleIdentifier); } }
Build personnalisée
L’astuce est de compiler deux fois le jeu. La première fois pour créer le projet de base avec les fichiers par défaut, puis on remplace les fichiers que l’on souhaite modifier (MainPage, tuiles, …). Pour finir, on relance la compilation une seconde fois pour prendre en compte les fichiers que l’on a remplacés.
using System.Linq; using System.Security.Policy; using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using System; public class AutoBuilderMenu : MonoBehaviour { [MenuItem("AutoBuilder/WP8")] private static void PerformBuild() { // Save current editor build target var currentTarget = EditorUserBuildSettings.activeBuildTarget; EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.WP8Player); var buildPath = GetBuildPath(target); var path = Path.GetDirectoryName(buildPath); var folderExists = Directory.Exists(path); if (!folderExists) Directory.CreateDirectory(path); // First build to create solution folder and project files BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None); // Replace custom files UpdateWP8Settings(buildPath); // Rebuild with replacing files BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None); // Set saved editor build target EditorUserBuildSettings.SwitchActiveBuildTarget(currentTarget); } private static void UpdateWP8Settings(string buildPath) { // SplashScreenImage var replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/SplashScreenImage.jpg"); var current = string.Format("{0}/{1}/SplashScreenImage.jpg", buildPath, PlayerSettings.bundleIdentifier); if (File.Exists(replace)) File.Copy(replace, current, true); // MainPage.xaml.cs replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/MainPage.xaml.cs"); current = string.Format("{0}/{1}/MainPage.xaml.cs", buildPath, PlayerSettings.bundleIdentifier); if (File.Exists(replace)) File.Copy(replace, current, true); // ApplicationIcon replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/ApplicationIcon.png"); current = string.Format("{0}/{1}/Assets/ApplicationIcon.png", buildPath, PlayerSettings.bundleIdentifier); if (File.Exists(replace)) File.Copy(replace, current, true); // WMAppManifest replace = string.Concat(Application.dataPath, "/../BuildSettings/WP8/WMAppManifest.xml"); current = string.Format("{0}/{1}/Properties/WMAppManifest.xml", buildPath, PlayerSettings.bundleIdentifier); if (File.Exists(replace)) File.Copy(replace, current, true); } private static string GetProjectName() { string[] s = Application.dataPath.Split('/'); return s[s.Length - 2]; } private static string[] GetScenePaths() { return EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(); } private static string GetBuildPath(BuildTarget target) { return String.Format("../Builds/{0}/{1}/{2}/{3}", GetProjectName(), PlayerSettings.bundleVersion, target.ToString(), PlayerSettings.bundleIdentifier); } }
Une façon plus élégante
Dans le script précédent, nous copions chaque fichiers “à la main”, ce qui n’est pas vraiment très pratique. Une autre possibilité est de copier le dossier contentant l’ensemble des fichiers modifiés pour WP8/W8 (BuildSettings/WP8 par exemple) automatiquement.
private static void PerformBuild(BuildTarget target, bool isBeta = false) { var currentTarget = EditorUserBuildSettings.activeBuildTarget; EditorUserBuildSettings.SwitchActiveBuildTarget(target); var buildPath = GetBuildPath(target); var path = Path.GetDirectoryName(buildPath); var folderExists = Directory.Exists(path); if (!folderExists) l { Directory.CreateDirectory(path); } BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None); if (target == BuildTarget.WP8Player) { UpdateWP8Settings(buildPath, string.Concat(Application.dataPath, "/../BuildSettings/WP8/"), string.Concat(buildPath, "/")); if (isBeta) { UpdateWP8Settings(buildPath, string.Concat(Application.dataPath, "/../BuildSettings/WP8_Beta/"), string.Concat(buildPath, "/")); } BuildPipeline.BuildPlayer(GetScenePaths(), buildPath, target, BuildOptions.None); } EditorUserBuildSettings.SwitchActiveBuildTarget(currentTarget); } private static void UpdateWP8Settings(string buildPath, string sourceRootPath, string destinationRootPath = "") { var files = Directory.GetFiles(sourceRootPath); foreach (var file in files) { var replace = file; var fileName = replace.Split('/').LastOrDefault().Split('\\').LastOrDefault(); var current = string.Concat(destinationRootPath, "/" + fileName); File.Copy(replace, current, true); } var directories = Directory.GetDirectories(sourceRootPath); foreach (var directory in directories) { var folderName = directory.Split('/').LastOrDefault().Split('\\').LastOrDefault(); UpdateWP8Settings(buildPath, directory, destinationRootPath + "/" + folderName); } }
Voici la hiérarchie des dossiers que j’ai mis en place :
Merci Jonathan pour l’astuce.
Commentaires