first commit
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace YueDestructibles
|
||||
{
|
||||
public class YueDestructableAudioSourceTemplate : MonoBehaviour
|
||||
{
|
||||
public AudioSource audioSource;
|
||||
[HideInInspector]
|
||||
public Transform[] debris;
|
||||
|
||||
private float timeAlive = 0f;
|
||||
private const float maxTimeAlive = 10f;
|
||||
private Vector3 averagePosition;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (debris.Length <= 0)
|
||||
Destroy(this.gameObject);
|
||||
|
||||
if (!debris[0])
|
||||
Destroy(this.gameObject);
|
||||
|
||||
// calculate position
|
||||
averagePosition = Vector3.zero;
|
||||
foreach (Transform t in debris)
|
||||
{
|
||||
if(t)
|
||||
averagePosition += t.position;
|
||||
}
|
||||
averagePosition /= debris.Length;
|
||||
|
||||
// add position
|
||||
transform.position = averagePosition;
|
||||
|
||||
// destroy, if overtime
|
||||
timeAlive += Time.deltaTime;
|
||||
|
||||
if (timeAlive > maxTimeAlive)
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 606a8c21594190f43a68a593a6ae0217
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,160 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: caaa216d24f80384c9342e188fda10bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: e13f4281a295b08448d3004bd4d0e006, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,95 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace YueDestructibles
|
||||
{
|
||||
public class YueDestructiblesGunDemo : MonoBehaviour
|
||||
{
|
||||
[Header("*** Important ***")]
|
||||
[Header("To see how to destruct objects by code look into this script.")]
|
||||
[Header("*** Important *** \n")]
|
||||
|
||||
[Header("Gun Config")]
|
||||
public float impulseFactor = 10f;
|
||||
|
||||
[Header("Prefabs")]
|
||||
public List<GameObject> prefabs;
|
||||
|
||||
[Header("Dependencies")]
|
||||
public Camera fpsCamera;
|
||||
|
||||
// variables
|
||||
private AudioSource source;
|
||||
private List<GameObject> spawnedPrefabs;
|
||||
private List<float> counters;
|
||||
private const float timeUntilSpawn = 5f;
|
||||
|
||||
void Start()
|
||||
{// this is just about respawning the prefabs
|
||||
SetupPrefabs();
|
||||
source = GetComponent<AudioSource>();
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetButtonDown("Fire1"))
|
||||
{
|
||||
// play audioclip
|
||||
source.PlayOneShot(source.clip);
|
||||
|
||||
// create raycast with mouse position
|
||||
Ray ray = fpsCamera.ScreenPointToRay(Input.mousePosition);
|
||||
if (Physics.Raycast(ray, out RaycastHit hit))
|
||||
{
|
||||
// check if there is a Destructable component on the hit object
|
||||
if(hit.transform.GetComponentInParent<YueDestructible>() != null)
|
||||
{
|
||||
// calculate direction of impulse of the "bullet"
|
||||
Vector3 direction = (hit.point - fpsCamera.transform.position).normalized;
|
||||
|
||||
// called "DestructWithImpulse" method to destruct the object
|
||||
// direction is multiplied with the impulse of the bullet
|
||||
// the point of the raycast hit has to be passed into method
|
||||
hit.transform.GetComponentInParent<YueDestructible>().DestructWithImpulse(direction * impulseFactor, hit.point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// respawn prefabs
|
||||
UpdatePrefabs();
|
||||
}
|
||||
|
||||
|
||||
// this below is just about respawning the prefabs
|
||||
private void SetupPrefabs()
|
||||
{
|
||||
spawnedPrefabs = new List<GameObject>();
|
||||
for (int i = 0; i < prefabs.Count; i++)
|
||||
{
|
||||
spawnedPrefabs.Add(Instantiate<GameObject>(prefabs[i], Vector3.zero + Vector3.forward * (0.25f * i) - Vector3.forward * 0.5f, Quaternion.identity));
|
||||
}
|
||||
|
||||
counters = new List<float>();
|
||||
|
||||
for(int i = 0; i < prefabs.Count; i++)
|
||||
counters.Add(0);
|
||||
}
|
||||
private void UpdatePrefabs()
|
||||
{
|
||||
for (int i = 0; i < prefabs.Count; i++)
|
||||
{
|
||||
if (!spawnedPrefabs[i])
|
||||
{
|
||||
if (counters[i] > timeUntilSpawn)
|
||||
{
|
||||
spawnedPrefabs[i] = Instantiate<GameObject>(prefabs[i], Vector3.zero + Vector3.forward * (0.25f * i) - Vector3.forward * 0.5f, Quaternion.identity);
|
||||
counters[i] = 0;
|
||||
}
|
||||
|
||||
counters[i] += Time.deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b18cc6fafe6f9548a4d30a9634df21e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace YueDestructibles
|
||||
{
|
||||
public class YueDestructiblesRoot : MonoBehaviour
|
||||
{
|
||||
private Rigidbody[] debris;
|
||||
private float dissapearingSpeed = 0f;
|
||||
private float size = 1f;
|
||||
|
||||
public void SetDisappearingTime(float time)
|
||||
{
|
||||
dissapearingSpeed = 1 / time;
|
||||
}
|
||||
public void SetDebris(Rigidbody[] rb)
|
||||
{
|
||||
debris = rb;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Update Size until 0, then destroy
|
||||
size -= Time.deltaTime * dissapearingSpeed;
|
||||
foreach(Rigidbody r in debris)
|
||||
{
|
||||
r.transform.localScale = Vector3.one * size;
|
||||
}
|
||||
|
||||
if(size <= 0.05f)
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ea9afe1ec9947948bef3c44c0a52fd5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: e13f4281a295b08448d3004bd4d0e006, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user