I am familiar with the common method of creating a world for a 3D platformer, where game objects are painted on a grid to create a world, as illustrated here:
However, in doing so, it seems apparent that you may paint hundreds of game objects just to create a small level environment. This creates hundreds of game objects for your project to manage.
It strikes me that a more efficient way would be to instead code the environment grid as a List. So for example, I imagine you could have, for a 3D rendered 2D platformer (like a Mario game) where the character moves hypothetically in X (horizontal) and Y (vertical):
class WorldObjects{
public position Vector3;
public int objectType; //could be an enum representing types of blocks, enemies, ladders, etc.
public bool currentlyRendered = false;
//other parameters needed perhaps
}
//program the list of world objects here:
List<WorldObjects> worldObjects = new List<WorldObjects>();
worldObjects.Add(new WorldObject{position= new Vector3(0,0,0), objectType=0});
Then on an Update loop, you can poll the camera view range to see what range of positions should be visible and need to be rendered (assuming you only want to render things in vision range).
So for example, camera bounds can be used by camera.ViewportToWorldPoint for each of the four corners of your viewport rect. I understand the z of the Vector3 for this is how far the camera is from the play area plane. Bottom-left of the viewport is (0,0); the top-right is (1,1).
So you can run routinely after each given increment of camera motion:
Vector3 bottomLeft = camera.ViewportToWorldPoint(new Vector3(0, 0, cameraDistanceToGamePlay));
Vector3 topRight = camera.ViewportToWorldPoint(new Vector3(1, 1, cameraDistanceToGamePlay));
for (int i=0;i<worldObjects.Count;i++){
bool shouldRender = false;
if (worldObjects.position.x > bottomLeft.x && worldObjects.position.x < topRight.x){
if (worldObjects.position.y > bottomLeft.y && worldObjects.position.y < topRight.y){
shouldRender = true;
}
}
if (shouldRender){
if (!worldObjects[i].currentlyRendered){
renderThisObject(worldObjects[i]); //function to take needed object from object pool and render it
}
}
else{
unRenderThisObject(worldObjects[i]); // function to cannibalize the object used to render it and return it to the `free` pool
}
worldObjects[i].currentlyRendered = shouldRender;
}
I recall seeing a video of how MineCraft was able to manifest such massive worlds and I believe it used a similar method. I am just wondering before I undertake this if this is a normal approach am I considering or foolish. Or if other people are routinely doing this how they are handling it compared to how I imagined above.
In principle, recycling objects and enemies, environment, etc. can keep the total GameObject count down which might be more efficient overall for weak environments like mobile. It might allow you to make each GameObject more detailed or more complex without overloading the system.