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();

    }


}

Simple vehicle controller in unity




 

Code :

using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Rigidbody))]
public class CController : MonoBehaviour
{
    public WheelCollider WheelFL;
    public WheelCollider WheelFR;
    public WheelCollider WheelRL;
    public WheelCollider WheelRR;
    public Transform WheelFLtrans;
    public Transform WheelFRtrans;
    public Transform WheelRLtrans;
    public Transform WheelRRtrans;
    private bool braked = false;
    private Rigidbody rb;
    public Transform centreofmass;
    public float maxTorque = 1000;
    public float maxBrakeTorque = 500;
    public float maxSteerAngle = 30;
    void Start()
    {
        rb = GetComponent  <Rigidbody> ();
        rb.centerOfMass = centreofmass.transform.localPosition;
    }

    void FixedUpdate()
    {
        if (!braked)
        {
            WheelFL.brakeTorque = 0;
            WheelFR.brakeTorque = 0;
            WheelRL.brakeTorque = 0;
            WheelRR.brakeTorque = 0;
        }
        //speed of car, Car will move as you will provide the input to it.

        WheelRR.motorTorque = maxTorque * Input.GetAxis("Vertical");
        WheelRL.motorTorque = maxTorque * Input.GetAxis("Vertical");

        //changing car direction
 //       Here we are changing the steer angle of the front tyres of the car so that we can change the car direction.
        WheelFL.steerAngle = maxSteerAngle * (Input.GetAxis("Horizontal"));
        WheelFR.steerAngle = maxSteerAngle * Input.GetAxis("Horizontal");
    }
    void Update()
    {
        HandBrake();

        //for tyre rotate
        WheelFLtrans.Rotate(WheelFL.rpm / 60 * 360 * Time.deltaTime, 0, 0);
        WheelFRtrans.Rotate(WheelFR.rpm / 60 * 360 * Time.deltaTime, 0, 0);
        WheelRLtrans.Rotate(WheelRL.rpm / 60 * 360 * Time.deltaTime, 0, 0);
        WheelRRtrans.Rotate(WheelRL.rpm / 60 * 360 * Time.deltaTime, 0, 0);
        //changing tyre direction
        Vector3 temp = WheelFLtrans.localEulerAngles;
        Vector3 temp1 = WheelFRtrans.localEulerAngles;
        temp.y = WheelFL.steerAngle - (WheelFLtrans.localEulerAngles.z);
        WheelFLtrans.localEulerAngles = temp;
        temp1.y = WheelFR.steerAngle - WheelFRtrans.localEulerAngles.z;
        WheelFRtrans.localEulerAngles = temp1;

    }
    void HandBrake()
    {
        //Debug.Log("brakes " + braked);
        if (Input.GetButton("Jump"))
        {
            braked = true;
        }
        else
        {
            braked = false;
        }
        if (braked)
        {

            WheelRL.brakeTorque = maxBrakeTorque * 20;//0000;
            WheelRR.brakeTorque = maxBrakeTorque * 20;//0000;
            WheelRL.motorTorque = 0;
            WheelRR.motorTorque = 0;
        }
    }
}
    

Video Tutorial :




Take input in Java easy tutorial

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