Loading objects instantiated during runtime from one scene to another in Unity - c#

I'm creating a game where the player creates objects (blocks) in a "set up" scene and then when the timer ends, I'd like those objects, including their transform values to be loaded into a new scene. How would I go about loading objects created during runtime into a new scene?

DontDestroyOnLoad is a valuable way to achieve this.
What you could also do is the following:
Create an Empty object called "Cross-Scene-Objects" and add a script to it, make it so it doesn't destroy on load. Then simply child any objects to that object, and remove objects as you see fit.
You could also make the CrossSceneObjects script a singleton class and have some basic AddObject and RemoveObject methods which handle putting the game objects under the object.
If you only want certain objects in certain scenes, you could use the method above but add some further logic to set game objects active if you're in the scene you want them to show up in.
I have no example code, but if this is not enough for you to work off I can happily edit to provide code examples :) My style is to first provide the solution steps rather than the code to give you a starting point.

Related

How can I grab a reference of a game-object in a scene from a prefab

currently I am working on a Equipment system that will Instantiate Game objects into the scene from a list, prior to this I was not using a Instantiation system with just keeping the Game Objects Active in the scene at all time.
Now with Instantiating the Game Object(Prefab) I am running into the error of Loosing the References when I instantiate them, I have looked at various other articles before such as this Discussion here:
However I am looking at alternative ways other than using Tags as this system may use a large amount of tags decreasing game performance overtime, would anyone know different methods as to saving references from a scene into a prefab?
So as this is a new system I am really just looking for suggestions on how to save references of scene game-objects into a prefab, as my old system was just holding the game objects active in the scene and not actually instantiating them, once again I would love to hear different types of methods, something more than just using Tags.
The References im trying to save are three Transform Elements from a script attached to my Prefab they are the following
public Transform camPos;
public Transform aimLocation;
public Transform crosshairLocation;
Currently I am just dragging and dropping the gameobjects from the scene into the public fields in the script
Since this will be a major system I would like to not want to use tags for this system. But it is definitely a Valid option I am just looking for other methods for saving references of scene game-objects into a prefab When Instantiating the prefab into the scene,
Thank you for taking the time to read and any suggestions would be greatly Appreciated!
Any Questions Just Ask!
You can not save scene references in prefabs, for obvious reasons (what happens if you instantiate that prefab into another scene?). Your prefab needs to discover the objects it needs after it's instantiated. I'm not a huge fan of the tag system in Unity (or any other system that uses strings as identifiers, too much room for error). I'd recommend you take any of these three approaches:
Make the transforms you need (cam pos, aim location, etc.) singletons if there's ever only going to be one of each. You'd make a script class specifically for each one, make that class a singleton, and put it on the game objects. Then, after your prefab is instantiated, you can do something like this: camPos = CamPos.Instance.transform; You can read up on the singleton pattern here.
If there's going to be more than one of each, group all related objects into a single hierarchy (that is, make them all the child of a single game object). For example, if there are going to be many characters and each is going to have a separate aim location, you can make aim location a child of the character game object. Then, in your prefab (take care to make the prefab a child of the same root game object as well), you can do something along these lines: camPos = transform.root.GetComponentInChildren<CamPos>().transform; Better yet, you can have a component that has references to all such objects, and attach one to the root game object. Then, you can do: camPos = transform.root.GetComponent<ReferenceRepository>().CamPos;
Initialize the prefabs when they're instantiated. For example, say you have a player class that instantiates a weapon and already has a reference to the camPos. You can do it like this: var weapon = Instantiate<Weapon>(myWeaponPrefab); weapon.CamPos = camPos; Note however that when you assign public fields this way, they will only be accessible once Start is called. In other words, they won't be available in Awake.
That said, I don't think making stuff like aim location and crosshair location separate objects is a very good idea anyway. You should have a player/human/pawn class, and that class can provide this information to other objects that need it.

Unity 5 C# - How to Change Scenes and Import all Resources from Last Scene

