You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

118 lines
3.0 KiB

using System;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : Entity, IColliderChecker
{
[SerializeField] float speed = 10.0f;
[SerializeField] float lifeTime = 5.0f;
[SerializeField] float maxDistance = 0f;
Vector2 headDirection;
float flyingDistance = 0.0f;
float elapsedLifeTime = 0.0f;
HashSet<string> collideFilter = new HashSet<string>();
HashSet<Collider2D> currentColliders = new HashSet<Collider2D>();
public event Action<Bullet> OnBeforeDestroy;
public event Action<Collider2D> OnEnterCollider;
public float Speed { get => speed; set => speed = value; }
public Vector2 HeadDirection
{
get
{
if (headDirection == default)
{
float zRad = transform.eulerAngles.z * Mathf.Deg2Rad;
headDirection = new Vector2(Mathf.Cos(zRad), Mathf.Sin(zRad)).normalized;
}
return headDirection;
}
set
{
headDirection = value.normalized;
transform.eulerAngles = new Vector3(0, 0, Mathf.Atan2(value.y, value.x) * Mathf.Rad2Deg);
}
}
public bool IsFired { get; private set; } = false;
private void LateUpdate()
{
if (!IsFired) return;
float moveUnit = speed * Time.fixedDeltaTime;
bool shouldDestroy = !UpdateLifeTime();
shouldDestroy |= !UpdateFlyingDistance(moveUnit);
if (shouldDestroy)
{
OnBeforeDestroy?.Invoke(this);
Destroy(gameObject);
}
else
{
transform.position += (Vector3)HeadDirection * moveUnit;
}
}
private bool UpdateLifeTime()
{
elapsedLifeTime += Time.fixedUnscaledDeltaTime;
return elapsedLifeTime < lifeTime;
}
private bool UpdateFlyingDistance(float moveUnit)
{
if(flyingDistance <= 0) return true;
flyingDistance += moveUnit;
return flyingDistance < maxDistance;
}
public void Fire()
{
elapsedLifeTime = 0;
flyingDistance = 0;
IsFired = true;
}
public void Fire(Transform target)
{
HeadDirection = target.position - transform.position;
elapsedLifeTime = 0;
flyingDistance = 0;
IsFired = true;
}
public void AddTagFilter(params string[] tags) => collideFilter.UnionWith(tags);
public void RemoveTagFilter(params string[] tags) => collideFilter.ExceptWith(tags);
public void ClearTagFilter() => collideFilter.Clear();
public void CheckColliding(Action<Collider2D> collided)
{
foreach (var target in currentColliders)
{
collided.Invoke(target);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (collideFilter.Contains(other.tag))
{
currentColliders.Add(other);
OnEnterCollider?.Invoke(other);
}
}
private void OnTriggerExit2D(Collider2D collision)
{
currentColliders.Remove(collision);
}
}