Files
BlueArchiveMiniGame/Assets/ThirdParty/DestroyIt/Demos (safe to delete)/Scripts/Effects/ShockWaveSphere.cs

124 lines
4.4 KiB
C#
Raw Normal View History

2025-09-17 18:56:28 +08:00
using UnityEngine;
namespace DestroyIt
{
[RequireComponent(typeof(SphereCollider))]
[RequireComponent(typeof(Rigidbody))]
public class ShockWaveSphere : MonoBehaviour
{
[Tooltip("How many seconds to wait before the shockwave starts.")]
public float timer = 10f;
[Tooltip("The particle effect to use for the shockwave.")]
public ParticleSystem visualEffect;
[Tooltip("How much force to apply to rigidbodies hit by the shockwave.")]
public float blastForce = 500f;
[Tooltip("How much damage to apply to Destructible objects that are hit by the shockwave.")]
public float damageAmount = 200f;
[Tooltip("How fast the shockwave spreads out.")]
public float shockwaveSpeed = 30f;
[Tooltip("The maximum radius of the shockwave. Once it reaches this size, it is disabled and removed from the scene.")]
public float maxRadius = 300f;
private Vector3 _originPos; // the world position where the shockwave originates
private float _timeLeft;
private bool _isInitialized;
private bool _hasStarted;
private SphereCollider _sphereCollider;
private Rigidbody _rigidbody;
public void Start()
{
Initialize();
}
public void OnEnable()
{
Initialize();
}
private void Initialize()
{
if (_isInitialized) return;
_originPos = transform.position;
_timeLeft = timer;
_sphereCollider = gameObject.GetComponent<SphereCollider>();
_sphereCollider.isTrigger = true;
_sphereCollider.radius = 0f;
_rigidbody = gameObject.GetComponent<Rigidbody>();
_rigidbody.useGravity = false;
_isInitialized = true;
}
public void Update()
{
if (!_isInitialized) return;
if (_hasStarted)
{
// Check if the shockwave has reached its max size. If so, destroy it.
if (_sphereCollider.radius >= maxRadius)
{
gameObject.SetActive(false);
Destroy(gameObject);
return;
}
// Grow the shockwave based on the shockwave speed
_sphereCollider.radius += Time.deltaTime * shockwaveSpeed;
return;
}
_timeLeft -= Time.deltaTime;
if (_timeLeft <= 0)
{
// Start the shockwave
if (visualEffect != null)
Instantiate(visualEffect, _originPos, Quaternion.identity);
_hasStarted = true;
}
}
public void OnTriggerEnter(Collider col)
{
// If it has a rigidbody, apply force
Rigidbody rbody = col.attachedRigidbody;
if (rbody != null && !rbody.isKinematic)
rbody.AddExplosionForce(blastForce, _originPos, 0f, 0.5f);
// Check for Chip-Away Debris
ChipAwayDebris chipAwayDebris = col.gameObject.GetComponent<ChipAwayDebris>();
if (chipAwayDebris != null)
{
if (Random.Range(1, 100) > 50) // Do this about half the time...
{
chipAwayDebris.BreakOff(blastForce, 0f, 0.5f);
return; //Skip the destructible check if the debris hasn't chipped away yet.
}
return;
}
// If it's a destructible object, apply damage
// Only do this for the first active and enabled Destructible script found in parent objects
// Special Note: Destructible scripts are turned off on terrain trees by default (to save resources), so we will make an exception for them and process the damage anyway
Destructible[] destObjs = col.gameObject.GetComponentsInParent<Destructible>(false);
foreach (Destructible destObj in destObjs)
{
if (!destObj.isActiveAndEnabled && !destObj.isTerrainTree) continue;
ExplosiveDamage explosiveDamage = new ExplosiveDamage { DamageAmount = damageAmount, BlastForce = blastForce, Position = _originPos, Radius = 0f, UpwardModifier = 0.5f };
destObj.ApplyDamage(explosiveDamage);
break;
}
}
}
}