One thing I always wonder when people use DrawMeshInstanced / Indirect, is how do they setup the collision detection when there isn’t a GameObject.
AFAIK, in games with very large and dynamic map, like Cities Skylines, collisions are simply ignored. But what if you are an action game, how do you stop the player from getting into geometry? Raycast against movement direction? Use map data to prevent players from moving into invalid position?
In short: I am going the DrawMeshInstanced rendering route, and realized I can’t use the built-in collision system without gameobject, what could I do?
(There is also the question of NPC navigation, but given I have the data for rendering, I can build a grid map or flow field for that, so less of an issue.)
I don’t have GameObjects associated with rendered geometries (eg. no GameObject / MeshRenderer in scene), so I can’t use Collider / Rigidbody component neither.
Your could have game objects with no renderer only collider and use that for the physics simulation. Than use the gameobject transform to draw the mesh on the correct place
My problem isn’t really genre specific, but rather I am trying to render geometries with DrawMeshInstanced and do manual culling myself. Hence I have this “no gameobject” problem.
(I didn’t aim for zero gameobject, just avoiding gameobjects in general for performance sake, as the level is dynamic and contains modular pieces; otherwise I would have combine mesh and use mesh collider…)
I could do that, but given the number of modular pieces, I would either need:
many gameobject, primitive collider, no mesh needed.
fewer gameobject, some logical grouping and mesh collider, require combined mesh to create fitting collider.
no gameobject, render directly, but come up with some smart custom collision detections and triggers.
I can reasonably pick 2 or 3; I was heavily invested in option 3 and came up with a good render strategy but now have to come up with a collision detection solution…
Let’s imagine a simple scenario:
Say our game is like a lot (aka a house) in The Sims.
Say we can control a character that walks inside this house
Say we can build/demolish rooms as we see fit.
Now, given the number of modular pieces here: Option 3 seems like a good strategy, until I realize it’s a bit of a problem when you give direct control of character to player.
If the control is like The Sims, then I can simply check for valid position and move using a navigation system, backed by the map data.
But since players have direct control, collision detection is needed, so Option 2 seems like a better strategy, but performance of Mesh Collider does concerns me even if we combine pieces per room…
You are probably better to use PhysX native features, as these are highly optimized, for collisions.
And are multi threaded.
Other than that, it seams you are starting worry far too early. It appears you talking mainly about static colliders.
Did you run any stress tests and profiler, to confirm any of your concerns? Please do if you haven’t and post here results. Then we can start worry, how to improve, if needed.
Edit:
For sake of discussion, I did while ago stress test of 5k falling and colliding stack blocks at the same time with each other. The lag happens, when all hit the ground at the same time. That means at least 5k pairs of collisions. Probably more than 10k at given frame. That heck a lot for most games. No much issue with 1000. And if you got only few collision per frame, that nothing to worry. How many objects in on the scene is least relevant.
Yeah. Composites are well optimized with PhysX.
Making own collision system, will probably lead to bottle neck, if not deep into the subject.
Jobs and DOTS will be more suitable for that purpose.
True, kinda why I want to run it through people here to see if it’s something people do.
I know there are solutions with ECS here but because I am on 2018 LTS and want to avoid building on a changing API, I would pass on ECS for this project.
This is kinda a noob question: but if we add/remove mesh at runtime, we can’t use Static Collider, right?
True, I haven’t benchmarked using compound collider, my intuition is to avoid gameobjects because I already did with rendering, but that could be wrong… I really wish there is a more lightweight “gameobject” (and I know ECS has that, but alas…)
I am curious about this one, you mean compound collider right? Are they all moving? Are they mostly static?
My baseline is laptop computers but they should have decent CPU nowadays.
My compound colliders example. I use ECS here. But colliders are still on GameObjects using PhysX. Colliders are visible on the video, as green gizmos, when I move quickly objects.
But Dynamic colliders have sleep method. Which is automatically handled. That allows to save on calculations.
Compounds colliders are handled a little different, but by much.
When I go purely the DrawMeshInstanced route, there are no GameObjects for the individual units in the scene. So any movement and collisions are handled manually by my own code. I create a class I call an Instancing Pool. My instancing pool contains an array of a custom struct to hold all of the information about the units in the scene as pure data.
Doing an instancing pool for a bunch of lasers is easy. Each laser unit will scan forward a small amount each frame using a raycast to see if the laser will hit any objects in the scene. And lasers do not have to check to collisions with other lasers.
When things get more complicated is when trying to build an instancing pool for units that do need to accept collisions. For example, if you want to make a massive asteroid field with thousands of asteroids floating around in the scene, then you would need to manually implement basic collision detection functions into the instancing pool class. The units would need to check for collisions with each other and expose a public function so other objects in the scene can ask the instancing pool if those objects would collide with any units in the instancing pool.
It depends on the implementation. Using a purely data oriented approach like instancing pools using DrawMeshInstanced can result in massive performance benefits when handling many thousands of active units in a scene. It outperforms GameObjects by a huge margin in that case.
For the lasers in Disputed Space, my instancing pool design outperformed object pools by a factor of about 6x. I have scenes with 10,000 lasers flying around with triple digit frame rates on PC. That was a game I released on Steam in 2017 that I built in Unity 5.5, so this was before ECS was available.
Thats pretty interesting - just watched the video - yeah you have a ton of lasers flying around. It’s an interesting example cuz the lasers themselves dont need collision. So yeah, you can just raycast against the ship colliders without needing to do all that stuff by hand. Smart.
Thx for sharing your method, this is kinda what I had in mind, I think my problem is slightly more complex as it’s a player-controlled character colliding with walls and large in-world objects, it’s basically collision prediction with non-constant speed/acceleration/direction.
By the way, does your ship use GameObject and Collider? If not I guess you have to store and check against AABB (Bounding volume).
I would take a step back, throw out any assumptions not based on actual testing. Do you know the performance difference between DrawMesh* and just having gameobjects in your project not just theory?
Start with the simple approaches first. Gameobjects with colliders and good LOD will take you a very long ways. Much further then you are thinking it will I guarantee that much.
Optimizing rendering and colliders starts with modeling and good design. Looking for ways to standardize/modularize so that you can use simple primitives colliders, etc…