efficient building blocks (meshes)?

Hi!

If you were building a complex object out of building blocks, are there any things to consider when modeling the blocks or importing them into Unity?

For example, think of a toy railroad made of straight blocks and curved blocks. You could model those blocks and bring them into Unity and you could build basically any combination of the blocks, but would there be anything special to consider to make it efficient?

Thanks!

First and foremost, make as much building blocks use the same material as possible. Use atlases of textures rather than separate images to do so. It will allow for dynamic batching if your blocks are very light in term of vertices and static batching to reduce the number of draw calls.

Personnaly I use a lot vertex color to create variation of blocks or objects using the same texture. You can tint objects or create low frequency gradients and simple baked shadows.

Pay a lot of attention to how you model your building blocks to optimize them since you will use them many times.

Thanks for the texture tips! I was planning to simply use the same texture, but I must dig into vertex color and atlases a bit more

So apart from textures an materials, there’s nothing special to it?

In other words “a tri is a tri” regardless if you have 100 instances of 1 mesh or 100 meshes with the equivalent tri count?

When I talk about atlases, it doesn’t necessarily involve the packTextures method of unity to generate some. It is something you commonly do manually when you’re using your 3D package. It’s just something you don’t care about for precalculated work but which is crucial for any real time task. It implies a lot more of work when you ‘unwrap’ your mesh and a lot more of thinking to plan how your textures will be grouped and applied. For instance when you plan to tile a texture which is part of an atlas, you must have in mind that the tiling will have to coincide exactly with your mesh tessellation.

Now regarding “a tri is a tri”, I’m not sure what you mean or what you want to ask. I don’t know how Unity handles exactly mesh instanciation. Theoritically if you use multiple times the same mesh, there’s memory to be saved somewhere. There’s certainly a lot of loading time and application size that is spared. For the rendering in itself, the most critical parameter is often draw calls. Render a scene with 100 000 tris scattered in 100 000 objects of one each can be much more CPU intensive than a million tris in one object. In the first case you will have 100 000 draw calls (or a multiple of that depending on your shader), in the second scenario only one (or a few more depending on your shader). The conclusion is that no : a tri is not just a tri ^^

Grouping objects to decrease draw calls is primordial and you can achieve that manually or with Unity batching features ONLY if your objects share the same material (shader + textures).

To use vertex color, keep in mind that your shader will have to take it into account to see it. I don’t think Unity built in shaders use it but you can easily find some examples on www.unifycommunity.com
Just a few more tricks about vertex color :

  • it’s far more interesting to use a shader that will multiply its values by 2 since it’s multiplied with your diffuse texture. This way you can either lighten or darkenyour base texture with values above or under 0.5 / 0.5 / 0.5.
  • use it with texture colors that are not too saturated, it will be easier to find correct values to tint with the desired result.

Thanks for the reply!

Well, you pretty much answered what I was wondering about. I figured there must be some performance benefits in instantiating one mesh over having separate objects, but I wasn’t sure.

I’m aware of the “same material”-rule, but vertex-colors not so much - thanks for the pointers, must take a look at those.

I’d say the problem with building primitives into objects inside of Unity is that you can’t optimize tris out.

Say you want a capsule, so you add 2 spheres to each end of a cylinder. You’d end up with hidden faces on each end of the cylinder, plus 2 halves of spheres hidden within the cylinder. If the spheres and cylinder are 20 sided you’d have somewhere around 80 unseen tris, over just a capsule mesh. That’s just a simple example but it could add up.

Also, if they had the same material you’d still get 3 draw calls (1 light 1 shader) unless you add a child combiner script to the top game object (and the other 2 were children). A capsule object would only be 1 draw call. Not a big deal unless you have a lot of capsules… (If you have Pro dynamic batching would do that work for you)

I also assume vert colors would add an extra draw call per light since Unity would render the material as one pass and vert colors as another (that’s how it’s usually done so I assume Unity is the same). But it could save you unwrapping, baking ao (baking ao wouldn’t work good for objects combined in game, but then again, vert color might not work that great either. How could you paint in shading for basic objects that could be combined in multiple ways. If they are always to be combined in one way so vert colors are predictable you could just do that in 3d program and bake ao.

Unity primitives are only debug or test objects, no one use them as a modeling base I think.

Vertex color do not require any extra draw call in itself. Most of the time you just multiply the diffuse map by the vertex color once and it does not require any additional pass.

Though vertex color can be used to simulate very basic ambiant occlusion, its best use in my opinion is not that : It’s usefull to create color variation of the same texture. Thus you can have multiple objects using the very same material and which don’t look exactly identical. You can also create low frequency variation of color or luminosity, which you could do with another texture like with lightmapping but it would cost far more.

You don’t need Pro for dynamic batching. You do need it for static batching.

–Eric

@Krobill

Have you seen this ?

Nope, but it sure is very interesting. Thanks for the link !
Not sure if it will be practical for complex geometry where a lot of hide / show polys is often required but for quick simple objects it sure could save some time…