Forum begins after the advertisement:


[Part 10] Issues with Boss

Home › Forums › Video Game Tutorial Series › Creating a Metroidvania in Unity › [Part 10] Issues with Boss

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #20111
    Nirvik Rajbhandari
    Level 7
    Participant
    Helpful?
    Up
    0
    ::

    https://github.com/KingPloof393/Metroidvania-Prototype Link to Github Ive been working on part ten and have had issues with the boss shrinking when flipping, dealing only two damage with triple slash, and the slash effect being too small.

    #20114
    Chelsea
    Level 4
    Moderator
    Helpful?
    Up
    2
    ::

    Hi Nirvik, could you add me as a collaborator so I can take a look at the issue? My github username is mxisnd. Thanks!

    and 1 other person have upvoted this post.
    #20115
    Nirvik Rajbhandari
    Level 7
    Participant
    Helpful?
    Up
    2
    ::

    I added you. Thank you!

    and 1 other person have upvoted this post.
    #20116
    Chelsea
    Level 4
    Moderator
    Helpful?
    Up
    1
    ::

    The issue with your slash effect being too small was that the script instantiated the slash effect without adjusting the scale. I fixed this by changing Instantiate() in the SlashAngle method to SlashEffectAtAngle() as the method already instantiates the effect, and adjusts for rotation and scale.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Boss : Enemy
    {
        public static Boss Instance;
    
        [SerializeField] GameObject slashEffect;
        [SerializeField] public Transform SideAttackTransform; //the middle of the side attack area
        [SerializeField] public Vector2 SideAttackArea; //how large the area of side attack is
    
        [SerializeField] public Transform UpAttackTransform; //the middle of the up attack area
        [SerializeField] public Vector2 UpAttackArea; //how large the area of side attack is
    
        [SerializeField] public Transform DownAttackTransform; //the middle of the down attack area
        [SerializeField] public Vector2 DownAttackArea; //how large the area of down attack is
    
        public float attackRange;
        public float attackTimer;
    
        [HideInInspector] public bool facingRight = true;
    
        [Header("Ground Check Settings:")]
        [SerializeField] private Transform groundCheckPoint; //point at which ground check happens
        [SerializeField] private float groundCheckY = 0.2f; //how far down from ground chekc point is Grounded() checked
        [SerializeField] private float groundCheckX = 0.5f; //how far horizontally from ground chekc point to the edge of the player is
        [SerializeField] private LayerMask whatIsGround; //sets the ground layer
        bool isGrounded;
    
        int hitCounter;
        bool stunned;
        bool canStun;
        bool alive;
    
        [HideInInspector] public float runSpeed;
    
        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.Boss_Stage1);
            alive = true;
        }
    
        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;
            }
        }
    
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            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 (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.Boss_Stage1:
                        break;
                    case EnemyStates.Boss_Stage2:
                        break;
                    case EnemyStates.Boss_Stage3:
                        break;
                    case EnemyStates.Boss_Stage4:
                        break;
                }
            }
        }
    
        protected override void OnCollisionStay2D(Collision2D _other)
        {
    
        }
        #region attacking
        #region variables
        [HideInInspector] public bool attacking;
        [HideInInspector] public float attackCountdown;
    
        #endregion
    
        #region Control
    
        public void AttackHandler()
        {
            if(currentEnemyState == EnemyStates.Boss_Stage1)
            {
                if(Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <=  attackRange)
                {
                    StartCoroutine(TripleSlash());
                }
                else
                {
                    return;
                }
            }
        }
        public void ResetAllAttacks()
        {
            attacking = false;
    
            StopCoroutine(TripleSlash());
        }
    
        #endregion
    
        #region Stage 1
        IEnumerator TripleSlash()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
    
            anim.SetTrigger("Slash");
            SlashAngle();
            yield return new WaitForSeconds(0.3f);
            anim.ResetTrigger("Slash");
    
            anim.SetTrigger("Slash");
            SlashAngle();
            yield return new WaitForSeconds(0.5f);
            anim.ResetTrigger("Slash");
    
            anim.SetTrigger("Slash");
            SlashAngle();
            yield return new WaitForSeconds(0.2f);
            anim.ResetTrigger("Slash");
    
            ResetAllAttacks();
        }
    
        void SlashAngle()
        {
            if (PlayerController.Instance.transform.position.x > transform.position.x ||
                PlayerController.Instance.transform.position.x < transform.position.x)
            {
                Instantiate(slashEffect, SideAttackTransform);
                SlashEffectAtAngle(slashEffect, 0, 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(20f, 20f);
        }
        #endregion
        #endregion
    }

    As for the triple slash only dealing damage twice, I unchecked Has Exit Time for the transition from Any State to Boss_Slash in the Animator. This allows the slash animation to play as soon as the Slash trigger is activated, instead of waiting for the previous animation to reach its exit time.

    Another possible reason for the missing hit is the player’s invincibility frames. The player remains invincible for 1 second after taking damage, while the boss’s triple slash uses delays of 0.3, 0.5, and 0.2 seconds. This means some of the attacks may land while the player is still invincible. I’m not entirely sure if these changes fully address the issue you’re experiencing with the triple slash, so do let me know if it’s still happening.

    Regarding the boss shrinking when flipping, I’m not exactly sure what you meant, as I wasn’t able to reproduce the issue on my end. Could you elaborate a little more on it?

    has upvoted this post.
Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: