I’m still very new at Unity. I’ve completed a few tutorials and started to extend on them to see what else i can learn within a familiar project. In this project we created prefabs for Floors, Walls, Enemies etc. I wanted to set up a Serialization in order to save the randomly generated level to file. I work a solution that worked in the editor, but will not work when i move to “Build” the game exe file.
The solution i tried was to keep a manifest of the generated objects. This manifest was simply:
What Prefab i loaded, using its name and location in the Resources folder
Where it is in the 2D world (X and Y)
If its enabled or not.
The problem that i’m facing is that in order to do this i’ve been using (variables created earlier):
parentObject = PrefabUtility.FindPrefabRoot(obj);
prefabFolder = AssetDatabase.GetAssetPath(parentObject);
These methods come from “using UnityEditor;” which itself is preventing me from building. Quick google search only really returned advice to remove this code, rather than an alternate. Is there a better way to get the prefab location that will allow me to build my project? Have i approached the Serialization in a way that’s just too wonky?
Save scene, asset and prefab are only Unity Editor functions.
To save prefab at runtime you need serialize GameObject. Unity GameObject or Component aren’t serialized classes. You need create own functions to serialize/deserialize it.
Yes this is what im using to load my resources. Ive created subfolders to keep everything organized. The problem is that on an object by object basis ill need to know what folder/subfolder each object came from.
I have created my own serialized class. The problem stems from finding a non-editor way of reading the prefab folder path when it comes to saving. The actual saving and load works great, if i have that path.
They ARE in the resources folder, but in subfolders within that path. Without details on your suggestion it appears you seem to indicate that that would mean that every Avater, Wall, Floor etc will have to be in a single folder. Surely that’s not good practice to lump everything into a single folder without some form of sub-folder categorization? Its getting that sub-folder name, within the resources folder, that is the problem.
Maybe i’ll set up my sub-folders by Tag. Then i can read the object tag, save the tag name just like i was doing the folder path. That should get around the issue.
I’m a little confused by your dilemma. You are building a level that has various Floor, Walls , etc. in it. Then when loading this level you need to instantiate say “Floor1a” prefab. But you need a way to know what subfolder that prefab was in? If they were all lumped in the Resources folder(which I agree is a bad idea), how would your code know that “Floor1a” was the name of the prefab you needed to load?
When generating the level, i have an array that holds a manifest of each of the objects that may need to be saved later. A separate parallel array is used to hold the object name and folder (lists could also work here depending on what suits the project). This data is available at the time of instantiation.
There are plenty of hardcode solutions but they don’t feel like “best” solution. Especially when i like to write code that is as clean and portable between projects as possible (20 years of programming does that to you).
I think the tag solution is going to work the best as TAG is a unity property that i can rely on project by project. Organising my serialisable prefabs into folders based on each tag would keep my code as dynamic as possible and allow me to port much of it from project to project with only a minimal project requirement to keep it working. This means my Save method can simply just accept a GameObject reference and original prefab name (allowing runtime names to be changed if required). I’ll then save to file tag instead of folder.
Then just make your paths logical. Put all your floor prefabs in Resources/Floor folder and make sure the spawned GameObjects have an identical name to their prefab and put them under a Floor empty GameObject. Then you can just enumerate Floor’s children and save the names of those children and look them up later.
// save
var floor = GameObject.Find("Floor");
foreach (var t in floor.transform)
{
if (t != floor.transform)
{
WriteToFile(t.name, t.position, t.rotation);
}
}
// load
foreach (var floor in savedFloors)
{
Instantiate(Resources.Load("Floors/" + floor.name), floor.position, floor.rotation);
}
How are you loading “obj” when generating the level in the first place? If it’s by using Resources.Load with a string somewhere you already have the path you need to save there, just keep it around for future reference.
The level prefab has an array of gameobjects for each type. This was the method used in the RogueLike tutorial so i’ve continued it. For example you have 8 floortiles and you put it in the array as part of creating the level prefab. Then the generation picks a random object from that array and instantiates it each time it needs a floor tile.
From what I have been reading is GameObjects can not be serialized. It throws an exception.
So you placed your prefabs in a folder then were able to find them with a tag and reload the gameobjects in your next application runtime?
Once again I got trapped in a Unity development scheme and hit a brick wall. I have a generated gameobject that I want to save off and reload as an asset into another unity usage.
Unity stating that they only support game usage dev is seriously very stupid. The amount of companys that want this type of product showcase type software is huge and Unity doesnt want to address this. I have added SimpleSql for data but cant get the gameobjects stored.
If anyone sees this and wants to do a work around it is also a good idea to have a single prefab of the type or types of GameObjects you want the player to be able to spawn/save and use a saving mechanic on the component information/values to apply at run time when loading the original prefab instead of saving a whole new prefab. You could save a bunch of different values just for it to have multiple options to choose from to load. Just my idea to mitigate the issue. Obviously this comes with the presumption that you already have a mechanic to save the game. I recommend EasySave3 if you don’t want to take weeks - months to make a really intricate save system. It’s what I use. Even though it’s difficult to understand right away it is still much easier than making your own.