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