160 lines
5.1 KiB
C#
160 lines
5.1 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace YueDestructibles
|
|
{
|
|
[RequireComponent(typeof(Rigidbody))]
|
|
public class YueDestructible : MonoBehaviour
|
|
{
|
|
[Header("Destruction Properties")]
|
|
public float shatterBounceMultiplier = 3f;
|
|
public float maximumImpulse = 1.5f;
|
|
public float impulseDamageMultiplier = 30f;
|
|
public bool accumulateDamage = false;
|
|
|
|
[Header("Health [%]")]
|
|
[SerializeField]
|
|
[Range(0f, 100f)]
|
|
private float health = 100f;
|
|
|
|
[Header("Debris Disappearance")]
|
|
public bool isDisappearing = true;
|
|
public float disappearingTime = 5f;
|
|
|
|
[Header("Sound Effects")]
|
|
public AudioClip[] destructionClips;
|
|
public float impulseVolumeFactor = 0.5f;
|
|
public YueDestructableAudioSourceTemplate audioSourceTemplate;
|
|
|
|
[Header("Dependencies")]
|
|
public GameObject debrisRoot;
|
|
[Header("Events")]
|
|
public UnityEvent onObjectDestruct;
|
|
// variables
|
|
#region
|
|
private Renderer mainObjectRenderer;
|
|
private Rigidbody[] debris;
|
|
private Rigidbody rigid;
|
|
|
|
private bool isDestructed = false;
|
|
private bool isSetup = false;
|
|
#endregion
|
|
|
|
private void Start()
|
|
{
|
|
// disable deris meshes
|
|
debrisRoot.SetActive(false);
|
|
// get list of debris rigidbodies
|
|
debris = debrisRoot.GetComponentsInChildren<Rigidbody>();
|
|
// get renderer to determine object size
|
|
mainObjectRenderer = GetComponent<Renderer>();
|
|
// get main rigidbody
|
|
rigid = GetComponent<Rigidbody>();
|
|
// check UnityEvent
|
|
if (onObjectDestruct == null)
|
|
onObjectDestruct = new UnityEvent();
|
|
|
|
isSetup = true;
|
|
}
|
|
private void OnCollisionEnter(Collision collision)
|
|
{
|
|
if (!isSetup)
|
|
return;
|
|
|
|
if (collision.impulse.magnitude > maximumImpulse)
|
|
{
|
|
DestructWithImpulse(collision.impulse, collision.GetContact(0).point);
|
|
}
|
|
|
|
if (!accumulateDamage)
|
|
return;
|
|
|
|
health -= collision.impulse.magnitude * impulseDamageMultiplier;
|
|
|
|
if (health < 0f)
|
|
DestructWithImpulse(collision.impulse, collision.GetContact(0).point);
|
|
}
|
|
|
|
public void DestructWithImpulse(Vector3 impulse, Vector3 point)
|
|
{
|
|
if (isDestructed)
|
|
return;
|
|
|
|
if (debris.Length <= 0)
|
|
return;
|
|
|
|
// active and unparent root
|
|
debrisRoot.SetActive(true);
|
|
debrisRoot.transform.parent = null;
|
|
|
|
// inherit main rigid velocity
|
|
foreach (Rigidbody rb in debris)
|
|
{
|
|
if (!rb)
|
|
break;
|
|
|
|
// set active
|
|
rb.gameObject.SetActive(true);
|
|
|
|
// apply propertie
|
|
rb.mass = rigid.mass / debris.Length;
|
|
rb.drag = rigid.drag;
|
|
rb.angularDrag = rigid.angularDrag;
|
|
|
|
// add velocity
|
|
rb.velocity = rigid.velocity;
|
|
rb.angularVelocity = rigid.angularVelocity;
|
|
|
|
// add impulse
|
|
rb.AddExplosionForce(impulse.magnitude * shatterBounceMultiplier, point, mainObjectRenderer.bounds.max.magnitude);
|
|
}
|
|
|
|
// create sound effect
|
|
CreateAudioEffect(impulse, point);
|
|
|
|
// set flag
|
|
isDestructed = true;
|
|
|
|
// setup root, if disappearing
|
|
if (isDisappearing)
|
|
{
|
|
debrisRoot.AddComponent<YueDestructiblesRoot>();
|
|
debrisRoot.GetComponent<YueDestructiblesRoot>().SetDebris(debris);
|
|
debrisRoot.GetComponent<YueDestructiblesRoot>().SetDisappearingTime(disappearingTime);
|
|
}
|
|
|
|
// invoke event
|
|
onObjectDestruct.Invoke();
|
|
|
|
// destroy intact object
|
|
Destroy(this.gameObject);
|
|
}
|
|
public void DestructSimple()
|
|
{
|
|
DestructWithImpulse(Vector3.zero, transform.position);
|
|
}
|
|
public void AddDamage(float damageInPercent)
|
|
{
|
|
health -= damageInPercent;
|
|
}
|
|
|
|
private void CreateAudioEffect(Vector3 impulse, Vector3 point)
|
|
{
|
|
if (destructionClips.Length <= 0)
|
|
return;
|
|
|
|
// instatiate sound effect
|
|
GameObject effect = Instantiate<GameObject>(audioSourceTemplate.gameObject, point, Quaternion.identity);
|
|
|
|
// init debris
|
|
YueDestructableAudioSourceTemplate templateClone = effect.GetComponent<YueDestructableAudioSourceTemplate>();
|
|
templateClone.debris = debrisRoot.GetComponentsInChildren<Transform>();
|
|
|
|
templateClone.audioSource.volume = impulseVolumeFactor * impulse.magnitude;
|
|
|
|
// play random sound
|
|
templateClone.audioSource.PlayOneShot(destructionClips[Random.Range(0, destructionClips.Length)]);
|
|
Destroy(effect, 5f);
|
|
}
|
|
}
|
|
} |