示例#1
0
 void UpdateAnimation()
 {
     if (CurrentState != _lastState)
     {
         ResetAllAnimation();
         an.SetBool(CurrentState.ToString(), true);
         _lastState = CurrentState;
     }
 }
示例#2
0
 private void Move2()
 {
     if (transform.position.x < 61 || transform.position.x > 75)
     {
         direction *= -1;
     }
     sprite.flipX       = direction.x > 0;
     transform.position = Vector3.MoveTowards(transform.position, transform.position + direction, speed * Time.deltaTime);
     state = SkeletonState.run;
 }
示例#3
0
    private void Update()
    {
        var newState = currentState.Update(this);

        if (newState != null)
        {
            currentState = newState;
            currentState.Enter(this);
        }
    }
示例#4
0
    private void Hit()
    {
        var newState = currentState.HandleInput(this, SkeletonCommand.HIT);

        if (newState != null)
        {
            currentState = newState;
            currentState.Enter(this);
            horizontal = 0.0f;
        }
    }
示例#5
0
    private void Die()
    {
        var newState = currentState.HandleInput(this, SkeletonCommand.DEATH);

        if (newState != null)
        {
            currentState = newState;
            currentState.Enter(this);
            horizontal = 0.0f;
            Destroy(gameObject, destroyAfterDeathDelay);
        }
    }
示例#6
0
    protected virtual void OnTriggerEnter2D(Collider2D collider)
    {
        Character user = collider.GetComponent <Character>();

        if (user && user is Character)
        {
            attack = true;
            state  = SkeletonState.attack;
            user.ReciveDamage();
            StartCoroutine(Attack());
            sprite.flipX = !user.usrSprite.flipX; // turn sprte to the enemy
        }
    }
示例#7
0
 public override void Die()
 {
     if (ActiveState != SkeletonState.DIED)
     {
         StopAllCoroutines();
         base.Die();
         ActiveState = SkeletonState.DIED;
         anim.SetTrigger("Die");
         Destroy(nav);
         DropItem();
         StartCoroutine(WaitTime());
     }
 }
示例#8
0
 private void OnTriggerExit(Collider other)
 {
     if (ActiveState != SkeletonState.DIED)
     {
         if (other.gameObject.tag == "Player")
         {
             if (ActiveState == SkeletonState.CHASE)
             {
                 ActiveState = SkeletonState.PLAYER_LOST;
                 chase.PlayerLost(target);
                 nav.SetDestination(target);
             }
         }
     }
 }
示例#9
0
    IEnumerator SkeletonStateEvent()
    {
        if (Avatar != null)
        {
            while (true)
            {
                SkeletonState            state    = Avatar.GetCurrentSkeleton();
                ServiceCallback <byte[]> callback = VrLifeCore.API.Event.SendSkeleton(state);
                yield return(callback.WaitCoroutine());

                if (callback.HasException)
                {
                    yield break;
                }
                yield return(null);
            }
        }
    }
示例#10
0
 private void Start()
 {
     if (!staticEnemy)
     {
         ActiveState = SkeletonState.PATROL;
         target      = patrol.GetNewWaipoint(new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity));
         nav.SetDestination(target);
     }
     else
     {
         ActiveState = SkeletonState.RETURNING_TO_POSITION;
         target      = hold.ReturnToPosition();
         nav.SetDestination(target);
     }
     angularSpeedBase = nav.angularSpeed;
     nextAtack        = attackList.GetNextAttack();
     destructionTime += Random.value * destructionTime; //randomice the destrucction time;
 }
