# Unity Pre Build Script - Add target dependent UI Elements

I wrote a postbuild script that deploys my builds to google drive. That works great, but when I tried to use the same type of logic on a pre build script, it fails. I'm trying to enable all game objects with the tag Mobile if the platform is mobile (andriod or ios). Otherwise turn those off. This is what I have for a script:

#if UNITY_EDITOR
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEditor;

public class PreBuild : IPreprocessBuildWithReport
{
public int callbackOrder => 0;

public void OnPreprocessBuild(BuildReport report)
{
var mobileGameObjects = GameObject.FindGameObjectsWithTag("Mobile");
switch (report.summary.platform) // todo: make sure all targets are populated here
{
// mobiles
case BuildTarget.Android:
case BuildTarget.iOS:
//enable all game objects
foreach (var mobileGameObject in mobileGameObjects)
{
mobileGameObject.SetActive(true);
}

break;
// standalones (desktops)
case BuildTarget.StandaloneWindows:
case BuildTarget.StandaloneLinux64:
case BuildTarget.StandaloneOSX:
foreach (var mobileGameObject in mobileGameObjects)
{
mobileGameObject.SetActive(false);
}

break;
// todo: consoles
}
}
}
#endif


The build runs fine, but when I run in mobile, none of the UI elements are there (off by default). Here is the heirarchy of them in my project: (screenshot not working):

- UI (Canvas Game Object)
- Mobile ("Empty" Game Object, is tagged with "Mobile")
- Joystick1
- Joystick2
- ActionButton


What am I missing?

• It might not be able to find any that are tagged. – Jeff Aug 3 '19 at 19:18

A few notes:

First, FindGameObjectsWithTag only finds active GameObjects. You would need every GameObject you wanted to possibly have enabled be active in the scene when saving it.

Second, that build preprocessor does not run with a specific scene loaded. You perhaps want to use a per-scene processor:

IProcessSceneWithReport.OnProcessScene

This processor runs in play mode in the editor as well, so that should be taken into account (by checking if (report == null)), unless it is desirable to have this behavior in the editor during testing.

Third, this script should go into an Editor folder so you don’t need to include #if UNITY_EDITOR.

So here’s my take (warning: untested):

using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEditor;
using System.Linq;

public class PreBuild : IProcessSceneWithReport
{
public int callbackOrder => 0;

public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, BuildReport report)
{
if (report == null) return;
foreach (var root in scene.GetRootGameObjects())
{
ProcessHierarchy(root.transform, report);
}
}

private void ProcessHierarchy(Transform root, BuildReport report)
{
var allTransforms = root.GetComponentsInChildren<Transform>(true);
var mobileGameObjects = allTransforms.Where(t=>t.CompareTag("Mobile")).Select(t=>t.gameObject);
BuildTarget bt = report.summary.platform;
bool isMobile = bt == BuildTarget.Android || bt == BuildTarget.iOS;
foreach (var mobileGameObject in mobileGameObjects)
{
mobileGameObject.SetActive(isMobile);
}
}
}

• I will try this out, my question is with this, does it only work for one scene? or is it all scenes, before processing, turn on/off mobile devices. It seems like this should be a build step, right? I honestly don't know typically what is done though. – Jeff Aug 4 '19 at 13:09
• Okay, I think I misunderstood what this function does. And in my mind, you'd just not include all mobile assets as a pre compiler step, but in actuality, these exist in a scene. You'd need to do implement the interface you specified. That being said, it still didn't work. No errors though. – Jeff Aug 4 '19 at 13:20
• Ah... this did work! I also had a build issue where it wouldn't run a new version of the app on my android. Thank you so much! – Jeff Aug 4 '19 at 20:16