v.0.1.2 Released


This was a good practice to learn how one can deform 3d vertices in Unity. Once a mesh is readable/writable, it is a piece of cake.

Here is the full script to enable the deformation.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshCollider), typeof(MeshFilter))]
public class DeformableObject : ClickableObject
{
    [SerializeField]
    private float softness = 0.05f;
    [SerializeField]
    private float impactRadius = 0.1f;
    [SerializeField]
    private float springness = 0.5f;
    [SerializeField]
    private float touchImpactMagnitude = 25.0f;
    [SerializeField]
    private float maxVertexDispositionRadius = 0.2f;
    private MeshCollider meshColliderComp = null;
    private Mesh meshComp = null;
    private Vector3[] initialVertices = null;
    private Vector3[] vertices = null;
    private void Awake()
    {
        meshColliderComp = GetComponent<meshcollider>();
        MeshFilter meshFilter = GetComponent<meshfilter>();
        if (meshFilter != null)
        {
            meshComp = meshFilter.mesh;
        }
        Debug.Assert(meshColliderComp != null || meshComp != null);
        initialVertices = meshComp.vertices;
    }
    private void OnCollisionEnter(Collision collision)
    {
        // Use single contact point for now.
        Vector3 impactPoint = transform.InverseTransformPoint(collision.GetContact(0).point);
        Vector3 impactNormal = transform.InverseTransformDirection(collision.GetContact(0).normal);
        float impulseMagnitude = collision.impulse.magnitude;
        DeformMesh(impactPoint, impactNormal, impulseMagnitude);
    }
    private void FixedUpdate()
    {
        vertices = meshComp.vertices;
        int vertexCount = vertices.Length;
        for (int i = 0; i < vertexCount; ++i)
        {
            float alpha = Mathf.Clamp(springness * Time.fixedDeltaTime, 0.0f, 1.0f);
            vertices[i] = Vector3.Lerp(vertices[i], initialVertices[i], alpha);
        }
        meshComp.vertices = vertices;
        meshColliderComp.sharedMesh = meshComp;
        meshComp.RecalculateNormals();
        meshComp.RecalculateBounds();
    }
    public override void Click(ClickEvent cEvent)
    {
        base.Click(cEvent);
        Vector3 impactPoint = transform.InverseTransformPoint(cEvent.position);
        Vector3 impactNormal = transform.InverseTransformDirection(cEvent.direction);
        DeformMesh(impactPoint, impactNormal, touchImpactMagnitude);
    }
    private void DeformMesh(Vector3 impactPoint, Vector3 impactNormal, float impulseMagnitude)
    {
        vertices = meshComp.vertices;
        float scale = 1.0f;
        int vertexCount = vertices.Length;
        for (int i = 0; i < vertexCount; ++i)
        {
            scale = Mathf.Clamp(impactRadius - (impactPoint - vertices[i]).magnitude, 0.0f, impactRadius);
            scale = Mathf.Clamp(impulseMagnitude * scale * softness, 0.0f, maxVertexDispositionRadius);
            vertices[i] += impactNormal * scale;
        }
        meshComp.vertices = vertices;
        meshColliderComp.sharedMesh = meshComp;
        meshComp.RecalculateNormals();
        meshComp.RecalculateBounds();
    }
    private void OnApplicationQuit()
    {
        meshComp.vertices = initialVertices;
    }
}

You can access all the files from the git repo.

Currently, this code is not optimized at all! I am reassigning its vertices each frame and also making it recalculate its normals and bounds. This is not a quality code at all. But, my purpose was to do a quick deformable mesh so this covers it. I may refactor it to be more optimized later (this means it will stay this way).

Files

PhysicsBox_v_0_1_2.zip 8 MB
Sep 01, 2020

Get Physics Box

Leave a comment

Log in with itch.io to leave a comment.