Unity : can I change the shape of a mesh collider at runtime? - unity3d

I have a mesh that updates it's shape according to the user's input, how can I get the collider to match the new shape of the mesh ?
As an important note : the mesh is always always convex ( no exceptions ). I saw that it is important in order for the collider to work properly.
I have found the following video that does it here but the collider is simply erased and recalculated for each frame by doing meshCollider.sharedMesh = null and then meshCollider.sharedMesh = updatedMesh.
Since I am already calculating the position of each vertex, edge and triangle of my mesh, is it possible to me to use those values for the mesh collider ?

No way to do it as colliders do not have constructors for this. What you are doing is explicitly frowned upon in unity docs
'You should not modify mesh geometry that is used for colliders because the physics engine has to rebuild an internal mesh collision acceleration structure every time you change the mesh. This causes a substantial performance overhead. For meshes that need to collide and change at runtime, it is often better to approximate the mesh shape with primitive colliders like capsules, spheres and boxes.'
One work around is to use InvokeRepeating on your method and create the new mesh collider every second instead of every frame (you can test and make it 0.1 second , 2 second, whatever can run without frame drops). You can call CancelInvoke when the object is done shifting.

Related

Most efficient way of calculating big terrain collision mesh

I'm using Unity Engine to make a space exploration game. I have to implement the collision system for the planet I made with quadsphere and quadtree LOD, I thought of two ways:
Generate a BIG mesh collider for the hole planet and keep the collision activated only for the face that the player is in (the planet has 6 faces). This works fine because the mesh is created only one time, but the game keeps a mesh collider bigger than needed in the scene.
Use the quadtree LOD and create a new mesh collider every second, but just for the high resolution terrain near the player. The mesh collider used in this option is way less bigger than the first option, but is updated every second.
Which way is more approachable? And there are more efficient methods than these two?

How to detect the collision with a surface as optimized as possible in Unity?

