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