I'm not sure how to switch scenes and bring all of my resources with me. I do understand that upon load of new scene, the previous scene gets destroyed on load. I've explored some with DontDestroyOnLoad() but had no luck with what I'm trying to do.
I tried to make my player controller a prefab and simply put him into the next scene; however, I returned a heck of a lot of errors because of the many scripts I have. Mostly stuff like checkpoint, HP bars, and even the weapon.
What I need to know is how to import everything into the next scene. How do I do this without having to recode or even re-make all of the stuff that I need?
You're looking for LoadSceneMode.Additive. This is the second parameter of the LoadScene method and will load the new scene into the current one.
If you need to import every object from the previous scene, then what's the point in creating a new one?
What you could do is saving the objects positions into a file and then loading that file back on the next scene or try (again) with DontDestroyOnLoad();
I recommend to check the documentation of Unity about this function.
If you want an individual object not to be destroyed on the scene change then on the void Awake() function of Unity make a DontDestroyOnLoad(this.gameObject);
Could you provide more information? I ask because it seems from your description that
DontDestoryOnLoad
should accomplish what you want but you say it does not. As long as the object holding the components whose states you want to save is persisted into the next scene using that method, then all of those components' states should be persisted as well. Please elaborate and we can possibly provide a better answer. As for how to use it to save the state of every game object:
GameObject[] allObjects = UnityEngine.Object.FindObjectsOfType<GameObject>();
foreach(GameObject go in allObjects) {
if (go.activeInHierarchy) { /* and any other logic you want. Maybe like !isTerrain */
Object.DontDestroyOnLoad(go);
}
}
For the above code, I ripped it from https://answers.unity.com/questions/329395/how-to-get-all-gameobjects-in-scene.html

How does Unity decide which Component to return when calling GetComponent<T> on a GameObject with multiple components of type T?

If I have a GameObject with multiple Component classes attached to it of the same type (let's call this type HingeJoint for example purposes), which HingeJoint component will I get if I called the function GetComponent<HingeJoint>() on my GameObject?
According to my research, this answer claims Unity will simply return the first match from the array of Components--however, the answer is only an educated guess based on the answerer's own game engine design that strives to mimic Unity and not an authoritative source for what Unity actually does.
Every object and it's subobjects in Unity are hierarchically placed in a collection. You can call it a "WYSIWYG" because as you see every object in the scene hierarchy is loaded in the same order they are displayed on that list. The same thing applies to the components and it's the main reason why Transform component is placed on top of every other component.
GetComponent will return the first item from the collection of Components seen from the top of the list. To be exactly sure which component will be returned you can order them as you wish in the inspector view.
From the documentation page:
The order you give to components in the Inspector window is the order you need to use when querying components in your user scripts. If you query the components programmatically, you’ll get the order you see in the Inspector.
EDITED after m.rogalski correction
The manual indicates that components are checked in the order you put them in the inspector, so GetComponent() will give you the first one of type T
How ever I would recommend not to use inspector ordering, but instead use
GetComponents<T>()
To retrieve them all and dynamically choose the one you need (See the doc if needed)
This is because it would make it really difficult for you to maintain your project if the order of your components mattered. Any other person working on the project would need to know the convention in which these components must be placed. Even if you work alone, you would need to be very careful when adding or removing components, and in case of a bug, your IDE won't be able to give you a clear error

Unity - persistence with inspector-added references

I have a persistent game object that I use to initialize basically everything. The script Persistence as I call it has some public references I just dragged on them via the inspector.
I'm trying to make it persistent like I found online:
public static Persistence instance;
void Awake()
{
if (instance != null)
{
DestroyImmediate(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
instance = this;
}
}
The thing is, when I load a level from main menu, it's fine. When I load back the main menu from that level, it says
MissingReferenceException: The object of type 'Persistence' has been destroyed but you are still trying to access it.
So I decided to let it create other instances when loading the main menu, but that messes up all the scripts on the game levels that rely on this data.
My question is, how to correctly implement this ~singleton persistent pattern in Unity, given I have inspector-added references?
NOTE that I initialize only from my Awake function in my persistent class and from nowhere else. Literally, my InitializeMe scripts are called from the Persistence class, one after the other.
What should I do differently to make this work? Initialize from a different, non-persistent gameobject? Forget dragging to the inspector? Any advice to make this work is appreciated.
I got it to work. So here's the thing one should know (I should have known) before messing around with persistence in Unity:
You don't drag references to a persistent GO via the inspector as they are gone the instant another scene is loaded except for additive loading. Also the persistent GO may hold data relevant to multiple scenes, hold functionality that is built for general purpose, as reusable as it goes, but it never initializes anything itself or interfere with non-persistent GOs other than being called - used as a tool - or providing the data.
This arcane wisdom is mine though, so anyone more skilled reading this, please do correct me if I'm wrong before others take this to heart.
So to be exact, I made a non-persistent master INITIALIZER that does the exact thing. I get all the scene GOs into a collection once and no GameObject.Find again. I used LINQ queries to conveniently filter my results from that collection. Another thing was my InitializeMe abstract class (or to be more precise, its descendants).
public abstract class InitializeMe : MonoBehaviour
{
public int orderNumber;
public abstract void INIT(INITIALIZER init);
}
here orderNumber is used to determine the order of the initializations, should one object depend on the other. It also worths mentioning that doing like so can result in a very predictable way to setting things up, as it is done one after the other. Note that this doesn't create a bottleneck, because Unity's scripting API only be executed in the main thread - dividing the code into multiple Awake or Start methods wouldn't perform better to my best knowledge as of 2017. It is used by a LINQ query in the INITIALIZER.
The good thing in INITIALIZER is that - again - it holds itself everything, including a reference to the persistent object and the save data as well, so via referencing itself to the InitializeMe methods they can do everything they need - as DataBank provides general purpose tools with persistent data, and INITIALIZER provides volatile (hope I use that right, I mean relevant to only main menu) data with some additional functionality that is used only for the main menu.
Now, persistence was ensured not by the persistent class itself, but by this INITIALIZER in Awake like so:
//find by tag or rename upon instantiation as by doing so will result in a "(Clone)" added to its name.
var d = GameObject.FindGameObjectWithTag("DataBank");
if (d == null)
{
//instantiating it
DATA = GameObject.Instantiate<DataBank>(DATA_blueprint);
//intializing the databank itself. The parameters are needed for me,
// but serve as a good example - all of those are dragged from the inspector to the _INITIALIZER_ but will remain in the whole game as long as databank exists.
DATA.LoadDataFromINIT(_baseColor, _baseColor2, _outlineColor,
new MMtoolBundle(DATA));
//to make it persistent.
DontDestroyOnLoad(DATA);
}else
{
//in this case the main menu is loaded from another scene.
//so we only find that loaded object and get its reference, no initialization as it was already setup.
this.DATA = d.GetComponent<DataBank>();
}
where DATA is my persistent DataBank. Note that by default I have NO DataBank object on the scene. DATA_blueprint is the prefab of DataBank dragged by the inspector (as INITIALIZER is not persistent). It could be loaded via AssetDatabase as well but this was a bit more convenient.
it worths mentioning that while DataBank is a MonoBehaviour itself so it can appear in Unity scenes, none of its members are MonoBehaviours so it is possible to harness the power of inheritance. Should one wish to start a coroutine in a non-mono toolkit, it would have to be started with a reference from DataBank itself.
An obvious drawback of this method is that the existence of my persistent GO depends on INITIALIZER, so that one has to be on the first scene. But again, as most games start with a main menu, this shouldn't pose a big issue (talking about single player games).
YET AGAIN I would recommend someone more skilled to correct me in case I lead others astray, but this solution worked for me - got the same and only persistent GO in all my scenes with no other ever created.

How to load/get to/from scene variables via loadlevel with scenemanager in unity3d programmatically

Since
Application.LoadLevel(level);
deprecated and new SceneManager is proposed, i am asking how to use it to load/get simple parameters like string type and in which functions of lifecycle would be best practise?(such as Start, Awake)
SceneManager.LoadScene("resultScene", chosenOptions);
note to simplify: is there an option besides writing new class such as?
Things in Unity work differently than a native mobile app. You don't need pass the parameters to use them in next scene while loading it. Just add a script on empty object in your first scene which has DontDestroyOnLoad in it and save your values in this script. As this object would presist through out the game life cycle, you can store your values in this script. And update them before loading a new scene. and then use them in start of new scene etc.
You can have a look at callback execution order and choose the method which suits your needs.
Read more about preloaded scene/object

Categories

Resources