- Home /
Best practice instantiating objects from code
I'm currently developing a RTS which includes a self made random map generator. Every prefab must be loaded from code, there is nothing in my scene except a Camera. What is the best way to load all the prefabs?
Let's say I have several buildings and unit types. I don't want to use Resource.Load every time I create a building or a unit, that's not good for performance.
Do I create a static class with all references to every prefab and load them at the start of the game? Do I create a database or something likewise?
I can't seem to find a solution on the internet. Also, almost everyone uses the editor. All help is appreciated.
Edit: After some more research I'm actually looking for object pooling with resources loaded from code. Anyone got this working?
Well my suggestion would be to create a static management class with a Dictionary that has the prefabs and an enum for each Unit type. Then use Resources to load them as needed, and through the life of a game, you will likely end up with all prefabs loaded, but without the cost of loading them all at once. An example would be...
public static class Unit$$anonymous$$anager
{
public enum UnitType { Soldier, Archer, Catapult }
private static Dictionary<UnitType, GameObject> units;
public static GameObject GetUnit(UnitType unitType)
{
if (units == null)
{
units = new Dictionary<UnitType, GameObject>();
}
if (!units.Contains$$anonymous$$ey(unitType)
{
units.Add(unitType, Resources.Load<GameObject>("units/" + unitType.ToString()));
}
return units[unitType];
}
}
then you just need to name your prefabs the exact same names as the UnitType enums.
The instantiation process can occur elsewhere in your pooling system. This is just how I would handle the resources side, as far as pooling goes, pooling is pretty simple, you can still use the enum too, like this.
public static Dictionary<UnitType, List<GameObject> existingUnits;
public static GameObject GetExistingUnit(UnitType unitType)
{
if (existingUnits == null)
{
existingUnits = new Dictionary<UnitType, List<GameObject>();
}
if (existingUnits.Contains$$anonymous$$ey(unitType))
{
if (existingUnits[unitType].Count > 0)
{
GameObject unit = existingUnits[unitType][0];
existingUnits[unitType].Remove(unit);
return unit;
}
}
return GetUnit(unitType);
}
public static void AddUnit(GameObject unit, UnitType unitType)
{
if (existingUnits == null)
{
existingUnits = new Dictionary<UnitType, List<GameObject>();
}
if (!existingUnits.Contains$$anonymous$$ey(unitType))
{
existingUnits.Add(unitType, new List<GameObject>());
}
existingUnits[unitType].Add(unit);
}
Hope this helps, and makes sense :)
Answer by tMahon · May 22, 2017 at 04:53 PM
Use the prefabs and reference them using a serialized field, then use GameObject.Instantiate() to create them. Check out the overloads for Instantiate in the documentation, you can set whatever you need as you create it. Beyond that, there's a really good tutorial for procedural tile creation if you look at the first 2 parts of the RogueLike Tutorial found here.
I know how to instantiate objects, I just want the prefabs loaded in memory. I'm looking for an efficient way to do this. I don't want to "get" the prefab by using Resources.Load every time I instantiate a new object.
You only need to load a resource once, then you can instantiate it as often as you want.
bobisgod is correct, but actually t$$anonymous$$ahon's solution does not require you to use Resources.Load at all.
You'll probably want to have some kind of factory or manager object handling the map creation, which will have fields that are references to the prefabs.
If this is a scene object then you can make those fields public and just hook up the prefabs to those fields in the inspector. Then you can instantiate them without using Resources.Load. (t$$anonymous$$ahon's solution)
OR if you don't want to hook them up in the inspector, you can load them using Resources.Load and as bob says you only need to do it once. One way to handle this would be to just load them all in the factory object's constructor (or Awake function of course, if it's a GameObject). Or if you want to be sure that you only load the prefabs you're using, you could use a "lazy" approach; checking each prefab field for null before use and loading it if required.
Your answer
Follow this Question
Related Questions
Reducing draw calls unity simple randomly generated world? 0 Answers
About to gut my use of the Resources folder. What are the best practices going forward? 1 Answer
What is the best way to load an instance of a gameObject when loading a saved game? 0 Answers
Do bulk prefabs cause performance issues? 2 Answers
Layers, Prefabs and Build Settings have been deleted 1 Answer