For a procedurally generated terrain, I’m generating a static mesh at runtime in C++, which the player is intended to be able to walk on. I’m using FStaticMeshBuilder as shown below.
This “works” in that it correctly builds/textures/lights the mesh, but the player actor just falls through it. If I use the FBuildMeshDescriptionsParams “bBuildSimpleCollision”, it generates a box collision for the terrain, which means the player basically walks on an invisible floor at whatever the greatest height is for that terrain mesh.
I assume I’m missing something simple. How do I tell the UStaticMesh or the UStaticMeshComponent to use the mesh itself as its own collision shape? (Targeting Unreal Engine 5.5, so I should have everything available).
// Static Mesh generation
FMeshDescription meshDesc;
FStaticMeshAttributes Attributes(meshDesc);
Attributes.Register();
FMeshDescriptionBuilder meshDescBuilder;
< bunch of stuff to fill in the vertices and such here>
UStaticMesh::FBuildMeshDescriptionsParams mdParams;
>> If this line is true, we get a valid box collision.
// mdParams.bBuildSimpleCollision = true;
mdParams.bFastBuild = true;
FStaticMeshOperations::ComputeTriangleTangentsAndNormals(meshDesc);
FStaticMeshOperations::ComputeTangentsAndNormals(meshDesc, EComputeNTBsFlags::Normals);
// Build static mesh
TArray<const FMeshDescription*> meshDescPtrs;
meshDescPtrs.Emplace(&meshDesc);
staticMesh->BuildFromMeshDescriptions(meshDescPtrs, mdParams);
// Assign new static mesh to the static mesh component
TerrainMesh2->SetStaticMesh(staticMesh);
ProceduralMeshComponent seems to do this automatically, but I’m intending to use Runtime Virtual Texturing, which doesn’t work with Procedural Meshes.
Is there a property or function to use complex as simple collision?
edit: Something like this…
#include "PhysicsEngine/BodySetup.h"
comp.GetBodySetup()->CollisionTraceFlag = ECollisionTraceFlag::CTF_UseComplexAsSimple;
where comp is a UStaticMeshComponent
edit2: Hmm… seems to be an editor only flag. But you could try it. I’ve only used the Realtime Runtime Mesh Component plugin and it has a callback to configure the collisions where you can generate your own mesh or just set ComplexAsSimple.
Yeah, no such luck. Even in the editor, that doesn’t actually seem to create the collision. Nor does setting the UStaticMesh’s ComplexCollision mesh to a pointer to itself.
I’ve tried RMC, but one of my targets is macOS, and RMC seems to consider mac compatibility something of a second-tier priority, so I’ve had some troubles with it. And at least until now, I didn’t need it’s main feature, which is very high performance.
My code at the moment has a hardcoded switch that lets me change between UProceduralMeshComponent (which works fine, including the collision) and UStaticMeshComponent (which looks identical, given identical seeds).
Main differences seem to me:
Procedural Mesh:
- Very fast – a fraction of a second to build a half kilometer square “landscape” with meter resolution.
- PCG (Procedural Content Generation) supports it easily with the World Raycast Query.
- Supposedly doesn’t support Runtime Virtual Texturing, although I haven’t tried it.
- A lot less flexible on things like multiple normals for a vertex, UV layers, etc.
Static Mesh:
- Very, very slow: 2-3 seconds to build the same landscape grid. (On my to-do list for the weekend is to try and find out what’s taking all that time with the profiler. Or if some wise reader of this knows, my code is above. I sort of suspect the MeshBuilder, that it might be much faster if I just created the mesh description manually.).
- The PCG World Raycast query isn’t finding the surface, nor does a Mesh Sampler seem to work even if I pass the static mesh to it directly through an Actor property. This might be related to…
- I still can’t figure out how to get the component to use its mesh as its collision shape. I’ve tried everything that I could find that seems to be related without effect.
- Much more flexible with shared and such, especially once I start adding hard edges, holes, etc. Since these meshes may eventually be voxels, this would make my life (a little) easier.
That performance hit makes Static Mesh unacceptable for my game in its current form, anyway, but I suspect that I could fix it. But it’s not worth investing too much time in unless I can figure out how to turn on pawn collision for it. I can probably live with the limitations of UProceduralMeshComponent if I have to, or I can take another look at RMC.
But I’m still hoping someone sees this and says “You idiot, you just need to set the (whatever) boolean like this…”
I think even with RMC, you still need a closed shape for collision. So you’d need to make a shape underneath the landscape to close it off. In an earlier failed game attempt of mine, I had used RMC and looking over my code, I had chosen to create my own simple geometry (it was a hex grid landscape). I created a convex volume for each hex cell and this worked great. IIRC, just using ComplexAsSimple didn’t work because my character would still fall through the seams or wouldn’t work correctly because the shape was too big. Or something like that… I’m not quite sure. RMC also lets you convert whatever you have to a static mesh in the editor. Not sure if that code would show any insights. Or how it sets collision at rutime.
Hopefully someone else can chime in and help you. I’d personally be interested in what you find since I want to revisit my old project at some point.