first commit

This commit is contained in:
2026-04-07 03:14:32 +03:00
commit b3992fec6b
1026 changed files with 366769 additions and 0 deletions

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 606a8c21594190f43a68a593a6ae0217
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -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:

View File

@@ -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;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b18cc6fafe6f9548a4d30a9634df21e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -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: