using System; using System.Collections.Generic; using UnityEngine; public class Bullet : MonoBehaviour { [SerializeField] private Collider2D collisionDetector; [SerializeField] private float speed = 10.0f; float maxFlyDistance = 0.0f; float currentFlyDistance = 0.0f; HashSet collided = new HashSet(); Action OnCollide; Action OnCompleteToTarget; public Transform Target { get; private set; } = null; public bool IsFired { get; private set; } = false; public float Speed { get => speed; set => speed = value; } public Vector2 HeadDirection { get { var zAngle = transform.eulerAngles.z; return new Vector2(Mathf.Cos(zAngle * Mathf.Deg2Rad), Mathf.Sin(zAngle * Mathf.Deg2Rad)).normalized; } set { transform.eulerAngles = new Vector3(0, 0, Mathf.Atan2(value.y, value.x) * Mathf.Rad2Deg); } } private void Update() { if(!IsFired) return; float sqrtDistanceToTarget = float.MaxValue; if (Target != null) { var ignoreZOfThis = transform.position; ignoreZOfThis.z = 0.0f; var ignoreZOfTarget = Target.position; ignoreZOfTarget.z = 0.0f; var toVec = ignoreZOfTarget - ignoreZOfThis; HeadDirection = toVec; sqrtDistanceToTarget = toVec.sqrMagnitude; } float moveUnit = speed * Time.deltaTime; if (sqrtDistanceToTarget < moveUnit * moveUnit) { transform.position = Target.position; BattleMgr.LoopAllCreatures(HandleCollide); OnCompleteToTarget?.Invoke(this); IsFired = false; } else if(maxFlyDistance > 0.0f && currentFlyDistance >= maxFlyDistance) { BattleMgr.LoopAllCreatures(HandleCollide); OnCompleteToTarget?.Invoke(this); IsFired = false; } else { transform.position += (Vector3)HeadDirection * moveUnit; currentFlyDistance += moveUnit; BattleMgr.LoopAllCreatures(HandleCollide); } } public void Fire(float maxFlyDistance, Action onCollide, Action onCompleteToTarget) { this.maxFlyDistance = maxFlyDistance; currentFlyDistance = 0.0f; OnCollide = onCollide; OnCompleteToTarget = onCompleteToTarget; collided.Clear(); IsFired = true; } public void Fire(Transform target, Action onCollide, Action onCompleteToTarget) { maxFlyDistance = 0.0f; currentFlyDistance = 0.0f; Target = target; OnCollide = onCollide; OnCompleteToTarget = onCompleteToTarget; collided.Clear(); IsFired = true; } private bool HandleCollide(CreatureBase creature) { var ignoreZOfBounds = collisionDetector.bounds; ignoreZOfBounds.extents = new Vector3(ignoreZOfBounds.extents.x, ignoreZOfBounds.extents.y, 0.0f); var ignoreZOfCreature = creature.transform.position; ignoreZOfCreature.z = 0.0f; if (collided.Contains(creature)) { if (!ignoreZOfBounds.Contains(ignoreZOfCreature)) { collided.Remove(creature); } return true; } if (ignoreZOfBounds.Contains(ignoreZOfCreature)) { collided.Add(creature); OnCollide.Invoke(this, creature); return false; } return true; } private void OnDrawGizmosSelected() { Logger.DrawArrow2D(transform.position, HeadDirection, 5.0f, Color.cyan); } }