I have two colliders (of any type) and I would like to know if there is any optimized way to detect the collision of one trigger (SphereCollider for example) with the surface of the other (this is basically that by entering and staying on the surface of the object (mesh) gives collision and that being outside or inside the object there is no type of collision. I know I can achieve this effect by making a collider of the mesh surface but that would increase the number of polygons and I don't know if it could be the most optimized (since for example in a cube its surface would be basically 6 cubes)

Unity: Mesh Renderer seems to not fit the Edge perfectly

We are currently trying to lay mesh colliders onto our edges as shown in the pictures. The problem is that the meshes sometimes seem to be 2D instead of 3D (shown in Picture 2 and Picture 3), which makes them unselectable from certain camera-angles. Sometimes the meshes even seem to disappear through some parts of the Edge(Picture 1).
Turning convex on for the colliders makes them way easier to select, but we dont really want to do that because that makes it realy unclear which edge you are selecting right now.
We are creating our meshes through bakeMesh from our previously created Edges as shown below:
LineRenderer lineRenderer = gameEdge.GetComponent<LineRenderer>();
MeshCollider meshCollider = gameEdge.AddComponent<MeshCollider>();
Mesh mesh = new Mesh();
lineRenderer.BakeMesh(mesh, Camera.main, false);
meshCollider.sharedMesh = mesh;
meshCollider.convex = false;
Edit:
We used this https://github.com/mattatz/unity-tubular to generate tube meshes around our edges, working pretty well now!
The mesh generated by the line renderer is actually 2D. I think that your best chance is to update the mesh orientation to face to the camera so that the mesh will always be facing to the camera wherever you are looking from. That way you'll allways be able to click on it.
You have 2 options:
1.- Passing the new camera (with its new position) all the time. This would be in the Update. Be carefull to only use the code that bakes the mesh and not the Mesh mesh = new Mesh() in the update. Because if you create a new mesh in the Update passed some time you'll have an stack overflow error. I recomend if you do this, to make the Mesh mesh; a class variable and start it only in the class initialization (mesh = new Mesh();) so that you use only the created instance to update the mesh all the time, not creating a new one for each update.
2.- If you are concerned about efficiency, you can handle when your camera is moving, so that when it stops moving, you pass in the new camera along with its position. For this you would need to handle the camera OnStopMoving event yourself to pass the new camera in, so whenever the Main camera stops moving, the mesh will always be facing it.
This makes sense because its easier for the user to click on things while stopped, so it can be presumed that the user will try to click on the lines while not moving
There is one third option I did not mention due to feasability, that is wrapping your line renderer with primitive colliders with the points of your line as an starting point for the procedural collider wrapping logic. However you would need to code all that out, which might take a while.
On the other hand making it a convex collider as far as I checked is not feasable, as the behaviour and shape of the collider itself changes on the mesh cooking by the MeshRenderer component. Check if this might be of help.

Unity3D Collider Passing Through Other Colliders

The Problem: Mesh colliders on some rigidbody objects are passing through colliders on other objects.
Things I have tried:
With the assumption A is a GameObject with a RigidBody attached and B is a normal GameObject with a collider.
Give A a convex mesh collider
Give A a non-convex mesh collider
Give B a convex mesh collider
Give B a non-convex mesh collider
give B a box collider
give B a convex mesh and box collider
give B a non-convex mesh and box collider
Adjusting the weight of the rigidbody
I have tried all of these in all combinations of A and B.
In addition,
Colliders are not marked as triggers
All objects are on the default layer (0)
Checking isKinematic; doing this seemed to make gravity stop affecting the object, so I have left it as false.
Constraints: I want A to use a mesh collider since most of the objects involved are moderately complex, and fitting other colliders to them would take a while.
Weird Behaviour: I have some objects with both rigidbody and convex mesh collider where the collision is working fine with a non-convex mesh collider. This is inconsistent with other gameobjects. The objects have all of the same settings.
I am using unity version 2019.3.11f1 if that is relevant.
The object being used are from this package. Specifically, the filing cabinet with rigidbodies on the drawers works fine. The desk, office chair, pen, and open laptop all fall through the "floor" (a cube with all of the above colliders tested on it).
Do you have 'isKinematic' checked on the objects with rigidbodies that are going through other colliders? If so uncheck it so that external forces affect it.
edit you also need to click convex on the mesh colliders if they are colliding with other mesh colliders, Convex Mesh Colliders are limited to 255 triangles, are the objects that are not passing through have more than 255 triangles in geometry?
I am Assuming you have set your Collision Detection to Discrete In your gameObject's RigidBody, if so, please make sure to select Collision Detection to Continuous In your gameObject's RigidBody.
Reason Why this is not working
You are trying to use collision that has (speed > your Computer's frame speed) so, the frame is not catching the collider properly some time catches and some time fails to catch.
You are moving your GameObjects with tranform.translate or position etc. If so then make sure to use Rigidbody Related function for Positioning, rotating.
Solution Image For First Problem
I'm assuming
-you game object which contain the mesh component is very small ( bellow 0.7 size(x,y,z) so the game engine is little difficult to detect it)
and also
for the colliding objects at-least one rigid-body component must be attach to one object
This seems to be a common big problem, and I have been struggling with the same issue for days, and have finally fixed it, so am feeling like I should highlight one important thing:
move Rigidbody via MovePosition, not via just changing its position field directly, nor via changing position of GameObject holding it.
Changing position via "wrong" ways will "teleport" your rigidbody, physics won't fully work on it in that case.

Blender import in Unity, how to generate correct mesh collider?

How to get/generate a proper mesh collider in Unity using a model exported from Blender (.obj/.fbx)?
This is my second day using Blender and I'm hitting a roadblock. I've tried fiddling with the Rigid Body Collisions, i.e., setting "Shape" to Convex Hull and "Source" to Final/Deformed (Blender docs specify that these two settings capture modifiers), I've tried "Generate Colliders" inside Unity and the mesh collider always comes out as above. A box.
How to assign mesh collider to the exact mesh? I started with a circle and used a boolean modifier to create the cutout. Desire is to have the mesh collider around the mesh exactly, meaning no collider on the cutout. How to do this?
Make sure you have a Mesh Collider component on your object with the correct mesh set. Watch out for the convex parameter for flat objects, as it can sometimes fail and give you a box collider instead.
Edit:
I just noticed you said you were using a RigidBody, which means you need to have Convex set. A solution to this is to make a second mesh in Blender with a third dimension to it, then set the flat one on the Mesh Filter and the one with thickness to the Mesh Collider.
In importing a .obj or a .fbx, select the asset. make sure you have generate colliders selected.
Here I have imported an FBX into unity, but there are no colliders.
Sellect the asset, and turn on generate colliders if you want a collider around the mesh: