I am making a game that is an ode to zelda, here's a gif:
I am currently in the early stages, trying to settle on a workflow that will allow me to smash out maps and environments while achieving certain goals. Those goals are:
- Each map 'section' is a small, discrete area that is loaded as a separate level. The player leaves one area via an exit and the game loads the next area, and unloads the previous.
- Reduce draw calls by any means necessary
- Use modular assets to accelerate development
- Be able to hand place assets
- Be able to go back and edit maps without much hassle
I am trying to optimize the hell out of this because I'd love to be able to make it a phone game, and I'm an optimization
nut. It might not end up being mobile, but I'd still like to optimize for it as a part of my workflow.
In order to cut down on draw calls while still using modular assets, I am building my maps in Blender using the different assets (trees, ledges, ground tiles etc) and then joining all the meshes and exporting as a single .fbx. Here's that map above reimported into blender. You can see it's all one mesh (it's also all one material):
Creating my maps this way allows me the following:
- I can place ground tiles manually, and I will be using that in order to build texture-based paths on the ground as per my other thread
- I can use modular assets like the ledges in the example above in order to build my maps
- I can weld verts on those modular assets that I use in order to avoid shading artefacts in-engine
- I reduce the drawcalls on my static map assets greatly - that mesh all uses a single 64x64 pixel palette material
But it has the following drawbacks:
- The distance between building maps in blender and testing maps in game is quite far - it's much nicer to move modular assets in the editor
- I need to build the collision for my maps as blocking volumes in the UE editor, instead of relying on static mesh collisions. In the case of say, the trees, that means placing a lot of volumes around the map
I have some specific questions:
- Is it ok - in mobile gaming terms - to have an abundance of blocking volumes in an environment? Am I better off using box colliders? What is generally the most performant way to do environment collision like that?
- If I join all these meshes it creates a single mesh with heaps of verts. If the player is on the other side of the map then a lot of those verts will be drawing off camera, because it's one single mesh. Does that really matter? I could break it out so that each ledge with trees on top is a single mesh, and they can flick off when out of frame. That would increase draw calls when they are being rendered, but allows me to free up that memory quite readily.
- I am totally avoiding any alpha materials here and using verts instead - you can see that on the grass on the top of the ledge and the leaves on the trees. As I understand it, alpha materials are expensive on mobile as well as textures in general (phones don't have much VRAM, which is where textures get stored?) so if I can get away with no alphas and just use verts instead, I can avoid that whole fiasco. Phones can handle a lot of verts, but struggle with transparency rendering. Am I totally incorrect, and kneecapping myself with that assumption?
Can anyone offer some advice on potential pitfalls, incorrect assumptions or alternative methods for this kind of map creation? I'd really appreciate it!
Replies
To avoid drawing things that are off screen I could break out parts of the map and draw them in separately so each of those 'ledges' from the example would be their own static mesh, allowing me to cull them when they are off screen:
This would mean slightly more draw calls but nowhere near the amount I would have otherwise, and is neither here nor there in terms of workflow, it would just be an intermediate step in laying out the maps.
I would absolutely love to be able to place static meshes in the editor and have them all batched to the same draw calls per asset but as far as I can tell that's not a thing? Am I incorrect?
Also:
https://www.reddit.com/r/unrealengine/comments/aq7nf0/autoinstancing_test_in_ue422_preview_1/
Its actually there since 4.22 not 23. This was also causing me some issues with hand written shaders. I had to rewrite certain thing due to this change. So I was pretty certain that this is a thing.
I did find this very satisfying though, It's an Instanced Static Mesh component inside a blueprint, with 64 instances:
Unfortunately the ISM components are hard to work with, but I think I have an idea for some tools I can make in blueprint to get around that...