示例#11
0
 public void SetSkeleton(SkeletonState skeleton)
 {
     SkeletonParts[(int)SkeletonEnum.BODY_LOCATION].transform.position         = skeleton.BodyLocation.ToUnity();
     SkeletonParts[(int)SkeletonEnum.BODY_LOCATION].transform.localEulerAngles = skeleton.BodyRotation.ToUnity();
     SkeletonParts[(int)SkeletonEnum.HEAD].transform.localEulerAngles          = skeleton.Head.ToUnity();
     SkeletonParts[(int)SkeletonEnum.HIPS].transform.localEulerAngles          = skeleton.Hips.ToUnity();
     SkeletonParts[(int)SkeletonEnum.SPINE].transform.localEulerAngles         = skeleton.Spine.ToUnity();
     SkeletonParts[(int)SkeletonEnum.NECK].transform.localEulerAngles          = skeleton.Neck.ToUnity();
     SkeletonParts[(int)SkeletonEnum.L_SHOULDER].transform.localEulerAngles    = skeleton.LeftShoulder.ToUnity();
     SkeletonParts[(int)SkeletonEnum.L_ARM].transform.localEulerAngles         = skeleton.LeftArm.ToUnity();
     SkeletonParts[(int)SkeletonEnum.L_HAND].transform.localEulerAngles        = skeleton.LeftHand.ToUnity();
     SkeletonParts[(int)SkeletonEnum.R_SHOULDER].transform.localEulerAngles    = skeleton.RightShoulder.ToUnity();
     SkeletonParts[(int)SkeletonEnum.R_ARM].transform.localEulerAngles         = skeleton.RightArm.ToUnity();
     SkeletonParts[(int)SkeletonEnum.R_HAND].transform.localEulerAngles        = skeleton.RightHand.ToUnity();
     SkeletonParts[(int)SkeletonEnum.L_KNEE].transform.localEulerAngles        = skeleton.LeftKnee.ToUnity();
     SkeletonParts[(int)SkeletonEnum.L_FOOT].transform.localEulerAngles        = skeleton.LeftFoot.ToUnity();
     SkeletonParts[(int)SkeletonEnum.R_KNEE].transform.localEulerAngles        = skeleton.RightKnee.ToUnity();
     SkeletonParts[(int)SkeletonEnum.R_FOOT].transform.localEulerAngles        = skeleton.RightFoot.ToUnity();
 }
示例#12
0
        public Skeleton(
            Animation staticAnimation,
            Animation followingAndBlockingAnimation,
            Animation attackRightAnimation,
            Animation attackLeftAnimation,
            Animation blockRightAnimation,
            Animation blockLeftAnimation,
            Vector2 position, Vector2 size, float directionAngle, Animation deadAnimation, ISound deathSound, ISound hitSound, ISound shieldHit) : base(position, size, directionAngle, 30)
        {
            this.staticAnimation = staticAnimation;
            this.followingAndBlockingAnimation = followingAndBlockingAnimation;
            this.attackRightAnimation          = attackRightAnimation;
            this.attackLeftAnimation           = attackLeftAnimation;
            this.blockRightAnimation           = blockRightAnimation;
            this.blockLeftAnimation            = blockLeftAnimation;
            this.deadAnimation = deadAnimation;
            this.deathSound    = deathSound;
            this.hitSound      = hitSound;
            this.shieldHit     = shieldHit;

            state = SkeletonState.Static;
        }
示例#13
0
 private void OnTriggerStay(Collider other)
 {
     if (ActiveState != SkeletonState.DIED)
     {
         if (other.gameObject.name == "Player")                                                                          // we can add inside this:  && other.gameobject.GetComponent<PlayerCombat> != null
         {
             if (FaceAndCheckObjective(other.transform.position, detectionAngle) && ActiveState != SkeletonState.ATTACK) //in vision
             {
                 if (Vector3.Distance(other.transform.position, transform.position) < nextAtack[1])
                 {
                     ActiveState = SkeletonState.ATTACK;
                 }
                 else
                 {
                     if (ActiveState != SkeletonState.CHASE)
                     {
                         ActiveState = SkeletonState.CHASE;
                         chase.PlayerFound();
                     }
                     target = other.transform.position;
                 }
             }
             else //out of vision
             {
                 if (ActiveState == SkeletonState.CHASE)
                 {
                     ActiveState = SkeletonState.PLAYER_LOST;
                     chase.PlayerLost(target);
                     nav.SetDestination(target);
                 }
                 if (ActiveState == SkeletonState.ATTACK)
                 {
                     target = other.transform.position;
                 }
             }
         }
     }
 }
示例#14
0
        private EventResponse HandleSkeletonEvent(ulong msgId, ulong clientId, EventDataMsg eventMsg)
        {
            Skeleton skeleton = eventMsg.SkeletonValue;

            if (skeleton == null)
            {
                return(IEventService.CreateErrorResponse(msgId, 0, 0, "Skeleton value cannot be null."));
            }
            if (!_api.Services.User.FastCheckUserId(clientId, skeleton.UserId))
            {
                return(IEventService.CreateErrorResponse(msgId, 0, 0, "Authentication error."));
            }
            uint?roomId = _api.Services.Room.RoomByUserId(skeleton.UserId);

            if (!roomId.HasValue)
            {
                return(IEventService.CreateErrorResponse(msgId, 0, 0, "User is not connected to any room."));
            }
            SkeletonState skelState = new SkeletonState(skeleton);

            _api.Services.TickRate.SetSkeletonState(roomId.Value, skeleton.UserId, skelState);
            return(null);
        }
 // Performs actions for dying state.
 IList<IAction> Die()
 {
     // Delimit time of skeleton GameObject destruction.
     float destructionTime = Time.time + DyingTime;
     // Create single-step action triggering die animation.
     IAction goDying = new CustomAction(
         () => {
             // Set current state to dying.
             this.state = SkeletonState.Dying;
             // Set die animation.
             this.animation.CrossFade("die");
             // Remove collider component.
             Destroy(collider);
         });
     // Create continuous action doing nothing.
     IAction dying = new CustomAction(
         () => { },		// Does nothing but waiting for termination condition come into being.
         // Action is active while:
         () => !this.IsTimeOut(destructionTime));		// dying timeout doesn't occured.
     // Create single-step action destructing current skeleton.
     IAction destroy = new CustomAction(
         () => {
             // Destroy current skeleton GameObject.
             Destroy(gameObject);
         });
     return new List<IAction> { goDying, dying, destroy };
 }
    void SkeletonFSM()
    {
        Vector3 direction = player.transform.position - this.transform.position;

        direction.y = 0;

        switch (skeletonState)
        {
        case SkeletonState.Idle:
            animator.SetBool("isIdle", true);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", false);

            sw.Start();

            if (sw.ElapsedMilliseconds > 3000)
            {
                skeletonState = SkeletonState.Wander;
            }

            if (Vector3.Distance(player.transform.position, this.transform.position) < 7)
            {
                skeletonState = SkeletonState.Notice;
            }
            break;

        case SkeletonState.Wander:
            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", true);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", false);

            sw.Start();

            if (sw.ElapsedMilliseconds > 6000)
            {
                sw.Reset();
                skeletonState = SkeletonState.Idle;
            }

            if (Vector3.Distance(player.transform.position, this.transform.position) < 7)
            {
                sw.Reset();
                skeletonState = SkeletonState.Notice;
            }

            break;

        case SkeletonState.Notice:
            direction = player.transform.position - this.transform.position;
            this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);

            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", false);

            if (sw.ElapsedMilliseconds > 2000)
            {
                skeletonState = SkeletonState.Chase;
            }


            break;

        case SkeletonState.Chase:
            direction = player.transform.position - this.transform.position;
            this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);

            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", true);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", false);

            if (Vector3.Distance(player.transform.position, this.transform.position) < 2)
            {
                sw.Reset();
                skeletonState = SkeletonState.Confront;
            }

            break;

        case SkeletonState.Confront:
            direction = player.transform.position - this.transform.position;
            this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);

            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", false);

            if (sw.ElapsedMilliseconds > 2000)
            {
                int checkBehaviorNum = Random.Range(1, 2);

                if (checkBehaviorNum == 1)
                {
                    sw.Reset();
                    skeletonState = SkeletonState.QuickSwing;
                }

                if (checkBehaviorNum == 2)
                {
                    sw.Reset();
                    skeletonState = SkeletonState.HeavySwing;
                }
            }

            break;

        case SkeletonState.QuickSwing:
            direction = player.transform.position - this.transform.position;
            this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);

            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", true);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", false);


            break;

        case SkeletonState.HeavySwing:
            direction = player.transform.position - this.transform.position;
            this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);

            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", true);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", false);

            break;

        case SkeletonState.Die:
            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", true);
            animator.SetBool("isResurrection", false);

            break;

        case SkeletonState.Resurrection:
            animator.SetBool("isIdle", false);
            animator.SetBool("isRunning", false);
            animator.SetBool("isWalking", false);
            animator.SetBool("isWalkingBack", false);
            animator.SetBool("isWalkingLeft", false);
            animator.SetBool("isWalkingRight", false);
            animator.SetBool("isSwingQuickly", false);
            animator.SetBool("isSwingHeavily", false);
            animator.SetBool("isDead", false);
            animator.SetBool("isResurrection", true);

            break;
        }
    }
 // Determines whether specified state equals skeleton state.
 bool IsInCurrentState(SkeletonState currentState)
 {
     return this.state == currentState;
 }
 // Reacts on collision with skeleton collider.
 void OnCollisionEnter(Collision collision)
 {
     if(collision.gameObject.name == "Projectile"
         && this.state != SkeletonState.Dying
         && this.state != SkeletonState.Hit) {
         // Set unstable hit state to signal collision with projectile.
         this.state = SkeletonState.Hit;
     }
 }
 // Performs actions for pursuing state.
 IList<IAction> Pursue()
 {
     // Set current state to pursuing.
     SkeletonState currentState = SkeletonState.Pursuing;
     // Remember players height level.
     float height = this.Player.transform.position.y;
     // Create single-step action triggering run animation.
     IAction goPursue = new CustomAction(
         () => {
             // Set current state to pursuing.
             this.state = currentState;
             // Set animation to run.
             this.animation.CrossFade("run");
         });
     // Create continuous action steering skeleton motion.
     IAction pursuing = new CustomAction(
         () => {
             // Obtain current player position.
             Vector3 targetPosition = this.Player.transform.position;
             // Evaluate rotation sign for obtain rotation spin.
             float targetSign = this.EvaluateAxisSign(targetPosition);
             // Move skeleton position and rotation approxiamting to the target.
             this.StepToTarget(targetPosition, targetSign);
         },
         // Action is active while:
         () => this.IsInCurrentState(currentState)		// state of skeleton hasn't been modified,
             && this.IsOnTheSamePlatform(height)			// player remains on the same platform,
             && this.IsPlayerNear());					// player remains in near distance.
     // Create single-step action choosing next state.
     IAction next = new CustomAction(
         () => {
             // If skeleton has remained in pursuing state
             if(this.IsInCurrentState(currentState)) {
                 // then go into idle.
                 this.actionQueue.Enqueue(this.Stop());
             // If skeleton has got hit
             } else if (this.state == SkeletonState.Hit) {
                 // then go into dying state.
                 this.actionQueue.Enqueue(this.Die());
             } else {
                 throw new InvalidProgramException("Unreachable code");
             }
         });
     return new List<IAction> { goPursue, pursuing, next };
 }
示例#20
0
    public void SkeletonStateMachine()
    {
        switch (ActiveState)
        {
        case SkeletonState.ATTACK:
        {
            if (!inAttack && anim.GetBool("AttackEnded"))         //start attack
            {
                inAttack = true;
                anim.SetBool("Attack", true);
                if (boostCoroutine != null)
                {
                    StopCoroutine(boostCoroutine);
                }
                nav.angularSpeed = angularSpeedBase * 0.75f;         //we want that the enemy spins to the enemy position, but more slow
                //this change will reverted at the end of animation
            }
            else
            {
                if (inAttack && anim.GetBool("AttackEnded"))              //attack ended
                {
                    boostCoroutine = StartCoroutine(BoostAngularSpeed()); //we boost the speed when the enemy finish the atack
                    inAttack       = false;
                    SetAttackID(anim.GetInteger("AttackID"));
                    nextAtack   = attackList.GetNextAttack();
                    ActiveState = SkeletonState.CHASE;
                    nav.SetDestination(target);
                }
                else         //in attack anim
                {
                    FaceObjective(target);
                    SetIsAttacking(anim.GetBool("CalculateDamage"));
                    if (weaponHitbox.GetHitted() && GetIsAttacking())
                    {
                        if (GetAttackID() != anim.GetInteger("AttackID"))         //if this enemy dont has attack yet
                        {
                            if (weaponHitbox.GetHittedEnemy().GetComponentInParent <PlayerCombat>() != null)
                            {
                                weaponHitbox.GetHittedEnemy().GetComponentInParent <PlayerCombat>().ChangeStats(CombatStatsType.HP, -GetDamage());        //do damage
                                SetAttackID(anim.GetInteger("AttackID"));
                                weaponHitbox.GetHittedEnemy().GetComponentInParent <PlayerCombat>().SetEnemyLastAttackID(GetAttackID());
                            }
                        }
                        else
                        {
                            if (GetAttackID() != weaponHitbox.GetHittedEnemy().GetComponentInParent <PlayerCombat>().GetEnemyLastAttackID())
                            {
                                if (weaponHitbox.GetHittedEnemy().GetComponentInParent <PlayerCombat>() != null)
                                {
                                    weaponHitbox.GetHittedEnemy().GetComponentInParent <PlayerCombat>().ChangeStats(CombatStatsType.HP, -GetDamage());
                                    weaponHitbox.GetHittedEnemy().GetComponentInParent <PlayerCombat>().SetEnemyLastAttackID(GetAttackID());
                                }

                                //if we hit 2 enemies we have this case
                            }
                            else
                            {
                                //El problema esta es que si golpeamos a más de un enemigo y por casualidad tiene el segundo (o posteriores)
                                //enemigos que reciben el golpe tienen como ultima id del golpe la id de ataque este enemigo, el sistema se cree
                                //que este enemigo ya ha sido golpeado. En el juego actualmente este error no puede pasar, pero si por ejemplo
                                //hacemos que el jugador tenga una mascota o invocacion, el error si ocurrira, para solucionarlo podriamos poner
                                //una lista en cada combatiente, con la id del ser, y la ultima id del hit, de esta forma arreglariamos el problema
                                //
                            }
                        }
                    }
                }
            }

            break;
        }

        case SkeletonState.CHASE:
        {
            nav.SetDestination(target);
            break;
        }

        case SkeletonState.HOLD:
        {
            if (!FaceAndCheckObjective(hold.DirectionToFace(), 2f))         //This will be better if we check once per second instead 1 per frame
            {
                ActiveState = SkeletonState.RETURNING_TO_POSITION;
            }

            break;
        }

        case SkeletonState.PATROL:
        {
            if (transform.position.x <= target.x + 0.4f && transform.position.x >= target.x - 0.4f && transform.position.z <= target.z + 0.4f && transform.position.z >= target.z - 0.4f)
            {
                target = patrol.GetNewWaipoint(target);
                nav.SetDestination(target);
            }
            break;
        }

        case SkeletonState.PLAYER_LOST:
        {
            if (transform.position.x <= target.x + 0.4f && transform.position.x >= target.x - 0.4f && transform.position.z <= target.z + 0.4f && transform.position.z >= target.z - 0.4f)
            {
                if (!chase.GetWaiting())
                {
                    chase.InLastKnowPosition();
                }
                if (chase.GetEndChase())
                {
                    if (staticEnemy)
                    {
                        target = hold.ReturnToPosition();
                        nav.SetDestination(target);
                        ActiveState = SkeletonState.RETURNING_TO_POSITION;
                    }
                    else
                    {
                        target = patrol.GetClosestWaipoint(transform.position);
                        nav.SetDestination(target);
                        ActiveState = SkeletonState.PATROL;
                    }
                }
            }
            break;
        }

        case SkeletonState.RETURNING_TO_POSITION:
        {
            if (transform.position.x <= target.x + 0.4f && transform.position.x >= target.x - 0.4f && transform.position.z <= target.z + 0.4f && transform.position.z >= target.z - 0.4f)
            {
                if (FaceAndCheckObjective(hold.DirectionToFace(), 2f))
                {
                    ActiveState = SkeletonState.HOLD;
                }
                else
                {
                    FaceObjective(hold.DirectionToFace());
                }
            }
            break;
        }

        case SkeletonState.DIED:
        {
            break;
        }
        }
    }
