public override WormAIBaseState Update()
    {
        switch (subState)
        {
        case SubState.GOING_TO_ENTRY:
            //Position head below entry point
            currentX = bb.GetJumpXGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false);
            Vector3 startPosition = bb.GetJumpPositionGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false);
            headTrf.position = startPosition;
            lastPosition     = startPosition;
            head.SetVisible(true);

            origin.WormEnterExit();

            subState = SubState.JUMPING;
            break;

        case SubState.JUMPING:
            //While not again below underground navmesh layer advance
            currentX        += Time.deltaTime * bb.spawnSpeed;
            lastPosition     = headTrf.position;
            headTrf.position = bb.GetJumpPositionGivenX(currentX);

            headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up);

            if (lastPosition.y > headTrf.position.y && rotation < 90f)
            {
                if (!highestPointReached)
                {
                    highestPointReached = true;
                }

                float angle = 30 * Time.deltaTime;
                headTrf.Rotate(new Vector3(0, 0, angle));
                rotation += angle;
            }

            if (!destinyInRange)
            {
                float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude;
                if (distanceToDestiny <= destinyInRangeDistance ||
                    (headTrf.position.y < destiny.transform.position.y &&
                     currentX >= 0))    //Safety check. When jump is too fast distance can never be less than range distance
                {
                    destinyInRange = true;

                    AttackActions();

                    destiny.WormAboveAttackStart();
                }
            }

            if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT)
            {
                SetHeadUnderground();

                subState = SubState.EXITING;
            }
            break;

        case SubState.EXITING:
            currentX        += Time.deltaTime * bb.spawnSpeed;
            lastPosition     = headTrf.position;
            headTrf.position = bb.GetJumpPositionGivenX(currentX);

            headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition));

            if (bb.tailReachedMilestone)
            {
                Vector3 pos = headTrf.position;
                pos.y            = -WormBlackboard.NAVMESH_LAYER_HEIGHT;
                headTrf.position = pos;

                return(head.wanderingState);
            }
            break;

        default:
            break;
        }

        return(null);
    }
    public override WormAIBaseState Update()
    {
        if (destiny == null)
        {
            return(head.wanderingState);
        }

        switch (subState)
        {
        case SubState.WARNING_PLAYER:
            headTrf.rotation = Quaternion.RotateTowards(headTrf.rotation, initialRotation, 90 / bb.AboveAttackSettingsPhase.warningTime * Time.deltaTime);

            if (elapsedTime >= bb.AboveAttackSettingsPhase.warningTime)
            {
                head.jumpAttackSoundFx.Play();
                subState = SubState.JUMPING;
            }
            else
            {
                elapsedTime += Time.deltaTime;
            }

            break;

        case SubState.JUMPING:
            //While not again below underground navmesh layer advance
            currentX        += Time.deltaTime * speed;
            lastPosition     = headTrf.position;
            headTrf.position = bb.GetJumpPositionGivenX(currentX);

            headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up);

            if (rotation < bb.AboveAttackSettingsPhase.selfRotation)
            {
                float angle = bb.AboveAttackSettingsPhase.selfRotation / bb.AboveAttackSettingsPhase.jumpDuration * Time.deltaTime;
                headTrf.Rotate(new Vector3(0, 0, angle));
                rotation += angle;
            }

            if (!destinyInRange)
            {
                float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude;
                if (distanceToDestiny <= destinyInRangeDistance ||
                    headTrf.position.y < destiny.transform.position.y)     //Safety check. When jump is too fast distance can never be less than range distance
                {
                    destinyInRange = true;
                    AttackActions();
                    destiny.WormAboveAttackStart();
                }
            }

            if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT)
            {
                SetHeadUnderground();
                subState = SubState.EXITING;
            }
            break;

        case SubState.EXITING:
            currentX        += Time.deltaTime * speed;
            lastPosition     = headTrf.position;
            headTrf.position = bb.GetJumpPositionGivenX(currentX);

            headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition));

            if (bb.tailReachedMilestone)
            {
                Vector3 pos = headTrf.position;
                pos.y            = -WormBlackboard.NAVMESH_LAYER_HEIGHT;
                headTrf.position = pos;

                return(head.wanderingState);
            }
            break;

        default:
            break;
        }

        return(null);
    }