Forum begins after the advertisement:


[part 10] dive causes unity to freeze completely

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [part 10] dive causes unity to freeze completely

Viewing 15 posts - 16 through 30 (of 46 total)
  • Author
    Posts
  • #15975
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    forget what i said about the bat i just fixed it.

    i have some questions about the boss:

    so this boss is fairly early on in my game so my player doesnt have the double jump unlocked, the boss is also quite a bit larger than the player so when dashing, im wondering if you can decrease the size of the box collider so my player can jump over it? ive tried changing it wiht key frames in the animator but since the box collider is on the boss handler and not the animate boss its not possible?? any way to do that?

    Also wondering if i can increase frequency of attacks since i am able to walkk upto my boss and wait there for a 5-8 seconds before it attacks me?

    #15976
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    i also have an odd issue:

    i watched your 10.5 bug fixing update but the dive is a bit bugged? when my player is nearby, the boss will be raised a tiny bit off the ground and loop only the first half of the diving animation. When hit in this state, the boss will perform parry and riposte animations but will then return to looping the diving anim. ive chcked the inspaector and the diving animation doesnt loop and idk whats wrong? ive even tried reverting my code to before i fixed it and it still stays like this

    this only happens when im really close to the boss

    diving script:

    <code>using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WoodenBotDive : StateMachineBehaviour
    {
        Rigidbody2D rb;
    
        bool callOnce;
    
        // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb = animator.GetComponentInParent<Rigidbody2D>();
        }
    
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            WoodenBot.Instance.divingCollider.SetActive(true);
    
            if (WoodenBot.Instance.Grounded())
            {
                WoodenBot.Instance.divingCollider.SetActive(false);
    
                if (!callOnce && DivingPillar.count < 10)
                {
                    Debug.Log("callOnce is true");
                    WoodenBot.Instance.DivingPillars();
                    animator.SetBool("Dive", false);
                    WoodenBot.Instance.ResetAllAttacks();
                    callOnce = true;
                }
    
            }
        }
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            callOnce = false;
            Debug.Log("CallOnce is false");
        }
    
    }</code>

    idle script:

    <code>using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WoodenBotIdle : StateMachineBehaviour
    {
        Rigidbody2D rb;
    
        // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb = animator.GetComponentInParent<Rigidbody2D>();
        }
    
        // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb.velocity = Vector2.zero;
            RunToPlayer(animator);
    
            if(WoodenBot.Instance.attackCountdown <= 0)
            {
                WoodenBot.Instance.AttackHandler();
                WoodenBot.Instance.attackCountdown = Random.Range(WoodenBot.Instance.attackTimer - 1, WoodenBot.Instance.attackTimer + 1);
            }
    
            if (!WoodenBot.Instance.Grounded())
            {
    
                rb.velocity = new Vector2(rb.velocity.x, -25);
            }
    
        }
    
        void RunToPlayer(Animator animator)
        {
            if(Vector2.Distance(PlayerController.Instance.transform.position, rb.position) > WoodenBot.Instance.attackRange)
            {
                animator.SetBool("Run", true);
            }
            else
            {
                return;
            }
        }
    
        // OnStateExit is called when a transition ends and the state machine finishes evaluating this state
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
    
        }
    
    }</code>

    diving functions from wooden bot script:

    <code>
        void DiveAttackJump()
        {
            attacking = true;
            moveToPosition = new Vector2(PlayerController.Instance.transform.position.x, rb.position.y + 10);
            diveAttack = true;
            anim.SetBool("Jump", true);
        }
    
        public void Dive()
        {
            anim.SetBool("Dive", true);
            anim.SetBool("Jump", false);
    
        }
    
        public void DivingPillars()
        {
            Vector2 _impactPoint = groundCheckPoint.position;
    
            float _spawnDistance = 5;
    
            for (int i = 0; i < 10; i++)
            {
                Vector2 _pillarSpawnPointRight = _impactPoint + new Vector2(_spawnDistance, -0.25f);
                Vector2 _pillarSpawnPointLeft = _impactPoint - new Vector2(_spawnDistance, -0.25f);
    
                Instantiate(pillar, _pillarSpawnPointRight, Quaternion.Euler(0, 0, 0));
                Instantiate(pillar, _pillarSpawnPointLeft, Quaternion.Euler(0, 0, 0));
                Debug.Log("pillars spawned");
    
                _spawnDistance += 7;
    
            }
    
            ResetAllAttacks();
        }</code>

    sorry abt all the questions- its my first game and all

    #15977
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    side note – just had a look at the link for fixing my camera:

    extrapolate makes my movement feel really good but doesnt fix the camera jitter

    interpolate makes my camera very very jittery and also makes my character move increadibly slow? it feels like all values for my characters movememnts have been divided by 1000? gravity, walkspeed, jumpforce, everything is slower

    #15988
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    Sorry, but can we get a video of the Dive attack error? I can’t quite picture what the issue is exactly.

    In the case that it’s completing the dive attack, and then going for another dive attack infinitely, Then this might be an issue with your AttackHandler.

    If it’s that your Boss is stuck in the Dive animation, Does it ever complete the dive? Or can it perform otehr actions like moving horizontally too?

    Could you also show your Boss script, just in case?


    Here’s a suggestion for the Dashing through the Boss.

    You could try the Changing of Layers for the Player only during dash, like in Part 6.5 with the Bat.

    [Part 6 Bug Fixes] Infinite Recoil Bat, Spikes Freeze Game, Optimized Bat Corpse

    Essentially, you will want to change your Player’s Layer to something that cant touch the boss yet can still collide with terrain, while you are dashing. Then turn it back to normal once you get out of dashing.


    As for the Camera, you could you take a look at your Camera’s settings once more, perhaps it was not set correctly during the transition?

    You can cross-reference with the video at this point:

    #15990
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::
    View post on imgur.com

    this is a link and shows the error, my camera jitter and the inspector settings for my camera

    i checked my inspector and the camera seems to be set right??

    ive also noticed, while testing, my barrage will sometimes just not activate and ill be stuck on the bendown animation, however if attacked, my boss will reset its attack and resume as normal unlike getting stuck in the dive

    code for my boss::

    <code>ng System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WoodenBot : Enemy
    {
    
        public static WoodenBot Instance;
    
        [Header("Ground Check Settings")]
        [SerializeField] private Transform groundCheckPoint;
        [SerializeField] private float groundCheckY = 0.2f;
        [SerializeField] private float groundCheckX = 0.5f;
        [SerializeField] private LayerMask whatIsGround;
    
        [SerializeField] private Transform wallCheckPoint;
    
        int hitCounter;
        bool stunned, canStun;
        bool alive;
    
        [HideInInspector] public bool facingRight;
        [HideInInspector] public float runSpeed;
        [HideInInspector] public bool damagePlayer = false;
        [HideInInspector] public bool parrying;
    
        [HideInInspector] public Vector2 moveToPosition;
    
        [Space(5)]
    
        [Header("attack settings")]
        [SerializeField] public Transform SideAttackTransform, UpAttackTransform, DownAttackTransform;
        [SerializeField] public Vector2 SideAttackArea, UpAttackArea, DownAttackArea;
        [SerializeField] public GameObject slashEffect;
    
        public float attackRange;
        public float attackTimer;
    
        [HideInInspector] public bool diveAttack;
        public GameObject divingCollider;
        public GameObject pillar;
    
        [HideInInspector] public bool barrageAttack;
        public GameObject barrageFireball;
    
        [HideInInspector] public bool outbreakAttack;
    
        [HideInInspector] public bool bounceAttack;
    
        [HideInInspector] public float rotationDirectionToTarget;
    
        [HideInInspector] public int bounceCount;
    
        public bool Grounded()
        {
            if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround)
                || Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)
                || Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
            {
                return true;
            }
            else
            {
    
                return false;
            }
        }
    
        public bool TouchedWall()
        {
            if (Physics2D.Raycast(wallCheckPoint.position, Vector2.down, groundCheckY, whatIsGround)
                || Physics2D.Raycast(wallCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround)
                || Physics2D.Raycast(wallCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
    
            Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
            Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
            Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
    
        }
    
        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
            }
            else
            {
                Instance = this;
            }
    
        }
    
        // Start is called before the first frame update
        protected override void Start()
        {
            base.Start();
            sr = GetComponentInChildren<SpriteRenderer>();
            anim = GetComponentInChildren<Animator>();
    
            ChangeState(EnemyStates.woodenBot_stage1);
            alive = true;
        }
    
        // Update is called once per frame
        protected override void Update()
        {
            base.Update();
    
            if (health <= 0 && alive)
            {
                Death(0);
            }
    
            if (!attacking)
            {
                attackCountdown -= Time.deltaTime;
            }
    
            if (stunned)
            {
                rb.velocity = Vector2.zero;
            }
    
        }
    
        public void Flip()
        {
            if (PlayerController.Instance.transform.position.x < transform.position.x && transform.localScale.x > 0)
            {
                transform.eulerAngles = new Vector2(transform.eulerAngles.x, 180);
                facingRight = false;
            }
            else
            {
                transform.eulerAngles = new Vector2(transform.eulerAngles.x, 0);
                facingRight = true;
            }
        }
    
        protected override void UpdateEnemyStates()
        {
            if (PlayerController.Instance != null)
            {
                switch (GetCurrentEnemyState)
                {
                    case EnemyStates.woodenBot_stage1:
                        attackTimer = 6;
                        canStun = true;
                        runSpeed = speed;
                        break;
    
                    case EnemyStates.woodenBot_stage2:
                        canStun = true;
                        attackTimer = 3;
                        break;
    
                    case EnemyStates.woodenBot_stage3:
                        canStun = false;
                        attackTimer = 3;
                        break;
    
                    case EnemyStates.woodenBot_stage4:
                        canStun= false;
                        attackTimer = 3;
                        break;
                }
    
            }
        }
    
        protected override void OnCollisionStay2D(Collision2D _other)
        {
    
        }
    
        #region attacking
        #region variables
        [HideInInspector] public bool attacking;
        [HideInInspector] public float attackCountdown;
    
        #endregion
        #endregion
    
        #region AttackHandler
    
        public void AttackHandler()
        {
            if (currentEnemyState == EnemyStates.woodenBot_stage1)
            {
                Debug.Log("Stage 1");
                if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange)
                {
                    StartCoroutine(TripleSlash());
                }
                else
                {
                    StartCoroutine(Lunge());
                }
            }
    
            if (currentEnemyState == EnemyStates.woodenBot_stage2)
            {
    
                Debug.Log("Stage 2");
                if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange)
                {
                    StartCoroutine(TripleSlash());
    
                }
                else
                {
                   int _attackChosen = Random.Range(1, 4);
                    if(_attackChosen == 1)
                    {
    
                        BarrageBendDown();
                        Debug.Log("barrage chosen");
                    }
                    if (_attackChosen == 2)
                    {
                        DiveAttackJump();
                        Debug.Log("dive chosen");
                    }
                    if (_attackChosen == 3)
                    {
                        StartCoroutine(Lunge());
                        Debug.Log("lunge chosen");
                    }
                }
            }
    
            if (currentEnemyState == EnemyStates.woodenBot_stage3)
            {
                Debug.Log("Stage 3");
                int _attackChosen = Random.Range(1, 5);
                if (_attackChosen == 1)
                {
                    OutBreakBendDown();
                }
                if (_attackChosen == 2)
                {
                    DiveAttackJump();
                }
                if (_attackChosen == 3)
                {
                    BarrageBendDown();
                }
                if (_attackChosen == 4)
                {
                    BounceAttack();
                }
    
            }
    
            if (currentEnemyState == EnemyStates.woodenBot_stage4)
            {
    
                Debug.Log("Stage 4");
                if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange)
                {
                    StartCoroutine(Slash());
                }
                else
                {
                    BounceAttack();
                }
            }
        }
    
        public void ResetAllAttacks()
        {
            attacking = false;
            StopCoroutine(Lunge());
            StopCoroutine(Parry());
            StopCoroutine(TripleSlash());
            StopCoroutine(Slash());
    
            diveAttack = false;
            barrageAttack = false;
            outbreakAttack = false;
            bounceAttack = false;
        }
    
        #endregion
    
        #region Stage 1
    
        IEnumerator TripleSlash()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
            anim.SetTrigger("Slash");
            SlashAngle();
            yield return new WaitForSeconds(2);
            anim.SetTrigger("Slash 2");
            SlashAngle();
            yield return new WaitForSeconds(2);
            anim.SetTrigger("Slash 3");
            SlashAngle();
            yield return new WaitForSeconds(2);
    
            ResetAllAttacks();
    
        }
    
        void SlashAngle()
        {
            if (PlayerController.Instance.transform.position.x > transform.position.x ||
                PlayerController.Instance.transform.position.x < transform.position.x)
            {
                Instantiate(slashEffect, SideAttackTransform);
            }
            else if (PlayerController.Instance.transform.position.y > transform.position.y)
            {
                SlashEffectAtAngle(slashEffect, 80, UpAttackTransform);
            }
            else if (PlayerController.Instance.transform.position.y < transform.position.y)
            {
                SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
            }
    
        }
    
        void SlashEffectAtAngle(GameObject _slashEffect, int _effectAngle, Transform _attackTransform)
        {
            _slashEffect = Instantiate(_slashEffect, _attackTransform);
            _slashEffect.transform.eulerAngles = new Vector3(0, 0, _effectAngle);
            _slashEffect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
    
        }
    
        IEnumerator Lunge()
        {
            Flip();
            attacking = true;
    
            anim.SetBool("Lunge", true);
            yield return new WaitForSeconds(1);
            damagePlayer = false;
            anim.SetBool("Lunge", false);
    
            ResetAllAttacks();
        }
    
        IEnumerator Parry()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
            anim.SetBool("Parry", true);
            yield return new WaitForSeconds(0.8f);
            anim.SetBool("Parry", false);
            parrying = false;
            ResetAllAttacks();
        }
    
        IEnumerator Slash()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
            anim.SetTrigger("Slash");
            SlashAngle();
            yield return new WaitForSeconds(2);
    
            ResetAllAttacks();
        }
    
        #endregion
    
        #region Stage 2
    
        void DiveAttackJump()
        {
            attacking = true;
            moveToPosition = new Vector2(PlayerController.Instance.transform.position.x, rb.position.y + 10);
            diveAttack = true;
            anim.SetBool("Jump", true);
        }
    
        public void Dive()
        {
            anim.SetBool("Dive", true);
            anim.SetBool("Jump", false);
    
        }
    
        public void DivingPillars()
        {
            Vector2 _impactPoint = groundCheckPoint.position;
    
            float _spawnDistance = 5;
    
            for (int i = 0; i < 10; i++)
            {
                Vector2 _pillarSpawnPointRight = _impactPoint + new Vector2(_spawnDistance, -0.25f);
                Vector2 _pillarSpawnPointLeft = _impactPoint - new Vector2(_spawnDistance, -0.25f);
    
                Instantiate(pillar, _pillarSpawnPointRight, Quaternion.Euler(0, 0, 0));
                Instantiate(pillar, _pillarSpawnPointLeft, Quaternion.Euler(0, 0, 0));
                Debug.Log("pillars spawned");
    
                _spawnDistance += 7;
    
            }
    
            ResetAllAttacks();
        }
    
        void BarrageBendDown()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
            barrageAttack = true;
            anim.SetTrigger("BendDown");
    
        }
    
        public IEnumerator Barrage()
        {
            rb.velocity = Vector2.zero;
    
            float _currentAngle = 30f;
    
            for (int i = 0; i < 10; i++)
            {
                GameObject _projectile = Instantiate(barrageFireball, DownAttackTransform.position, Quaternion.Euler(0, 0, _currentAngle));
    
                if (facingRight)
                {
                    _projectile.transform.eulerAngles = new Vector3(_projectile.transform.eulerAngles.x, 0, _currentAngle + 45);
                }
                else
                {
                    _projectile.transform.eulerAngles = new Vector3(_projectile.transform.eulerAngles.x, 180, _currentAngle + 45);
                }
    
                _currentAngle = 5f;
    
                yield return new WaitForSeconds(0.4f);
            }
            yield return new WaitForSeconds(0.1f);
            anim.SetBool("Barrage", false);    
            ResetAllAttacks();
        }
    
        private void OnTriggerEnter2D(Collider2D _other)
        {
            if (_other.GetComponent<PlayerController>() != null && (diveAttack || bounceAttack))
            {
                _other.GetComponent<PlayerController>().TakeDamage(damage * 2);
                PlayerController.Instance.pState.recoilingx = true;
            }
        }</code>
    #15991
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    also for my camera, it was set up properly as this jitteryness only occured when i switched laptops. Strange errors just appeared when switching laptops such as :

    camera jitters and bat enemy moved very slowly(fixed now)

    ichecked and im using the same unity editor version

    #15996
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    I am not certain about why your camera is not smoothly tracking your player, but focusing on the boss for now, can you test out the boss again.

    First, let’s Change your Dive animation to stop looping. You can do so by going into the Boss Animator/Animation and finding the Dive animation clip, double clicking it for the Inspector and turning off Loop.

    Then let’s test whether the Dive will stop should the boss touch the ground.

    Normally, the boss would move above the player, I think something might be wrong with the BossIdle script so let’s just try something by stopping it entirely whenever the boss wants to dive.

    public class WoodenBotIdle : StateMachineBehaviour
    {
        Rigidbody2D rb;
    
        // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb = animator.GetComponentInParent<Rigidbody2D>();
        }
    
        // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            if(!WoodenBot.Instance.diveAttack)
            {
                rb.velocity = Vector2.zero;
                RunToPlayer(animator);
    
                if(WoodenBot.Instance.attackCountdown <= 0)
                {
                    WoodenBot.Instance.AttackHandler();
                    WoodenBot.Instance.attackCountdown = Random.Range(WoodenBot.Instance.attackTimer - 1, WoodenBot.Instance.attackTimer + 1);
                }
    
                if (!WoodenBot.Instance.Grounded())
                {
                    rb.velocity = new Vector2(rb.velocity.x, -25);
                }
            }
        }
    
        void RunToPlayer(Animator animator)
        {
            if(Vector2.Distance(PlayerController.Instance.transform.position, rb.position) > WoodenBot.Instance.attackRange)
            {
                animator.SetBool("Run", true);
            }
            else
            {
                return;
            }
        }
    
        // OnStateExit is called when a transition ends and the state machine finishes evaluating this state
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
    
        }
    
    }

    This way we can see if the Idle script is impacting the Dive in any way.

    Finally, the Parry is supposed to turn off the diveAttack boolean through the method ResetAllAttacks, but that doesn’t stop the animator bools if I remember correctly. Thus, Let’s focus on trying to get the Boss to complete the Dive Attack before anything.


    Try these few things:

    1. While the boss is stuck in the Dive Animation, Move the boss in the inspector upwards by a bit. If the boss continues movement on it’s own, then it may just be stuck on the floor’s collision for some reason.

    Otherwise, 2) Move the boss back onto the ground after raising them in the air. If the boss completes the dive attack, then the Dive Attack is working fine but the boss simply cannot move.

    If the boss does not finish the dive upon touching the ground 3) Move the boss into the air and make it touch a wall. We implemented a wall check method for Dive and other attacks to immediately fall to the ground should they hit a wall. So this should work in letting the boss complete the attack while stuck. Just make sure the wall check is facing the correct direction when you move the boss to touch the wall. (Move the boss to touch the right wall if the wall check is on the right side of the boss.

    #16005
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    i just attemped all methods with no new results?

    i also want to say that sometimes the barrage attack will get stuck in the bendown animation – however, the boss will cotinue as normal if i hit the boss and it finishes parrying?

    really not sure whats wrong

    #16010
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    I think going simple, Is the looping animation your Jump animation?

    If it’s your jump animation can you check what your Jump state script has? and if there could be anything interfering with it calling Dive() in your boss script due to the player’s distance? In any case, could you send the jump script.

    #16011
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    heres the jump scripy:

    <code>using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WoodenBotJump : StateMachineBehaviour
    {
        Rigidbody2D rb;
    
        // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb = animator.GetComponentInParent<Rigidbody2D>();
        }
    
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            DiveAttack();
    
        }
    
        void DiveAttack()
        {
            if (WoodenBot.Instance.diveAttack)
            {
                WoodenBot.Instance.Flip();
    
                Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime);
    
                rb.MovePosition(_newPos);
    
                float _distance = Vector2.Distance(rb.position, _newPos);
    
                if (_distance < 0.1f)
                {
                    WoodenBot.Instance.Dive();
                }
    
                if (WoodenBot.Instance.TouchedWall())
                {
                    WoodenBot.Instance.moveToPosition.x = rb.velocity.x;
    
                    _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime);
    
                }
            }
    
        }
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
    
        }
    
    }</code>
    #16012
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    Let’s try something first for the dive and tell me the result:

    public class WoodenBotJump : StateMachineBehaviour
    {
        Rigidbody2D rb;
    
        // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb = animator.GetComponentInParent<Rigidbody2D>();
        }
    
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            DiveAttack();
    
        }
    
        void DiveAttack()
        {
            if (WoodenBot.Instance.diveAttack)
            {
                WoodenBot.Instance.Flip();
    
                Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime);
    
                rb.MovePosition(_newPos);
    
                float _distance = Vector2.Distance(rb.position, _newPos);
    
                if (_distance < 0.1f)
                {
                    WoodenBot.Instance.Dive();
                }
    
                if (WoodenBot.Instance.TouchedWall())
                {
                    WoodenBot.Instance.moveToPosition.x = rb.velocity.x;
    
                    _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime);
    
                }
            }
            else
            {
                animator.SetBool("Jump", false);
            }
        }
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
    
        }
    
    }

    What we’re doing here is checking if the Boss’ diveattack bool is turned off, causing the boss to be stuck in it’s jump state since it cannot call anything to get out of it. We could have also checked this on the Debug menu for the inspector, but through this way we can see it happen visually.

    If your boss is unable to dive attack anymore/jump while you are close that means that for some reason the diveattack is turned off.

    Also, can I just check with you that whenever you test the bug where the boss loops it’s dive, you only went close to it, did not attack it whatsoever?

    #16014
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    Ok some progress was made The boss sometimes does the jumping animation and it will freeze on the last frame on the ground instead of looping

    However I’ve noticed tje error happens significantly less but still does occur

    #16022
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    Let’s set up some prints in ResetAllAttacks() and DiveAttackJump() to see when they are being called.

    One of the only reasons why your boss is unable to come out of the dive is because the jump animation for some reason is not able to progress it’s OnStateUpdate() function. So likely the diveAttack bool is being set to false somehow, which is why we did the previous step of adding an else statement to exit the jump state.

    Now, the only way to set the diveAttack to false is through ResetAllAttacks() and completing the dive itself.

        public void ResetAllAttacks()
        {
            attacking = false;
            StopCoroutine(Lunge());
            StopCoroutine(Parry());
            StopCoroutine(TripleSlash());
            StopCoroutine(Slash());
    
            diveAttack = false;
            print("DiveAttack off");
            barrageAttack = false;
            outbreakAttack = false;
            bounceAttack = false;
        }
    
        void DiveAttackJump()
        {
            attacking = true;
            moveToPosition = new Vector2(PlayerController.Instance.transform.position.x, rb.position.y + 10);
            diveAttack = true;
            anim.SetBool("Jump", true);
            print("Starting Jump");
        }

    Let’s also check that your the else statement jump is also activating.

    public class WoodenBotJump : StateMachineBehaviour
    {
        Rigidbody2D rb;
    
        // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb = animator.GetComponentInParent();
        }
    
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            DiveAttack();
    
        }
    
        void DiveAttack()
        {
            if (WoodenBot.Instance.diveAttack)
            {
                WoodenBot.Instance.Flip();
    
                Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime);
    
                rb.MovePosition(_newPos);
    
                float _distance = Vector2.Distance(rb.position, _newPos);
    
                if (_distance < 0.1f)
                {
                    WoodenBot.Instance.Dive();
                }
    
                if (WoodenBot.Instance.TouchedWall())
                {
                    WoodenBot.Instance.moveToPosition.x = rb.velocity.x;
    
                    _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime);
                }
            }
            else
            {
                print("Stopping Jump");
                animator.SetBool("Jump", false);
            }
        }
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
    
        }
    }

    Now could you record another video showing the console and triggering the error a couple times?

    #16026
    Niyam Shah
    Level 8
    Participant
    Helpful?
    Up
    0
    ::

    the boss not working is infrequent but it does now revert to normal when hit.Also ive had to altersome of the code for the WoodenBotJump script since it wasnt working and piling with errors: it should be the same as urs justin a different order?

    <code>public class WoodenBotJump : StateMachineBehaviour
    {
        Rigidbody2D rb;
    
        // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            rb = animator.GetComponentInParent<Rigidbody2D>();
        }
    
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            if (WoodenBot.Instance.diveAttack)
            {
                DiveAttack();
            }
            else
            {
                animator.SetBool("Jump", false);
                Debug.Log("JumpAttack Off");
                WoodenBot.Instance.ResetAllAttacks();    
            }
    
        }
    
        void DiveAttack()
        {
    
            if (WoodenBot.Instance.diveAttack)
            {
                WoodenBot.Instance.Flip();
    
                Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 3 * Time.fixedDeltaTime);
    
                rb.MovePosition(_newPos);
    
                float _distance = Vector2.Distance(rb.position, _newPos);
    
                if (_distance < 0.1f)
                {
                    WoodenBot.Instance.Dive();
                }
    
                if (WoodenBot.Instance.TouchedWall())
                {
                    WoodenBot.Instance.moveToPosition.x = rb.velocity.x;
    
                    _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * Random.Range(2, 4) * Time.fixedDeltaTime);
    
                }
            }
    
        }
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
    
        }
    
    }</code>
    #16042
    Joseph Tang
    Level 13
    Moderator
    Helpful?
    Up
    0
    ::

    Sorry, but the print codes only work if we are able to see the console window whenever you test the boss out.

    Could you deactivate “Play Focused” to something else and keep your Console window open in your unity so we can see when the print messages are being made.

    Next this might be the problem as to why your dive stops working, the ResetAllAttacks() is delayed by so long after the boss performs a slash that it stops the diveattack when it happens occasionally. Perhaps why it happens so infrequently at all. This might also solve your Barrage attack issue similarly.

        IEnumerator Slash()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
            anim.SetTrigger("Slash");
            SlashAngle();
            yield return new WaitForSeconds(2 0.2);
    
            ResetAllAttacks();
        }
Viewing 15 posts - 16 through 30 (of 46 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: