Forum begins after the advertisement:


[part 10] outbreak attack not working as expected?

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [part 10] outbreak attack not working as expected?

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #15955
    Niyam Shah
    Participant
    Helpful?
    Up
    0
    ::

    so my boss will rise above and perform the outbreak animation, however:
    no fireballs will go flying – weird how they dont spawn despite them working with the barrage attack?
    theboss will stay floating in the air and wont leave the outbreak animation no matter what
    also the boss will be able to be spun in circles if touched by the player? – due to it not having frozen constraints

    LOTTA ISSUEs

    bend down script:::

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WoodenBotBendDown : 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>();
        }
    
        void OutbreakAttack()
        {
            if (WoodenBot.Instance.outbreakAttack)
            {
                Vector2 _newPos = Vector2.MoveTowards(rb.position, WoodenBot.Instance.moveToPosition, WoodenBot.Instance.speed * 1.5f * Time.fixedDeltaTime);
    
                rb.MovePosition(_newPos);
    
                float _distance = Vector2.Distance(rb.position, _newPos);
    
                if(_distance < 0.1f)
                {
                    WoodenBot.Instance.rb.constraints = RigidbodyConstraints2D.FreezePosition;
                }
    
            }
        }
    
        override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            OutbreakAttack();
        }
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            animator.ResetTrigger("BendDown");
        }
    
    }

    woodenbot events:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WoodenBotEvents : MonoBehaviour
    {
    
        void SlashDamagePlayer()
        {
            if (PlayerController.Instance.transform.position.x > transform.position.x ||
        PlayerController.Instance.transform.position.x < transform.position.x)
            {
                Hit(WoodenBot.Instance.SideAttackTransform, WoodenBot.Instance.SideAttackArea);
            }
            else if (PlayerController.Instance.transform.position.y > transform.position.y)
            {
                Hit(WoodenBot.Instance.UpAttackTransform, WoodenBot.Instance.UpAttackArea);
            }
            else if (PlayerController.Instance.transform.position.y < transform.position.y)
            {
                Hit(WoodenBot.Instance.DownAttackTransform, WoodenBot.Instance.DownAttackArea);
            }
        }
    
        void Hit(Transform _attackTransform, Vector2 _attackArea)
        {
            Collider2D[] _objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0);
            for(int i = 0; i < _objectsToHit.Length; i++)
            {
                if(_objectsToHit[i].GetComponent<PlayerController>() != null && !PlayerController.Instance.pState.invincible)
                {
                    _objectsToHit[i].GetComponent<PlayerController>().TakeDamage(WoodenBot.Instance.damage);
    
                }
            }
        }
    
        void Parrying()
        {
            WoodenBot.Instance.parrying = true;
        }
    
        void BendDownCheck()
        {
            if (WoodenBot.Instance.barrageAttack)
            {
                StartCoroutine(BarrageAttackTransition());
            }
            if (WoodenBot.Instance.outbreakAttack)
            {
                StartCoroutine(OutbreakAttackTransition());
            }
        }
    
        void BarrageOrOutbreak()
        {
            if (WoodenBot.Instance.barrageAttack)
            {
                WoodenBot.Instance.StartCoroutine(WoodenBot.Instance.Barrage());
            }
            if (WoodenBot.Instance.outbreakAttack)
            {
                WoodenBot.Instance.StartCoroutine(WoodenBot.Instance.OutBreak());
            }
        }
    
        IEnumerator BarrageAttackTransition()
        {
            yield return new WaitForSeconds(1f);
    
            WoodenBot.Instance.anim.SetBool("Barrage", true);
        }
    
        IEnumerator OutbreakAttackTransition()
        {
            yield return new WaitForSeconds(1f);
            WoodenBot.Instance.anim.SetBool("Outbreak", true);
        }
    
    }
    
    

    woodenBot scipt:

    using 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;
    
        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;
    
        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);
    
        }
    
        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 (!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.woodenBot_stage1:
                        break;
    
                    case EnemyStates.woodenBot_stage2:
                        break;
    
                    case EnemyStates.woodenBot_stage3:
                        break;
    
                    case EnemyStates.woodenBot_stage4:
                        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)
            {
                if (Vector2.Distance(PlayerController.Instance.transform.position, rb.position) <= attackRange)
                {
                    StartCoroutine(TripleSlash());
                }
                else
                {
                    //StartCoroutine(Lunge());
                    //DiveAttackJump();
                    //BarrageBendDown();
                    OutBreakBendDown();
                }
            }
        }
    
        public void ResetAllAttacks()
        {
            attacking = false;
            StopCoroutine(Lunge());
            StopCoroutine(Parry());
            StopCoroutine(TripleSlash());
            StopCoroutine(Slash());
    
            diveAttack = false;
            barrageAttack = false;
            outbreakAttack = 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; 1 < 10; i++)
            {
                Vector2 _pillarSpawnPointRight = _impactPoint + new Vector2(_spawnDistance, 0);
                Vector2 _pillarSpawnPointLeft = _impactPoint + new Vector2(_spawnDistance, 0);
    
                Instantiate(pillar, _pillarSpawnPointRight, Quaternion.Euler(0, 0, -90));
                Instantiate(pillar, _pillarSpawnPointLeft, Quaternion.Euler(0, 0, -90));
                Debug.Log("pillars spawned");
    
                _spawnDistance += 5;
            }
            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)
            {
                _other.GetComponent<PlayerController>().TakeDamage(damage * 2);
                PlayerController.Instance.pState.recoilingx = true;
            }
        }
    
        #endregion
    
        #region Stage 3
    
        void OutBreakBendDown()
        {
            attacking = true;
            rb.velocity = Vector2.zero;
            moveToPosition = new Vector2(DownAttackTransform.position.x, rb.position.y + 5);
            outbreakAttack = true;
            anim.SetTrigger("BendDown");
        }
    
        public IEnumerator OutBreak()
        {
            yield return new WaitForSeconds(1f);
    
            anim.SetBool("Outbreak", true);
    
            rb.velocity = Vector2.zero;
    
            for (int i = 0; i < 30; i++)
            {
                Instantiate(barrageFireball, transform.position, Quaternion.Euler(0, 0, Random.Range(110, 130))); // down
                Instantiate(barrageFireball, transform.position, Quaternion.Euler(0, 0, Random.Range(50, 70))); // diagonal right
                Instantiate(barrageFireball, transform.position, Quaternion.Euler(0, 0, Random.Range(260, 200))); // diagonal left
    
                yield return new WaitForSeconds(0.2f);
            }
    
            yield return new WaitForSeconds(0.1f);
    
            rb.constraints = RigidbodyConstraints2D.None;
            rb.constraints = RigidbodyConstraints2D.FreezeRotation;
            rb.velocity = new Vector2(rb.velocity.x, -10);
    
            yield return new WaitForSeconds(0.1f);
    
            anim.SetBool("Outbreak", false);
    
            ResetAllAttacks();
        }
    
        #endregion
    
        public override void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
        {
            if (!parrying)
            {
                base.EnemyHit(_damageDone, _hitDirection, _hitForce);
                
                if(currentEnemyState != EnemyStates.woodenBot_stage4)// parry isnt used in final form for a frantic ending
                {
                    ResetAllAttacks();
                    StartCoroutine(Parry());
    
                }
     
            }
            else
            {
                StopCoroutine(Parry());
                ResetAllAttacks();
                parrying = false;
                //parry attack
                StartCoroutine(Slash());
    
            }
    
        }
    }
    #15961
    Niyam Shah
    Participant
    Helpful?
    Up
    1
    ::

    dont worry about this – i fixed it

    i had the animator not selecting the correct function on the outbreak animation

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

Go to Login Page →


Advertisement below: