I get errors related to copying files when attempting to use BuildPipeline
with iOS or Android (it works fine with OS X and Windows).
Here is the iOS error I get:
IOException: Failed to Copy File / Directory from 'Temp/StagingArea/Trampoline/Unity-iPhone.xcodeproj/project.pbxproj' to '/Users/wuchiang/Desktop/mygame-build/ios/Unity-iPhone.xcodeproj/project.pbxproj'.
UnityEditor.iOS.Utils.ReplaceFileOrDirectoryCopy (System.String src, System.String dst)
UnityEditor.iOS.PostProcessiPhonePlayer.UpdateInstallLocation (UnityEditor.iOS.ProjectPaths paths, ScriptingImplementation backend, BuildOptions options, UnityEditor.iOS.IncludedFileList includedFiles)
UnityEditor.iOS.PostProcessiPhonePlayer.PostProcess (UnityEditor.iOS.iOSBuildPostprocessor pp, BuildTarget target, System.String stagingAreaData, System.String stagingArea, System.String stagingAreaDataManaged, System.String playerPackage, System.String installPath, System.String companyName, System.String productName, BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry)
UnityEditor.iOS.iOSBuildPostprocessor.PostProcess (BuildPostProcessArgs args)
UnityEditor.PostprocessBuildPlayer.Postprocess (BuildTarget target, System.String installPath, System.String companyName, System.String productName, Int32 width, Int32 height, System.String downloadWebplayerUrl, System.String manualDownloadWebplayerUrl, BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry) (at /Users/builduser/buildslave/unity/build/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs:316)
UnityEditor.BuildPipeline:BuildPlayer(String[], String, BuildTarget, BuildOptions)
BuildForAllPlatforms:BuildGame() (at Assets/GameAssets/Scripts/Editor/BuildForAllPlatforms.cs:67)
and here is the Android error I get:
DirectoryNotFoundException: Could not find a part of the path "/Users/wuchiang/Desktop/mygame-build/android/MyGame.apk".
System.IO.File.Delete (System.String path) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/File.cs:173)
UnityEditor.Android.PostProcessAndroidPlayer.PostProcessInternal (BuildTarget target, System.String stagingAreaData, System.String stagingArea, System.String playerPackage, System.String installPath, System.String companyName, System.String productName, BuildOptions options)
UnityEditor.Android.PostProcessAndroidPlayer.PostProcess (BuildTarget target, System.String stagingAreaData, System.String stagingArea, System.String playerPackage, System.String installPath, System.String companyName, System.String productName, BuildOptions options)
UnityEditor.Android.AndroidBuildPostprocessor.PostProcess (BuildPostProcessArgs args)
UnityEditor.PostprocessBuildPlayer.Postprocess (BuildTarget target, System.String installPath, System.String companyName, System.String productName, Int32 width, Int32 height, System.String downloadWebplayerUrl, System.String manualDownloadWebplayerUrl, BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry) (at /Users/builduser/buildslave/unity/build/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs:316)
UnityEditor.BuildPipeline:BuildPlayer(String[], String, BuildTarget, BuildOptions)
BuildForAllPlatforms:BuildGame() (at Assets/GameAssets/Scripts/Editor/BuildForAllPlatforms.cs:90)
Error building Player: DirectoryNotFoundException: Could not find a part of the path "/Users/wuchiang/Desktop/mygame-build/android/MyGame.apk".
Here is my script:
using UnityEditor;
using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
public class BuildForAllPlatforms
{
private static int VersionCode = 4;
private static string Version = "1.0.4";
private static string GameName = "MyGame";
private static ApiCompatibilityLevel ApiCompatLevel = ApiCompatibilityLevel.NET_2_0;
// iOS
private static string iOSBundleIdentifier = "com.unity.answers";
private static iOSTargetDevice iOSTargetDev = iOSTargetDevice.iPhoneAndiPad;
private static iOSTargetOSVersion iOSTargetVer = iOSTargetOSVersion.iOS_8_0;
// Android
private static string AndroidBundleIdentifier = "com.unity.answers";
private static AndroidSdkVersions AndroidMinSdk = AndroidSdkVersions.AndroidApiLevel16; // Jellybean;
[MenuItem("Custom Build/Build for all platforms %&b")]
public static void BuildGame()
{
// Get build path
string path = EditorUtility.SaveFolderPanel("Choose Location of Built Game", "", "");
string[] levels = GetLevelPaths();
// Build win32 player.
BuildPipeline.BuildPlayer
(
levels,
path + "/win32/" + GameName + ".exe",
BuildTarget.StandaloneWindows,
BuildOptions.None
);
// Build osx64 player
BuildPipeline.BuildPlayer
(
levels,
path + "/osx64/" + GameName + ".app",
BuildTarget.StandaloneOSXIntel64,
BuildOptions.None
);
// Setup settings shared between Android and iOS
PlayerSettings.bundleVersion = Version;
PlayerSettings.apiCompatibilityLevel = ApiCompatLevel;
// Setup settings for iOS player
PlayerSettings.iPhoneBundleIdentifier = iOSBundleIdentifier;
PlayerSettings.iOS.targetDevice = iOSTargetDev;
PlayerSettings.iOS.targetOSVersion = iOSTargetVer;
// Build iOS player
BuildPipeline.BuildPlayer
(
levels,
path + "/ios/",
BuildTarget.iOS,
BuildOptions.Il2CPP | BuildOptions.AcceptExternalModificationsToPlayer
);
// Setup settings for Android player
PlayerSettings.Android.bundleVersionCode = VersionCode;
PlayerSettings.Android.minSdkVersion = AndroidMinSdk;
PlayerSettings.Android.androidIsGame = true;
PlayerSettings.bundleIdentifier = AndroidBundleIdentifier;
// Read and setup keystore data
Dictionary<string, string> keystoreData = GetAndroidKeystoreData();
PlayerSettings.Android.keystoreName = keystoreData["MYGAME_ANDROID_KEYSTORE_PATH"];
PlayerSettings.Android.keystorePass = keystoreData["MYGAME_ANDROID_KEYSTORE_PASSWORD"];
PlayerSettings.Android.keyaliasName = keystoreData["MYGAME_ANDROID_KEY_ALIAS_NAME"];
PlayerSettings.Android.keyaliasPass = keystoreData["MYGAME_ANDROID_KEY_ALIAS_PASSWORD"];
// Build Android player
BuildPipeline.BuildPlayer
(
levels,
path + "/android/" + GameName + ".apk",
BuildTarget.Android,
BuildOptions.None
);
}
private static string[] GetLevelPaths()
{
List<string> temp = new List<string>();
foreach (UnityEditor.EditorBuildSettingsScene scene in UnityEditor.EditorBuildSettings.scenes)
{
if (scene.enabled)
{
temp.Add(scene.path);
}
}
return temp.ToArray();
}
private static Dictionary<string, string> GetAndroidKeystoreData()
{
string homePath = System.Environment.GetEnvironmentVariable("HOME") + "/";
string configFileName = ".mygame_config";
var sr = new StreamReader(homePath + configFileName);
var fileContents = sr.ReadToEnd();
sr.Close();
Dictionary<string, string> keystoreData = new Dictionary<string, string>();
var lines = fileContents.Split("
"[0]);
foreach (string line in lines)
{
if (line.Length == 0)
{
continue;
}
int indexOfEql = line.IndexOf('=');
string option = line.Substring(0, indexOfEql);
string value = line.Substring(indexOfEql + 1);
keystoreData.Add(option, value);
}
return keystoreData;
}
}