A bit of background:
I’m currently creating a 2D game, and I’m making heavy use of additive scene loading. I have a primary scene containing most of my UI and generic manager objects. This then loads a ‘location’ scene, which can be unloaded and reloaded when the player changes screens. On top of this I can have a ‘utility’ screen for things like pop-up tutorial boxes or stand-alone mini games.
I hate messing around with ‘don’t destroy on load’ because I feel it breaks the hierarchy of my game.
However, this raises the following annoyance. I would like to be able to test my sub-scenes independently of the main one, and to use a UI canvas set to ‘Screen Space - Camera’, but I can’t have two EventSystem objects or Cameras at a time. This means if I want to test one of these sub-scenes in isolation, I have to manually add or activate these elements. Frankly, I don’t want the game to compile with any unwanted objects in the scene at all.
Is there a way I can mark objects so that they are only part of the scene if I’m running it directly from the editor, and are ignored by the compiler?
I do a lot of multi-scene additive tricks. The most sane thing seems to locate all of the “onesies” like a Main Camera and EventSystem only in one scene, and keep it consistent.
Just put a DestroyInProduction
or somesuch Component on things you want to go away in a build. That will work and if it ultimately bugs you so much you can’t abide by those things going out the door, then write a pre-build script to iterate each scene and remove items flagged that way.
You really can also set up all kinds of crazy editor tooling to speed up your partial-scene iteration.
Just don’t make too much of a mess of things because it gets ticklish timing-wise.
As one silly example, you don’t even NEED scenes at all, with a construct like this:
using UnityEngine;
// @kurtdekker - for the purists who don't want ANY scenes in project
//
// All other Unity asset inclusion rules are still in effect, so no
// assets will make it into your project unless they are:
//
// - correctly in a Resources/ folder
// - referenced by something in the above
// - correctly in the Streaming Assets folder / system.
// - correctly bundled in Asset Bundles or Addressables
public class RunmeJohnny : MonoBehaviour
{
// This is where it all begins. You will be called here the
// moment the Unity Engine is up and running and ready for you.
[RuntimeInitializeOnLoadMethod]
static void StartWithNoScenes()
{
Camera cam = new GameObject("Camera").AddComponent<Camera>();
cam.transform.position = new Vector3(0, 3, -10);
cam.orthographic = false;
cam.fieldOfView = 60.0f;
// NOTE: the material on this cube will NOT be included
// in the build because... you didn't reference it anywhere.
//
// You will need to get a material on this cube or
// else it will be hot pink. See comment at top.
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
// inject an instance of this script to get things started
var runme = cube.AddComponent<RunmeJohnny>();
runme.cube = cube;
}
// injected by the above (superfluous here, since it is ourselves,
// but provided as a way to inject other scripts with with stuff)
GameObject cube;
private void Update()
{
float angle = Time.time * 100.0f;
cube.transform.rotation = Quaternion.Euler(0, angle, 0);
}
}
2 Likes
Cool, DestroyInProduction, that’s very likely what I’ve been looking for. Thanks, I will give it a try in the morning!