Hello guys, I made a small script that simulates Rubber, like 3dsMax flex modifier does, but using vertex colors to set the effect intensity. Besides rubber objects, can also help to make more realistic the character animation, with some gravity, elasticity and inertia on some mesh part, like a big belly when moving. I hope you enjoy! Browser example: http://bit.ly/cQMs4h Code (csharp): /* ******************************************************************************************************* * * RUBBER EFFECT * * You need to set the Vertex Colors of your 3d model, on your prefered 3d Modelling Tool * * by Rodrigo Pegorari - 2010 - [url]http://rodrigopegorari.net[/url] * * based on the Processing 'Chain' code example ([url]http://www.processing.org/learning/topics/chain.html[/url]) * * ******************************************************************************************************* */ using UnityEngine; using System.Collections; public class RubberEffect : MonoBehaviour { public RubberType Presets; public enum RubberType { Custom, RubberDuck, HardRubber, Jelly, SoftLatex } public float EffectIntensity = 1; public float gravity = 0; public float damping = 0.7f; public float mass = 1; public float stiffness = 0.2f; private Mesh WorkingMesh; private Mesh OriginalMesh; private float[] ColorIntensity; private VertexRubber[] vr; internal class VertexRubber { public float v_gravity; public float v_mass; public float v_stiffness; public float v_damping; public Vector3 pos; Vector3 vel = new Vector3(); public VertexRubber(Vector3 v_target, float m, float g, float s, float d) { v_gravity = g; v_mass = m; v_stiffness = s; v_damping = d; pos = v_target; } public void update(Vector3 target) { Vector3 force = new Vector3(); Vector3 acc = new Vector3(); force.x = (target.x - pos.x) * v_stiffness; acc.x = force.x / v_mass; vel.x = v_damping * (vel.x + acc.x); pos.x += vel.x; force.y = (target.y - pos.y) * v_stiffness; force.y -= v_gravity / 10; acc.y = force.y / v_mass; vel.y = v_damping * (vel.y + acc.y); pos.y += vel.y; force.z = (target.z - pos.z) * v_stiffness; acc.z = force.z / v_mass; vel.z = v_damping * (vel.z + acc.z); pos.z += vel.z; } } void Start(){ Debug.Log(Presets); MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter)); OriginalMesh = filter.sharedMesh; WorkingMesh = Instantiate(filter.sharedMesh) as Mesh; filter.sharedMesh = WorkingMesh; ColorIntensity = new float[OriginalMesh.vertices.Length]; vr = new VertexRubber[OriginalMesh.vertices.Length]; for (int i = 0; i < OriginalMesh.vertices.Length; i++) { ColorIntensity[i] = (1 - ((OriginalMesh.colors[i].r + OriginalMesh.colors[i].g + OriginalMesh.colors[i].b) / 3)) * EffectIntensity; vr[i] = new VertexRubber(transform.TransformPoint(OriginalMesh.vertices[i]), mass, gravity, stiffness, damping); } } void Update() { checkPreset(); Vector3[] V3_WorkingMesh = OriginalMesh.vertices; for (int i = 0; i < V3_WorkingMesh.Length; i++) { if (!float.Equals(ColorIntensity[i],0f)){ Vector3 v3_target = transform.TransformPoint(V3_WorkingMesh[i]); vr[i].v_gravity = gravity; vr[i].v_mass = mass; vr[i].v_stiffness = stiffness; vr[i].v_damping = damping; vr[i].update(v3_target); v3_target = transform.InverseTransformPoint(vr[i].pos); V3_WorkingMesh[i] = Vector3.Lerp(V3_WorkingMesh[i], v3_target, ColorIntensity[i] * EffectIntensity); } } WorkingMesh.vertices = V3_WorkingMesh; WorkingMesh.RecalculateBounds(); } void checkPreset() { switch (Presets) { case RubberType.HardRubber: gravity = 0f; mass = 8f; stiffness = 0.5f; damping = 0.9f; EffectIntensity = 0.5f; break; case RubberType.Jelly: gravity = 0f; mass = 1f; stiffness = 0.95f; damping = 0.95f; EffectIntensity = 1f; break; case RubberType.RubberDuck: gravity = 0f; mass = 2f; stiffness = 0.5f; damping = 0.85f; EffectIntensity = 1f; break; case RubberType.SoftLatex: gravity = 1f; mass = 0.9f; stiffness = 0.3f; damping = 0.25f; EffectIntensity = 1f; break; } } }
Great job! I've been looking for a quick and easy way to do this myself in my free time, without resorting to joints and colliders. Thanks for a wonderful share with the community. BTW the project package link on your site is borked.
I had forgotten about this script. I wonder if it might somehow be used with a ragdoll to make interaction with it more realistic... hmmm...
The soft bodies in Unity 3 are more like "deflated bodies"... This rubber duck is much nicer. But I couldn't get it to work with a model of my own. The mesh just shattered (made in Blender). Any tips on what the limitations are for a mesh to use with this script?
This is super awesome! Is there a way to modify it to work with bone rotation only? Say you have a character with a pony tail, and you wanted the bones rotation to be effected by inertia?
Hello!! , I need to do something like that, but when a sphere collides with the duck, how can I do this? Thanks for your answer.
What problems are you having? Do you have errors? The script is almost 10 years old so there may be things that need to be updated to current API.
It works fine in Unity 2021.3.20f1. You just need to make read/write available in settings of the exported mesh. And also don't forget to vertex paint you mesh before exporting in Unity.