OldBlueWater/BlueWater/Assets/02.Scripts/Weapon/ParticleWeapon.cs

124 lines
5.2 KiB
C#

using System;
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Events;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class ParticleWeapon : MonoBehaviour
{
public GameObject impactParticle; // Effect spawned when projectile hits a collider
public GameObject projectileParticle; // Effect attached to the gameobject as child
public GameObject muzzleParticle; // Effect instantly spawned when gameobject is spawned
[Header("Adjust if not using Sphere Collider")]
public float colliderRadius = 1f;
[Range(0f, 1f)] // This is an offset that moves the impact effect slightly away from the point of impact to reduce clipping of the impact effect
public float collideOffset = 0.15f;
[Title("Extensions Data")]
[SerializeField] private LayerMask targetLayer;
[SerializeField] private bool useAutoDestroy = true;
[ShowIf("@useAutoDestroy")]
[SerializeField] private float autoDestroyTime = 5f;
public UnityEvent<RaycastHit, float, GameObject> onHitAction;
private GameObject marker;
private float power;
private float detectionDistance;
public Rigidbody Rb { get; private set; }
private SphereCollider sphereCollider;
private void OnDrawGizmosSelected()
{
var radius = sphereCollider ? sphereCollider.radius : colliderRadius;
var direction = Rb ? Rb.velocity.normalized : transform.forward;
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, radius); // Draws the start sphere
Gizmos.DrawLine(transform.position, transform.position + direction * detectionDistance); // Draws the path of the SphereCast
}
private void Awake()
{
Rb = GetComponent<Rigidbody>();
sphereCollider = GetComponent<SphereCollider>();
}
private void Start()
{
if (useAutoDestroy)
{
Destroy(gameObject, autoDestroyTime);
}
projectileParticle = Instantiate(projectileParticle, transform.position, transform.rotation) as GameObject;
projectileParticle.transform.parent = transform;
if (muzzleParticle)
{
muzzleParticle = Instantiate(muzzleParticle, transform.position, transform.rotation) as GameObject;
Destroy(muzzleParticle, 1.5f); // 2nd parameter is lifetime of effect in seconds
}
}
private void FixedUpdate()
{
if (Rb.velocity.magnitude != 0)
{
transform.rotation = Quaternion.LookRotation(Rb.velocity); // Sets rotation to look at direction of movement
}
float radius; // Sets the radius of the collision detection
if (sphereCollider)
radius = sphereCollider.radius;
else
radius = colliderRadius;
var direction = Rb.velocity; // Gets the direction of the projectile, used for collision detection
if (Rb.useGravity)
direction += Physics.gravity * Time.deltaTime; // Accounts for gravity if enabled
direction = direction.normalized;
detectionDistance = Rb.velocity.magnitude * Time.deltaTime; // Distance of collision detection for this frame
if (Physics.SphereCast(transform.position, radius, direction, out var hit, detectionDistance, targetLayer)) // Checks if collision will happen
{
transform.position = hit.point + (hit.normal * collideOffset); // Move projectile to point of collision
var impactP = Instantiate(impactParticle, transform.position, Quaternion.FromToRotation(Vector3.up, hit.normal)) as GameObject; // Spawns impact effect
var trails = GetComponentsInChildren<ParticleSystem>(); // Gets a list of particle systems, as we need to detach the trails
//Component at [0] is that of the parent i.e. this object (if there is any)
for (var i = 1; i < trails.Length; i++) // Loop to cycle through found particle systems
{
var trail = trails[i];
if (trail.gameObject.name.Contains("Trail"))
{
trail.transform.SetParent(null); // Detaches the trail from the projectile
Destroy(trail.gameObject, 2f); // Removes the trail after seconds
}
}
if (onHitAction == null)
{
hit.transform.GetComponent<IDamageable>()?.TakeDamage(power);
}
else
{
onHitAction.Invoke(hit, power, marker);
}
Destroy(projectileParticle, 3f); // Removes particle effect after delay
Destroy(impactP, 3.5f); // Removes impact effect after delay
Destroy(gameObject); // Removes the projectile
}
}
public void SetPower(float value) => power = value;
public void SetHitMarker(GameObject value) => marker = value;
}
}