- Home /
How to create a BuildOptions mask in the Editor Window?
I'm trying to setup an EditorWindow script that can create separate builds. So far everything is going well and works. The only issue I seem to be having is setting up a BuildOptions mask in the editor.
I want to have code that does something like this:
private int buildOptionsMask = 0;
private void OnGUI()
{
buildOptionsMask = (int)((BuildOptions)EditorGUILayout.EnumMaskField(
(BuildOptions)buildOptionsMask));
BuildPipeline.BuildPlayer(sceneNames, pathToBuildTo,
buildTarget, (BuildOptions)buildOptionsMask);
}
Thus, I was wondering how would we setup a BuildOptions mask that correctly uses the values picked in the mask. Currently, the code I posted does not work.
EDIT: Dmitriy Yukhanov found a bug with Unity's BuildOptions, so to correctly implement the mask the way it is suppose to be please see his comment here.
Answer by codestage · Oct 16, 2015 at 04:43 PM
Hey, just do it like this:
private BuildOptions buildOptionsMask;
// ...
buildOptionsMask = (BuildOptions)EditorGUILayout.EnumMaskField(buildOptionsMask);
So your full snippet would be:
private BuildOptions buildOptionsMask = 0;
private void OnGUI()
{
buildOptionsMask = (BuildOptions)EditorGUILayout.EnumMaskField(buildOptionsMask);
BuildPipeline.BuildPlayer(sceneNames, pathToBuildTo, buildTarget, buildOptionsMask);
}
I tried that as well, but the mask seemed to be incorrect when I passed it to BuildPipeline.BuildPlayer. Have you confirmed the code works?
Hey, yes, it should work. But looks like there's something wrong with BuildOptions enum. It doesn't work fine as flags. Just try use StaticEditorFlags ins$$anonymous$$d of BuildOptions to see that code works fine and chooses right mask combination.
Here is how BuildOptions look like initially:
[Flags]
public enum BuildOptions
{
None = 0,
Development = 1,
AutoRunPlayer = 4,
ShowBuiltPlayer = 8,
BuildAdditionalStreamedScenes = 16,
AcceptExternal$$anonymous$$odificationsToPlayer = 32,
InstallInBuildFolder = 64,
WebPlayerOfflineDeployment = 128,
ConnectWithProfiler = 256,
AllowDebugging = 512,
SymlinkLibraries = 1024,
UncompressedAssetBundle = 2048,
[Obsolete("Use BuildOptions.Development ins$$anonymous$$d")] StripDebugSymbols = 0,
[Obsolete("Texture Compression is now always enabled")] CompressTextures = 0,
ConnectToHost = 4096,
DeployOnline = 8192,
EnableHeadless$$anonymous$$ode = 16384,
}
I noticed it has no element with value 2 and it has element with index 0. It looks like an error. Here is a version which works fine with the Enum$$anonymous$$askField:
[Flags]
public enum BuildOptionsFixed
{
Development = 1,
None = 2,
AutoRunPlayer = 4,
ShowBuiltPlayer = 8,
BuildAdditionalStreamedScenes = 16,
AcceptExternal$$anonymous$$odificationsToPlayer = 32,
InstallInBuildFolder = 64,
WebPlayerOfflineDeployment = 128,
ConnectWithProfiler = 256,
AllowDebugging = 512,
SymlinkLibraries = 1024,
UncompressedAssetBundle = 2048,
ConnectToHost = 4096,
DeployOnline = 8192,
EnableHeadless$$anonymous$$ode = 16384,
}
So, your final code may look like
private BuildOptionsFixed buildOptions$$anonymous$$ask;
[Flags]
private enum BuildOptionsFixed
{
Development = 1,
None = 2,
AutoRunPlayer = 4,
ShowBuiltPlayer = 8,
BuildAdditionalStreamedScenes = 16,
AcceptExternal$$anonymous$$odificationsToPlayer = 32,
InstallInBuildFolder = 64,
WebPlayerOfflineDeployment = 128,
ConnectWithProfiler = 256,
AllowDebugging = 512,
SymlinkLibraries = 1024,
UncompressedAssetBundle = 2048,
ConnectToHost = 4096,
DeployOnline = 8192,
EnableHeadless$$anonymous$$ode = 16384,
}
private void OnGUI()
{
buildOptions$$anonymous$$ask = (BuildOptionsFixed)EditorGUILayout.Enum$$anonymous$$askField(buildOptions$$anonymous$$ask);
if (GUILayout.Button("Build!"))
{
BuildPipeline.BuildPlayer(new []{ "Assets/CodeStage/AntiCheatToolkit/Examples/TestScene.unity" }, "D:\\TestBuild.exe", BuildTarget.StandaloneWindows, (BuildOptions)buildOptions$$anonymous$$ask);
}
}
I've tried to use it and it worked fine for me. I'm not sure there's a bug in the BuildOptions, maybe I'm missing something here, but I'm going to report it and see what they will answer.
Please note you'll have BuildOptionsFixed.None == 2 ins$$anonymous$$d of initial 0 though.
That did the trick. Thanks for looking into this. I'm going to mark this as the answer, and reference your comment until Unity fixes this issue.
Answer by Bunny83 · Oct 16, 2015 at 10:30 PM
Well, EnumMaskField doesn't quite do what you would expect. What it does is this:
string[] flagNames = (
from x in Enum.GetNames(enumValue.GetType())
select ObjectNames.NicifyVariableName(x)).ToArray<string>();
int value = MaskFieldGUI.DoMaskField(position2, controlID, Convert.ToInt32(enumValue), flagNames, style);
return EditorGUI.EnumFlagsToInt(type, value);
EnumFlagsToInt just does this:
private static Enum EnumFlagsToInt(Type type, int value)
{
return Enum.Parse(type, value.ToString()) as Enum;
}
So it doesn't really care about the actual values of the enum members. It just shows the enum member names in the order they are returned by "Enum.GetNames" and treat them as 1,2,4,8,16, ... regardless of their actual value.
That's why i wrote this wrapper a long time ago. It should work with all bitflag enums and will also handle "combined" values like:
public enum EAbility
{
Fly = 0x02,
Swim = 0x04,
Walk = 0x08,
Talk = 0x10,
Sleep = 0x20,
FlyAndSwim = 0x06,
WalkAndTalk = 0x18,
AllWithoutSleep = 0x1E
}
Note: I skipped 0x01 on purpose. Gaps aren't a problem for that method.