- Home /
Collider on Skinned Mesh
Hello all.
I have Shinned Mesh with 2 bones for nonlinear Scalind (GO change from one side of axis). But Mesh Collider does not change its shape following the change in the mesh.
Maybe are there other methods for nonlinear Scaling if this unsolvable problem?
Answer by rageingnonsense · Sep 23, 2015 at 05:49 PM
This is an old post, but I figured I would answer because there is a much simpler way to do this (at least in Unity 5, not sure if this would have worked at the time the question was posed):
SkinnedMeshRenderer meshRenderer;
MeshCollider collider;
public void UpdateCollider() {
Mesh colliderMesh = new Mesh();
meshRenderer.BakeMesh(colliderMesh);
collider.sharedMesh = null;
collider.sharedMesh = colliderMesh;
}
You would of course initialize the MeshCollider and SkinnedMeshRenderer.
This takes a snapshot of the deformed mesh, applies it to colliderMesh, then uses that for the MeshCollider. you just need to call it when you want to update the collider to match the mesh
Thanks I will try it. I am not so sure about the slowdown, maybe it is very feasible with a proxy low poly mesh, I will make a test
You can just update it twice a second ins$$anonymous$$d of every frame:
// Start is called before the first frame update
void Start()
{
meshRenderer = GetComponent<Skinned$$anonymous$$eshRenderer>();
collider = GetComponent<$$anonymous$$eshCollider>();
}
private float time = 0;
// Update is called once per frame
void Update()
{
time += Time.deltaTime;
if (time >= 0.5f)
{
time = 0;
UpdateCollider();
}
}
Skinned$$anonymous$$eshRenderer meshRenderer;
$$anonymous$$eshCollider collider;
public void UpdateCollider()
{
$$anonymous$$esh collider$$anonymous$$esh = new $$anonymous$$esh();
meshRenderer.Bake$$anonymous$$esh(collider$$anonymous$$esh);
collider.shared$$anonymous$$esh = null;
collider.shared$$anonymous$$esh = collider$$anonymous$$esh;
}
Note that $$anonymous$$esh objects do not get destroyed automatically. So your code as well as the code in this answer will cause more and more memory to be allocated. If you want to create a new mesh each time you should destroy the old one. However it would make much more sense to reuse the same $$anonymous$$esh instance and just clear it before re-baking.
Answer by Eric5h5 · Dec 23, 2010 at 03:07 PM
You wouldn't want the mesh collider to update with a skinned mesh even if it was possible, since it would be very slow. You can attach primitive colliders to bones instead.
Update shared$$anonymous$$esh of $$anonymous$$esh Collider does not alter the shape collider. Changes only the base mesh. Is there a way to change the collider at runtime?
If I could use a primitive Collider, certainly would have done it. But thanks.
This is the first thing I did before asking a question. I'll try to solve the problem by any design method. Thank you.
That means manually going through each bone and adjusting the colliders to match the skinned mesh, right? And still not always get a satisfying result, depending on the mesh or on your needs... Also, way too troublesome. But, it has its usage, being the fastest way to process colliders and all. Lastly, yes we would want that for sporadic usage. ;-)
I am not so sure about the slowdown, you can use a proxy low poly mesh of the skinned mesh and use that as a collider, better than primitive all over the bones. I will make a test.
Answer by mattirwin · Jan 26, 2011 at 09:39 PM
I found a script to do this on the forum from user Darkrobyn. I believe this code reproduces the calculations that Unity is doing internally to deform the mesh.
It's working for me, but I currently have a fairly simple mesh and bone setup. I'm firing the forceUpdate occasionally (on mouse up events) which works great in my application.
Have a look here:
http://forum.unity3d.com/threads/14378-Raycast-without-colliders
The poster didn't include a couple of custom classes that you'll have to add. Something like this:
class CVertexWeight {
public int index;
public Vector3 localPosition;
public float weight;
public CVertexWeight(int i, Vector3 p, float w)
{
index = i;
localPosition = p;
weight = w;
}
}
class CWeightList {
public Transform transform;
public ArrayList weights;
public CWeightList()
{
weights = new ArrayList();
}
}
A capital C is sometimes used as a prefix for class names to indicate that it's a class. I just followed the na$$anonymous$$g in the original script. If you download the original script you'll find those classes are missing.
Answer by itsnarutofan · Apr 15 at 03:19 PM
You Can Watch This Video :- https://youtu.be/M4IGWELxR9c