using System; using UnityEngine; [Serializable] public class EnemyIdle : State { StatData actionDelayStat; float actionDelayTime => actionDelayStat != null ? actionDelayStat.Value : 0; float actionDelayElapsedTime; bool IsInActionDelay => actionDelayTime > actionDelayElapsedTime; StatData attackDistanceStat; EnemyChasePlayer chaseState; EnemyAttack attackState; EnemyCastSkill castSkillState; protected override void OnInitialize() { Owner.Excutor.Data.TryGetStat(StatID.ActionDelay, out actionDelayStat); Owner.Excutor.Data.TryGetStat(StatID.AttackDistance, out attackDistanceStat); Owner.TryGetState(out chaseState); Owner.TryGetState(out attackState); Owner.TryGetState(out castSkillState); Debug.Assert(chaseState != null, "chase state not exist"); Debug.Assert(attackState != null, "attack state not exist"); Debug.Assert(castSkillState != null, "cast skill state not exist"); actionDelayElapsedTime = actionDelayTime; Debug.Assert(Owner.Excutor.SkeletonAnimation.TryGetAnimation("idle", out Spine.Animation _), "idle animation not exist"); } public override void Enter() { Owner.Excutor.IsBattleReady = true; Owner.Excutor.SkeletonAnimation.AnimationState.SetAnimation(0, "idle", true); } public override void Excute() { actionDelayElapsedTime = MathF.Min(actionDelayElapsedTime + Time.fixedDeltaTime, actionDelayTime); if (IsInActionDelay) return; if (castSkillState.TryGetCurrentTopSkill(out var topSkill) && !topSkill.IsInCoolTime) // if there is a skill to cast { topSkill.transform.position = Owner.Excutor.CenterPivot; if (topSkill.IsTargetExistInCastRange()) { Owner.ChangeState(); actionDelayElapsedTime = 0f; } else if (TargetFinder.TryFindNearest(Owner.Excutor.Position, Owner.Excutor.TargetTags, out var nearest)) { chaseState.SetTarget(nearest as Entity, topSkill.CastDistance); Owner.ChangeState(); } } else if(attackDistanceStat != null) { if (!TargetFinder.TryFindNearest(Owner.Excutor.Position, Owner.Excutor.TargetTags, out var nearest)) return; float attackDistance = attackDistanceStat.Value; Vector2 to = (nearest as Entity).Position - Owner.Excutor.Position; if(to.sqrMagnitude <= attackDistance * attackDistance) { attackState.Target = nearest; Owner.ChangeState(); actionDelayElapsedTime = 0f; } else { chaseState.SetTarget(nearest as Entity, attackDistance); Owner.ChangeState(); } } } }