using UnityEngine; namespace BumpCombat.Defense { [DisallowMultipleComponent] public sealed class DefenseSummonUnit : MonoBehaviour { private Sprite[] idleFrames; private Sprite[] attackFrames; private string idleKey; private string attackKey; private float spriteFrameTime; private int spriteFrame; private bool playingAttack; private bool isWalking; private string walkKey; private Sprite[] walkFrames; private DefenseTower owner; private DefensePrototypeController controller; private Vector2 anchorLocalPosition; private SpriteRenderer spriteRenderer; private float attackCooldown; public void Configure( DefenseTower tower, DefensePrototypeController prototypeController, Vector2 localAnchor) { owner = tower; controller = prototypeController; anchorLocalPosition = localAnchor; spriteRenderer = gameObject.AddComponent(); spriteRenderer.color = Color.white; spriteRenderer.sortingOrder = 11; RefreshArt(); } public void RefreshArt() { if (spriteRenderer == null || owner == null) { return; } string family = owner.Tier == 4 && owner.Branch == DefenseTowerBranch.First ? "GiantSlime" : owner.Tier == 4 && owner.Branch == DefenseTowerBranch.Second ? "LavaSlime" : "Slime"; idleKey = $"Summons/{family}/Idle"; attackKey = $"Summons/{family}/Attack01"; walkKey = $"Summons/{family}/Walk"; idleFrames = DefenseTowerArt.Load(idleKey); attackFrames = DefenseTowerArt.Load(attackKey); walkFrames = DefenseTowerArt.Load(walkKey); spriteFrame = 0; spriteFrameTime = 0f; playingAttack = false; if (idleFrames.Length > 0) { spriteRenderer.sprite = idleFrames[0]; } float scale = family == "GiantSlime" ? 1.55f : family == "LavaSlime" ? 1.15f : 1.1f; transform.localScale = new Vector3(scale, scale, 1f); } private void Update() { UpdateSpriteAnimation(); if (owner == null || !owner.isActiveAndEnabled || controller == null || !controller.CanOperateTowers) { return; } attackCooldown = Mathf.Max(0f, attackCooldown - Time.deltaTime); Vector2 anchor = owner.transform.TransformPoint(anchorLocalPosition); DefenseRouteAgent target = controller.FindNearestTarget( anchor, controller.Tuning.SummonAreaRadius, DefenseTowerKind.Summon); if (target == null) { Vector2 previous = transform.position; transform.position = Vector2.MoveTowards( previous, anchor, controller.Tuning.SummonUnitMoveSpeed * Time.deltaTime); isWalking = ((Vector2)transform.position - previous).sqrMagnitude > 0.000001f; return; } Vector2 targetPosition = target.transform.position; spriteRenderer.flipX = targetPosition.x < transform.position.x; Vector2 previousPosition = transform.position; transform.position = Vector2.MoveTowards( previousPosition, targetPosition, controller.Tuning.SummonUnitMoveSpeed * Time.deltaTime); isWalking = ((Vector2)transform.position - previousPosition).sqrMagnitude > 0.000001f; float attackRange = controller.Tuning.SummonAttackRange * (owner.Tier == 4 && owner.Branch == DefenseTowerBranch.Second ? 2.5f : 1f); if (attackCooldown <= 0f && (targetPosition - (Vector2)transform.position).sqrMagnitude <= attackRange * attackRange && owner.TryAttack(target)) { PlayAttackSprite(); owner.ShowSummonAttackEffect(transform.position, targetPosition); attackCooldown = controller.Tuning.SummonAttackInterval / (1f + 0.15f * (owner.Tier - 1)) * controller.GetTowerAttackIntervalMultiplier(owner); } } private void PlayAttackSprite() { if (attackFrames == null || attackFrames.Length == 0) { return; } playingAttack = true; spriteFrameTime = 0f; spriteFrame = 0; spriteRenderer.sprite = attackFrames[0]; } private void UpdateSpriteAnimation() { Sprite[] frames = playingAttack ? attackFrames : isWalking ? walkFrames : idleFrames; string key = playingAttack ? attackKey : isWalking ? walkKey : idleKey; if (spriteRenderer == null || frames == null || frames.Length == 0) { return; } spriteFrameTime += Time.deltaTime; while (spriteFrameTime >= DefenseTowerArt.FrameSeconds(key, spriteFrame)) { spriteFrameTime -= DefenseTowerArt.FrameSeconds(key, spriteFrame); spriteFrame++; if (spriteFrame >= frames.Length) { if (playingAttack) { playingAttack = false; spriteFrame = 0; frames = idleFrames; key = idleKey; } else { spriteFrame = 0; } } spriteRenderer.sprite = frames[spriteFrame]; } } } }