Characters
This commit is contained in:
123
Game/Scripts/WeaponSystem/Projectile.cs
Normal file
123
Game/Scripts/WeaponSystem/Projectile.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using MegaKoop.Game.Combat;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MegaKoop.Game.WeaponSystem
|
||||
{
|
||||
public class Projectile : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float hitRadius = 0.05f;
|
||||
[SerializeField] private LayerMask hitMask = Physics.DefaultRaycastLayers;
|
||||
[SerializeField] private bool alignToVelocity = true;
|
||||
|
||||
private Vector3 direction;
|
||||
private float speed;
|
||||
private float damage;
|
||||
private float lifetime;
|
||||
private float timeAlive;
|
||||
private Team sourceTeam;
|
||||
private GameObject owner;
|
||||
private Collider[] projectileColliders;
|
||||
|
||||
public void Initialize(Vector3 shotDirection, float projectileSpeed, float damageAmount, float projectileLifetime, GameObject projectileOwner, Team ownerTeam, Collider[] ownerColliders, LayerMask mask)
|
||||
{
|
||||
direction = shotDirection.sqrMagnitude > 0f ? shotDirection.normalized : transform.forward;
|
||||
speed = Mathf.Max(0f, projectileSpeed);
|
||||
damage = Mathf.Max(0f, damageAmount);
|
||||
lifetime = Mathf.Max(0.01f, projectileLifetime);
|
||||
owner = projectileOwner;
|
||||
sourceTeam = ownerTeam;
|
||||
hitMask = mask;
|
||||
timeAlive = 0f;
|
||||
|
||||
projectileColliders ??= GetComponentsInChildren<Collider>();
|
||||
if (ownerColliders != null && projectileColliders != null)
|
||||
{
|
||||
foreach (Collider ownerCollider in ownerColliders)
|
||||
{
|
||||
if (ownerCollider == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (Collider projectileCollider in projectileColliders)
|
||||
{
|
||||
if (projectileCollider == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Physics.IgnoreCollision(projectileCollider, ownerCollider, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
float deltaTime = Time.deltaTime;
|
||||
Vector3 displacement = direction * speed * deltaTime;
|
||||
float distance = displacement.magnitude;
|
||||
|
||||
if (distance > 0f)
|
||||
{
|
||||
if (Physics.SphereCast(transform.position, hitRadius, direction, out RaycastHit hitInfo, distance, hitMask, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
TryHandleHit(hitInfo.collider, hitInfo.point, hitInfo.normal);
|
||||
return;
|
||||
}
|
||||
|
||||
transform.position += displacement;
|
||||
}
|
||||
|
||||
if (alignToVelocity && distance > 0f)
|
||||
{
|
||||
transform.forward = direction;
|
||||
}
|
||||
|
||||
timeAlive += deltaTime;
|
||||
if (timeAlive >= lifetime)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
TryHandleHit(other, transform.position, -direction);
|
||||
}
|
||||
|
||||
private void TryHandleHit(Collider other, Vector3 hitPoint, Vector3 hitNormal)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner != null)
|
||||
{
|
||||
if (other.transform.IsChildOf(owner.transform))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IDamageable damageable = other.GetComponentInParent<IDamageable>();
|
||||
if (damageable != null && damageable.IsAlive)
|
||||
{
|
||||
bool isFriendly = damageable.Team == sourceTeam && damageable.Team != Team.Neutral;
|
||||
if (isFriendly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (damage > 0f)
|
||||
{
|
||||
var payload = new DamagePayload(damage, hitPoint, hitNormal, owner, sourceTeam, other.gameObject);
|
||||
damageable.ApplyDamage(payload);
|
||||
}
|
||||
}
|
||||
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user