示例#21
0
    // Update is called once per frame
    void Update()
    {
        if (UpdateTimer(ref _deathCount))
        {
            Destroy(gameObject);
        }
        if (UpdateTimer(ref _attackCount))
        {
            CurrentState            = SkeletonState.Walking;
            _attackCooldownDuration = AttackCooldown;
        }

        UpdateTimer(ref _attackCooldownDuration);

        float hMov = 0;

        if (CurrentState == SkeletonState.Attacking && _attackCount <= AxeOnTime)
        {
            if (_attackCount <= AxeOffTime)
            {
                axeHitbox.enabled = false;
            }
            else
            {
                axeHitbox.enabled = true;
            }
        }

        if (CurrentState != SkeletonState.Attacking && _deathCount <= 0f)
        {
            float distance = Vector2.Distance(transform.position, playerTransform.position);
            if (distance < PlayerDistance)
            {
                if (distance < SkeletonAttackRange && _attackCooldownDuration <= 0f) // Attacks
                {
                    _attackCount = AttackDuration;
                    CurrentState = SkeletonState.Attacking;
                }
                else // Waits For Player
                {
                    CurrentState = SkeletonState.WaitingForPlayer;
                    SetDirection(Mathf.Clamp(playerTransform.position.x - transform.position.x, -1, 1).ToDirection());
                }
            }
            else
            {
                CurrentState = SkeletonState.Walking;
                // Walk Routine
                Vector2 nextPosition = _patrolIndex == 0 ? FirstStop : SecondStop;

                hMov = Mathf.Clamp(nextPosition.x - transform.position.x, -1, 1);

                if (Vector2.Distance(transform.position, nextPosition) < PositionError)
                {
                    _patrolIndex = _patrolIndex == 1 ? 0 : 1;
                }

                SetDirection(hMov.ToDirection());
            }
        }
        rb.velocity = new Vector2(hMov * Time.deltaTime * 60 * Speed, rb.velocity.y);

        UpdateAnimation();
    }
 // Performs actions for running in random direction state.
 IList<IAction> Run()
 {
     // Set current state to running.
     SkeletonState currentState = SkeletonState.Running;
     // Random target in radius specified by MaxRandomTargetDistance.
     Vector3 targetPosition = this.RandomTargetPosition(MaxRandomTargetIterations);
     // Evaluate rotation sign for constant rotation spin.
     float targetSign = this.EvaluateAxisSign(targetPosition);
     // Create single-step action triggering run animation.
     IAction goRun = new CustomAction(
         () => {
             // Set current state to running.
             this.state = currentState;
             // Set animation to run.
             this.animation.CrossFade("run");
         });
     // Create continuous action steering skeleton motion.
     IAction running = new CustomAction(
         () => {
             // Move skeleton position and rotation approxiamting to the target.
             this.StepToTarget(targetPosition, targetSign);
         },
         // Action is active while:
         () => this.IsInCurrentState(currentState)		// state of skeleton hasn't been modified,
             && !this.IsTargetReached(targetPosition)	// target hasn't been reached yet,
             && !this.IsPlayerNear());					// player is not in near distance.
     // Create single-step action choosing next state.
     IAction next = new CustomAction(
         () => {
             // If skeleton has remained in running state
             if(this.IsInCurrentState(currentState)) {
                 // and player has came near
                 if(this.IsPlayerNear()) {
                     // then go into warning state
                     this.actionQueue.Enqueue(this.Warn());
                 // when there is no player around
                 } else {
                     // then go into idle.
                     this.actionQueue.Enqueue(this.Stop());
                 }
             // If skeleton has got hit
             } else if (state == SkeletonState.Hit) {
                 // then go into dying state.
                 this.actionQueue.Enqueue(this.Die());
             } else {
                 throw new InvalidProgramException("Unreachable code");
             }
         });
     return new List<IAction> { goRun, running, next };
 }
 // Performs actions for warning state.
 IList<IAction> Warn()
 {
     // Set current state to warning.
     SkeletonState currentState = SkeletonState.Warning;
     // Delimit time of warning state expiration.
     float warningTime = Time.time + WarningTime;
     // Create single-step action triggering waiting for battle animation.
     IAction goWarn = new CustomAction(
         () => {
             // Set current state to warning.
             this.state = currentState;
             // Set waiting for battle animation.
             this.animation.CrossFade("waitingforbattle");
         });
     // Create continuous action doing nothing.
     IAction warning = new CustomAction(
         () => { },		// Does nothing but waiting for termination condition come into being.
         // Action is active while:
         () => this.IsInCurrentState(currentState)		// state of skeleton hasn't been modified,
             && !this.IsTimeOut(warningTime)				// warning timeout doesn't occured,
             && this.IsPlayerNear()						// player is in near distance,
             && !this.IsPlayerVeryClose());				// but hasn't came too close.
     // Create single-step action choosing next state.
     IAction next = new CustomAction(
         () => {
             // If skeleton has remained in warning state
             if(this.IsInCurrentState(currentState)) {
                 // and player has remained near
                 if(this.IsPlayerNear()) {
                     // then pursue him,
                     this.actionQueue.Enqueue(this.Pursue());
                 // when player has drifted away
                 } else {
                     // then go into idle.
                     this.actionQueue.Enqueue(this.Stop());
                 }
             // If skeleton has got hit
             } else if (state == SkeletonState.Hit) {
                 // then go into dying state.
                 this.actionQueue.Enqueue(this.Die());
             } else {
                 throw new InvalidProgramException("Unreachable code");
             }
         });
     return new List<IAction> { goWarn, warning, next };
 }
 // Performs actions for idle state.
 IList<IAction> Stop()
 {
     // Delimit time of idle state expiration.
     float stopTime = Time.time + this.RandomTimeSpan(this.AverageIdleTime);
     // Set current state to idle.
     SkeletonState currentState = SkeletonState.Idle;
     // Create single-step action triggering idle animation.
     IAction goIdle = new CustomAction(
         () => {
             // Set current state to idle.
             this.state = currentState;
             // Set animation to idle.
             this.animation.CrossFade("idle");
         });
     // Create continuous action doing nothing.
     IAction beingIdle = new CustomAction(
         () => {	},	// Does nothing but waiting for termination condition come into being.
         // Action is active while:
         () => this.IsInCurrentState(currentState)	// state of skeleton hasn't been modified,
             && !this.IsTimeOut(stopTime)			// idle timeout doesn't occured,
             && !this.IsPlayerNear());				// player is not in near distance.
     // Create single-step action choosing next state.
     IAction next = new CustomAction(
         () => {
             // If skeleton has remained in idle state
             if(this.IsInCurrentState(currentState)) {
                 // and player has came near
                 if(this.IsPlayerNear()) {
                     // then go into warning state
                     this.actionQueue.Enqueue(this.Warn());
                 // when there is no player around
                 } else {
                     // then go into running in random direction.
                     this.actionQueue.Enqueue(this.Run());
                 }
             // If skeleton has got hit
             } else if (state == SkeletonState.Hit) {
                 // then go into dying state.
                 this.actionQueue.Enqueue(this.Die());
             } else {
                 throw new InvalidProgramException("Unreachable code");
             }
         });
     return new List<IAction> { goIdle, beingIdle, next };
 }
 void Start()
 {
     sw.Reset();
     skeletonState = SkeletonState.Idle;
 }