Sunday, April 9, 2023

Mesh deformation in unity tutorial

 




Code:

using System.Collections.Generic;

using UnityEngine;


public class DeformableVehicle : MonoBehaviour

{

    public MeshFilter[] meshFilters;

    private Vector3[][] originalVertices;

    private List <MeshCollider> meshColliders= new List<MeshCollider>();

    private Rigidbody rigidbody;


    public float deformationAmount = 1f,demageAmount=3;

    public float deformationRadius = 1.0f;

    public float minVelocity = 2;

    AudioSource audioSource;

    public AudioClip hitClip;

    public float resetDeformGap = 3;

    bool isDeformAble;


    void Start()

    {

        isDeformAble = true;


        audioSource = gameObject.AddComponent<AudioSource>();

        audioSource.clip = hitClip;


        originalVertices = new Vector3[meshFilters.Length][];

        rigidbody = GetComponent<Rigidbody>();


        ////////// getting all colliders,original vertices attached on mesh filters /////////

        for (int i = 0; i < meshFilters.Length; i++)

        {

            originalVertices[i] = meshFilters[i].mesh.vertices;

            meshFilters[i].mesh.MarkDynamic();

            meshColliders.Add(meshFilters[i].GetComponent<MeshCollider>());

        }


    }


    void ResetDeformation()

    {

        isDeformAble = true;

    }


    void OnCollisionEnter(Collision collision)

    {

        Vector3 impactVelocity = collision.relativeVelocity;


        /////// check if we hit with veloicty greater than needed to deform ///////

        if (impactVelocity.magnitude>minVelocity && isDeformAble

            && collision.gameObject!=gameObject) {


            isDeformAble = false;


            Invoke(nameof(ResetDeformation),resetDeformGap);


            //////// getting the hit point of vehcile /////////////

            Vector3 hitPoint = collision.contacts[0].point;


            PlayHitSound(impactVelocity.magnitude);


            // now we will modify/deform all mesh filters that will come in radius we decided //////

            for (int i = 0; i < meshFilters.Length; i++)

            {

                if (meshFilters[i] != null)

                {

                    DeformMesh(meshFilters[i].mesh, meshFilters[i].transform, hitPoint, impactVelocity, i);

                }

            }


            // Apply a force to the rigidbody to simulate the impact

            Vector3 impactForce = -transform.forward * 200;

            rigidbody.AddForce(impactForce, ForceMode.Impulse);

            }


    }


    void DeformMesh(Mesh meshHere,Transform transformHere,Vector3 hitPoint,Vector3 hitVelocity,int meshIndex)

    {

        ///////// get the local contact point according to the mesh transform i.e its position or point

        Vector3 localContactPoint = transformHere.InverseTransformPoint(hitPoint);

        Vector3 localContactForce = transformHere.InverseTransformDirection(hitVelocity);


        bool meshDeformed = false;

        /////// get all the vertices in that mesh filter ////////////

        Vector3[] vertices = meshHere.vertices;


        for (int j = 0; j < vertices.Length; j++)

        {

            ////////// get and check if that vertix is in the radius that we set for destrcution ////

            float distance = (localContactPoint - vertices[j]).magnitude;


            if (distance <= deformationRadius)

            {

                //////////// apply the demage force on that vertice

                vertices[j] += localContactForce * (deformationRadius - distance) * demageAmount;

                Vector3 deformation = vertices[j] - originalVertices[meshIndex][j];



                if (deformation.magnitude > deformationAmount)

                {

                    vertices[j] = originalVertices[meshIndex][j] + deformation.normalized * deformationAmount;

                }


                meshDeformed = true;

            }

        }


        /////////////// after deforming all the meshes, assign it 

        //////// the mesh and it is necessary to set the colliders

        ////////////// according to the new shape //////////

        ///

        if (meshDeformed) {

            meshHere.vertices = vertices;

            meshHere.RecalculateNormals();

            meshHere.RecalculateBounds();


            ////// check if collider is assigned ///////////

            if (meshColliders[meshIndex])

                meshColliders[meshIndex].sharedMesh = meshHere;

        }

    }



    ////////// setting the volume of hit sound as compared to the speed of vehcile

    /////////// i.e more speed will result in high volume 

    void PlayHitSound(float currentSpeed)

    {

        audioSource.volume = currentSpeed;

        audioSource.Play();

    }


}

No comments:

Post a Comment

Take input in Java easy tutorial

  Input taking in Java tutorial Download Link : Download input taking in Java example code ...