Forum begins after the advertisement:


[Part 10] Boss hit very fast and Null ref

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 10] Boss hit very fast and Null ref

Viewing 15 posts - 1 through 15 (of 27 total)
  • Author
    Posts
  • #16384
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    So i was making the boss for the game. And when I making the boss event and test the 3 hit function. My boss hit very fast. As we could said it doesn’t reset the animator. It just 2 punch in a frame. And when the boss hit, the console send a message of NullReference. As you can see in what i show below. First is the test video

    then is the code. First is the CorruptedMonk.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class CorruptedMonk : Enemy
    {
        public static CorruptedMonk Instance;
    
        [Header("Attacking setting")]
        [SerializeField] public Transform sideAttackTransform, upAttackTransform, downAttackTransform;
        [SerializeField] public Vector2 sideAttackArea, upAttackArea, downAttackArea;
        [Space(5)]
    
        public float attackRange;
        public float attackTimer;
    
        [Header("Groundcheck setting")]
        [SerializeField] private Transform groundcheck;
        [SerializeField] private float groundchecky = 0.2f;
        [SerializeField] private float groundcheckx = 0.5f;
        [SerializeField] private LayerMask isground;
    
        int hitCounter;
        bool stunned, canStunned;
        bool alive;
    
        [HideInInspector] public float runSpeed;
        [HideInInspector] public bool facingRight;
        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.Monk_State1);
            alive = true;
        }
    
        public bool isonGround()
        {
            if (Physics2D.Raycast(groundcheck.position, Vector2.down, groundchecky, isground)
                || Physics2D.Raycast(groundcheck.position + new Vector3(groundcheckx, 0, 0), Vector2.down, groundchecky, isground)
                || Physics2D.Raycast(groundcheck.position + new Vector3(-groundcheckx, 0, 0), Vector2.down, groundchecky, isground)
                )
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.yellow;
            Gizmos.DrawWireCube(sideAttackTransform.position, sideAttackArea);
            Gizmos.DrawWireCube(upAttackTransform.position, upAttackArea);
            Gizmos.DrawWireCube(downAttackTransform.position, downAttackArea);
        }
        // Update is called once per frame
        protected override void Update()
        {
            base.Update();
            if (!attacking)
            {
                attackCountdown -= Time.deltaTime;
            }
        }
    
        public void Flip()
        {
            if (Move.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(Move.Instance != null)
            {
                switch (GetCurrentEnemyStates)
                {
                    case EnemyStates.Monk_State1:
                        break;
                    case EnemyStates.Monk_State2:
                        break;
                    case EnemyStates.Monk_State3: 
                        break;
                    case EnemyStates.Monk_State4: 
                        break;
                }
            } 
        }
    
        protected override void OnCollisionStay2D(Collision2D _other)
        {
    
        }
    
        public void ResetAllAttack()
        {
            attacking = false;
            StopCoroutine(TriplePunch());
        }
    
        #region attacking
        #region variables
        [HideInInspector] public bool attacking;
        [HideInInspector] public float attackCountdown;
        #endregion
    
        #region Control
    
        public void AttackHandler()
        {
            if(currentState == EnemyStates.Monk_State1)
            {
                if(Vector2.Distance(Move.Instance.transform.position,rb.position) <= attackRange)
                {
                    StartCoroutine(TriplePunch());
                }
                else
                {
                    return;
                }
            }
        }
    
        #endregion
    
        #region Stage1
        IEnumerator TriplePunch()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
            anim.SetTrigger("Punch");
            yield return new WaitForSeconds(0.3f);
            anim.ResetTrigger("Punch");
    
            anim.SetTrigger("Punch");
            yield return new WaitForSeconds(0.5f);
            anim.ResetTrigger("Punch");
    
            anim.SetTrigger("Punch");
            yield return new WaitForSeconds(0.1f);
            anim.ResetTrigger("Punch");
    
            ResetAllAttack();
        }
    
        #endregion
        #endregion
    
    }

    Then is the Corrupted_Monk_Event.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Corrupted_Monk_Event : MonoBehaviour
    {
        void PunchDamagePlayer()
        {
            if (Move.Instance.transform.position.x > transform.position.x || Move.Instance.transform.position.x < transform.position.x)
            {
                Hit(CorruptedMonk.Instance.sideAttackTransform, CorruptedMonk.Instance.sideAttackArea);
            }
            else if (Move.Instance.transform.position.y > transform.position.y)
            {
                Hit(CorruptedMonk.Instance.upAttackTransform, CorruptedMonk.Instance.upAttackArea);
            }
            else if (Move.Instance.transform.position.y < transform.position.y)
            {
                Hit(CorruptedMonk.Instance.downAttackTransform, CorruptedMonk.Instance.downAttackArea);
            }
        }
        void Hit(Transform _attackTrasnform, Vector2 _attackArea)
        {
            Collider2D[] _objectToHit = Physics2D.OverlapBoxAll(_attackTrasnform.position, _attackArea, 0);
            for(int i = 0 ; i < _objectToHit.Length; i++)
            {
                if (_objectToHit[i].GetComponent<Collider2D>() != null)
                {
                    _objectToHit[i].GetComponent<Move>().takeDmg(CorruptedMonk.Instance.dmgMake);
                }
            }
        }
    }
    Null ref error

    I even try to change from WaitForSecond to WaitForSecondRealTime but still doesn’t making the punch slow down. Tks you for the series. And another thank for helping me

    #16385
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    Update: I add a debug to check how many punch the boss does and it only make 3 punch. So the Boss still hitting 3 hit. But i got 6 damage and the boss doesn’t need to reset animation at all

    null and the null ref i already fix it. The getcomponent at the event first getcomponent i just took it wrong. From PlayerController to collider2d. It my fault. It kinda late in the time I made it so maybe my eyes has lied me.
    #16399
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    I really need help here. I making the diving pillar skill and the boss. It jump to the sky and dive down. But when he create the pilar. I only see that he only create one pillar only. And the pillar making multiple time damage to my player and my player get oneshot instead of only two damaga. If you need me to provide anything, just reply and I will give it ASAP.

    #16449
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Let’s start by fixing the NullReferenceException here:

    NullReferenceException

    The issue appears to be with line 29 of the Corrupted_Monk_Event script:

    public class Corrupted_Monk_Event : MonoBehaviour
    {
        void PunchDamagePlayer()
        {
            if (Move.Instance.transform.position.x > transform.position.x || Move.Instance.transform.position.x < transform.position.x)
            {
                Hit(CorruptedMonk.Instance.sideAttackTransform, CorruptedMonk.Instance.sideAttackArea);
            }
            else if (Move.Instance.transform.position.y > transform.position.y)
            {
                Hit(CorruptedMonk.Instance.upAttackTransform, CorruptedMonk.Instance.upAttackArea);
            }
            else if (Move.Instance.transform.position.y < transform.position.y)
            {
                Hit(CorruptedMonk.Instance.downAttackTransform, CorruptedMonk.Instance.downAttackArea);
            }
        }
        void Hit(Transform _attackTrasnform, Vector2 _attackArea)
        {
            Collider2D[] _objectToHit = Physics2D.OverlapBoxAll(_attackTrasnform.position, _attackArea, 0);
            for(int i = 0 ; i < _objectToHit.Length; i++)
            {
                if (_objectToHit[i].GetComponent<Collider2D>() != null)
                {
                    _objectToHit[i].GetComponent<Move>().takeDmg(CorruptedMonk.Instance.dmgMake);
                }
            }
        }
    }

    Do you have a Move component attached to your boss?

    #16464
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    So about the null references, I has already fix it but forgot to write the update on here. it was my mistake that calling this _objectToHit[i].GetComponent<Collider2D>() instead of _objectToHit[i].GetComponent<Move>() I has change and it look good. Now the problem is only the pillar doesn’t spawn right and the dmg it make. I will show you a record of it

    As you could see in the record. The pillar is spawn in a random patten and sometime move very far the player. But when it hit, it make about 10 time hits that you could see in the console in just a tic. Here is the script of the water pillar Diving pillar.cs

    public class DivingPillar : MonoBehaviour
    {
        // Start is called before the first frame update
        private void OnTriggerEnter2D(Collider2D collision)
        {
            if (collision.CompareTag("Player"))
            {
                Debug.Log("Player hit by pillar!");
                collision.GetComponent<Move>().takeDmg(CorruptedMonk.Instance.dmgMake);
                Debug.Log($"Player health after hit: {collision.GetComponent<Move>().health}");
            }
        }
    
    }

    boss_flyingkick.cs in the flyingkick animator

    public class Boss_FlyingKick : 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>();
        }
    
        // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            CorruptedMonk.Instance.divingCollider.SetActive(true);
    
            if (CorruptedMonk.Instance.isonGround())
            {
                CorruptedMonk.Instance.divingCollider.SetActive(false);
                if (!callOnce)
                {
                    CorruptedMonk.Instance.DivingPillar();
                    animator.SetBool("FlyingKick", false);
                    CorruptedMonk.Instance.ResetAllAttack();
                    callOnce = true;
                }
            }
        }
    
        // 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)
        {
            callOnce = false;
        }
    
    }

    Boss_jump.cs

    public class Boss_Jump : 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)
        {
            DiveAttack();
        }
    
        void DiveAttack()
        {
            if (CorruptedMonk.Instance.flyingKichAttack)
            {
                CorruptedMonk.Instance.Flip();
    
                Vector2 _newPos = Vector2.MoveTowards(rb.position, CorruptedMonk.Instance.moveToPosition, CorruptedMonk.Instance.speed * 2 * Time.fixedDeltaTime);
                rb.MovePosition(_newPos);
    
                if (CorruptedMonk.Instance.touchWall())
                {
                    CorruptedMonk.Instance.moveToPosition.x = rb.position.x;
                    _newPos = Vector2.MoveTowards(rb.position, CorruptedMonk.Instance.moveToPosition, CorruptedMonk.Instance.speed * 3 * Time.fixedDeltaTime);
                }
    
                float _distance = Vector2.Distance(rb.position, _newPos);
                if(_distance <0.1f)
                {
                    CorruptedMonk.Instance.Dive();
                }
            }
        }
        // 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)
        {
    
        }
    
    }

    and the flying kick in the boss script

    void FlyingKickAttackJump()
    {
        attacking = true ;
        moveToPosition = new Vector2(Move.Instance.transform.position.x, rb.velocity.y +2);
        flyingKichAttack = true ;
        anim.SetBool("Jump", true);
    }
    
    public void Dive()
    {
        anim.SetBool("FlyingKick",true);
        anim.SetBool("Jump", false);
    }
    
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.GetComponent<Move>() != null && flyingKichAttack)
        {
            collision.GetComponent<Move>().takeDmg(dmgMake * 2);
            Move.Instance.playerStateList.recoilingX = true;
    
            // Disable the attack to prevent further damage
            flyingKichAttack = false;
        }
    }
    
    public void DivingPillar()
    {
        if (pillar == null)
        {
            Debug.LogError("Pillar prefab is missing!");
            return;
        }
    
        Vector2 _impactPoint = groundcheck.position;
        float _spawnDistance = 3;
    
        for (int i = 0; i < 10; i++)
        {
            Vector2 _pillarSpawnPointRight = _impactPoint + new Vector2(_spawnDistance, 0);
            Vector2 _pillarSpawnPointLeft = _impactPoint - new Vector2(_spawnDistance, 0);
    
            Debug.Log($"Spawning right pillar at: {_pillarSpawnPointRight}");
            Instantiate(pillar, _pillarSpawnPointRight, Quaternion.Euler(0, 0, 0));
            Debug.Log($"Spawning left pillar at: {_pillarSpawnPointLeft}");
            Instantiate(pillar, _pillarSpawnPointLeft, Quaternion.Euler(0, 0, 0));
    
            _spawnDistance += 2;
        }
    
        ResetAllAttack();
    }
    #16465
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    It seems like all your diving pillars are spawning at the same place. Can you check your Hierarchy to confirm this? Then we will find out why it is.

    Add the following as well and show me what it prints on the console:

        for (int i = 0; i < 10; i++)
        {
            Vector2 _pillarSpawnPointRight = _impactPoint + new Vector2(_spawnDistance, 0);
            Vector2 _pillarSpawnPointLeft = _impactPoint - new Vector2(_spawnDistance, 0);
            print($"Diving Pillar {i} has a spawn distance of {_spawnDistance}");
            Debug.Log($"Spawning right pillar at: {_pillarSpawnPointRight}");
            Instantiate(pillar, _pillarSpawnPointRight, Quaternion.Euler(0, 0, 0));
            Debug.Log($"Spawning left pillar at: {_pillarSpawnPointLeft}");
            Instantiate(pillar, _pillarSpawnPointLeft, Quaternion.Euler(0, 0, 0));
    
            _spawnDistance += 2;
        }
    #16467
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    In the hierachy, yes the boss spawn so much water pillar. As you can see at the below picture

    Boss hierachy And in the console, this is what it show Console It up to 9 pillar and the spawn distance of 21
    #16469
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    I forgot to write this in previous reply but yes, what you thinkk is right, all the pillar is at the same place. There about more than 15 pillar and I check every single one and it appear in the same place. Stack together

    #16474
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Can you check all the Pillars in the Hierarchy and see if they are in the same coordinates? Because in our code we created them in different places, but they are still stacking in the same place.

    If we find out why, we will fix your issue.

    #16477
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    yes, in the inspector, it was the same value in the transform. All have the same value like this when the boss create the pillar

    boss pillar inspector
    #16500
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Does your console have the “Spawning left pillar at…” and “Spawning right pillar at…” messages?

    #16502
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    Yes, i have. I was thinking that the number it show up in the console is the x and y position of the pillar. But then when we figure out the pillar is spawn in the same place, the number in the console is different so i dont think it is the x and y position anymore. I will give you a picture later

    #16503
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    Here is the image in the console with the debug log Debug.Log($"Spawning right pillar at: {_pillarSpawnPointRight}"); and the left

    console and here is the inspector of the water pillar at the same time at the console log water pillar inspector
    #16537
    pepecry
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    What should I check next? Do you have any idea yet? I could let you access to my project to checking the problem if you want

    #16567
    A_DONUT
    Level 6
    Moderator
    Helpful?
    Up
    0
    ::

    do u need any more help?

Viewing 15 posts - 1 through 15 (of 27 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: