Forum begins after the advertisement:


[Part 4] My down spell is not dealing damage

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 4] My down spell is not dealing damage

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #19059
    Nirvik Rajbhandari
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    All of my other spells are working as expected, but my down spell won’t deal damage. Here is my player controller script using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;

    public class Player_Controller : MonoBehaviour { [Header(“Horizontal Movement Settings”)]
    [SerializeField] private float WalkSpeed = 1; [Space(5)]

    [Header("Vertical Movement Settings")]
    [SerializeField] private float JumpForce = 45;
    private float Jump_Buffer_Counter;
    [SerializeField] private float Jump_Buffer_Frames = 0;
    private float Coyote_Time_Counter;
    [SerializeField] private float Coyote_Time;
    private int Air_Jump_Counter = 0;
    [SerializeField] private int Max_Air_Jumps;
    [Space(5)]
    
    [Header("Ground Check Settings")]
    [SerializeField] Transform GroundCheckPoint;
    [SerializeField] private float GroundCheckY = 0.2f;
    [SerializeField] private float GroundCheckX = 0.5f;
    [SerializeField] private LayerMask WhatIsGround;
    [Space(5)]
    
    [Header("Dash Settings")]
    [SerializeField] private float Dash_Speed;
    [SerializeField] private float Dash_Time;
    [SerializeField] private float Dash_Cooldown;
    private bool Can_Dash = true;
    private bool Dashed;
    [SerializeField] GameObject Dash_Effect;
    [Space(5)]
    
    [Header("Attack Settings")]
    [SerializeField] float Time_Between_Attack;
    float Attack_Time_Counter;
    [SerializeField] private Transform Side_Attack_Transform;
    [SerializeField] private Transform Up_Attack_Transform;
    [SerializeField] private Transform Down_Attack_Transform;
    [SerializeField] private Vector2 Side_Attack_Area;
    [SerializeField] private Vector2 Up_Attack_Area;
    [SerializeField] private Vector2 Down_Attack_Area;
    [SerializeField] private float Up_Attack_Parameter;
    [SerializeField] private float Down_Attack_Parameter;
    [SerializeField] private LayerMask Attackable_Layer;
    [SerializeField] private float Player_Damage;
    [SerializeField] GameObject Slash_Effect_Object;
    bool Attack_Bool = false;
    bool Restore_Time;
    float Restore_Time_Speed;
    [Space(5)]
    
    [Header("Recoil Settings")]
    [SerializeField] int Recoil_X_Steps = 5;
    [SerializeField] int Recoil_Y_Steps = 5;
    [SerializeField] int Recoil_X_Speed = 100;
    [SerializeField] int Recoil_Y_Speed = 100;
    int Steps_X_Recoiled;
    int Steps_Y_Recoiled;
    
    [Header("Health Settings")]
    public int Player_Health;
    public int Player_Max_Health;
    [SerializeField] GameObject Blood_Spurt;
    [SerializeField] float Hit_Flash_Speed;
    public delegate void On_Health_Changed_Delegate();
    [HideInInspector] public On_Health_Changed_Delegate On_Health_Changed_Callback;
    float Heal_Timer;
    [SerializeField] float Time_To_Heal;
    [Space(5)]
    
    [Header("Mana Settings")]
    [SerializeField] UnityEngine.UI.Image Mana_Storage;
    [SerializeField] float Mana;
    [SerializeField] float Mana_Drain_Speed;
    [SerializeField] float Mana_Gain;
    [Space(5)]
    
    [Header("Spell Casting")]
    [SerializeField] float Mana_Spell_Cost = 0.3f;
    [SerializeField] float Time_Between_Cast = 0.5f;
    [SerializeField] float Spell_Damage;
    [SerializeField] float Down_Spell_Force;
    [SerializeField] GameObject Side_Spell;
    [SerializeField] GameObject Up_Spell;
    [SerializeField] GameObject Down_Spell;
    float Cast_Time_Counter;
    float Cast_Or_Heal_Timer;
    
    [Space(5)]
    
    private Vector3 Mouse_Position;
    [HideInInspector] public Player_State_List Player_State;
    private Rigidbody2D Rigidbody;
    private SpriteRenderer Sprite_Renderer;
    private float Gravity;
    private float XAxis;
    Animator Animator;
    
    public static Player_Controller Instance;
    
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            Instance = this;
        }
        Player_Health = Player_Max_Health; 
    }
    
    // Start is called before the first frame update
    void Start()
    {
        Player_State = GetComponent<Player_State_List>();
        Rigidbody = GetComponent<Rigidbody2D>();
        Sprite_Renderer = GetComponent<SpriteRenderer>();
        Animator = GetComponent<Animator>();
        Gravity = Rigidbody.gravityScale;
        Player_Mana = Mana;
        Mana_Storage.fillAmount = Mana;
    }
    
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireCube(Side_Attack_Transform.position, Side_Attack_Area);
        Gizmos.DrawWireCube(Up_Attack_Transform.position, Up_Attack_Area);
        Gizmos.DrawWireCube(Down_Attack_Transform.position, Down_Attack_Area);
    }
    
    // Update is called once per frame
    void Update()
    {
        GetInputs();
        UpdateJumpVariables();
        if (Player_State.Dashing)
        {
            return;
        }
        Restore_Time_Scale();
        Flash_While_Invincible();
        Move();
        Heal();
        Cast_Spell();
        if (Player_State.Healing)
        {
            return;
        }
        Flip();
        Jump();
        Attack();
        Start_Dash();
    }
    
    private void OnTriggerEnter2D(Collider2D Other)
    {
        if(Other.GetComponent<Enemy>() != null && Player_State.Casting)
        {
            Other.GetComponent<Enemy>().Enemy_Hit(Spell_Damage, (Other.transform.position - transform.position).normalized, -Recoil_Y_Speed);
        }
    }
    
    private void FixedUpdate()
    {
        if (Player_State.Dashing)
        {
            return;
        }
        Recoil();
    }
    
    void GetInputs()
    {
        XAxis = Input.GetAxisRaw("Horizontal");
        Attack_Bool = Input.GetButtonDown("Attack");
        Mouse_Position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Mouse_Position.x -= gameObject.transform.position.x;
        Mouse_Position.y -= gameObject.transform.position.y;
        Mouse_Position.z = 0f;
        if (Input.GetButton("Cast/Heal"))
        {
            Cast_Or_Heal_Timer += Time.deltaTime;
        }
        else
        {
            Cast_Or_Heal_Timer = 0;
        }
    }
    
    void Flip()
    {
        if(Attack_Time_Counter < 0.5f)
        {
            return;
        }
        if(XAxis < 0)
        {
            transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), transform.localScale.y);
            Player_State.Looking_Right = false;
        }
        else if(XAxis > 0)
        {
            transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y);
            Player_State.Looking_Right = true;
        }
    }
    
    private void Move()
    {
        if(Player_State.Healing)
        {
            Rigidbody.velocity = new Vector2(0,0);
        }
        Rigidbody.velocity = new Vector2(WalkSpeed * XAxis, Rigidbody.velocity.y);
        Animator.SetBool("Walking", Rigidbody.velocity.x != 0 && Grounded());
    }
    
    void Start_Dash()
    {
        if(Input.GetButtonDown("Dash") && Can_Dash && !Dashed)
        {
            StartCoroutine(Dash());
            Dashed = true;
        }
        if(Grounded())
        {
            Dashed = false;
        }
    }
    
    IEnumerator Dash()
    {
        Player_State.Dashing = true;
        Player_State.Invincible = true;
        Can_Dash = false;
        Animator.SetTrigger("Dashing");
        Rigidbody.gravityScale = 0;
        Rigidbody.velocity = new Vector2(-transform.localScale.x * Dash_Speed, 0);
        if(Grounded())
        {
            Instantiate(Dash_Effect, transform);
        }
        yield return new WaitForSeconds(Dash_Time);
        Rigidbody.gravityScale = Gravity;
        Player_State.Dashing = false;
        Player_State.Invincible = false;
        yield return new WaitForSeconds(Dash_Cooldown);
        Can_Dash = true;
    }
    
    void Attack()
    {
        Attack_Time_Counter += Time.deltaTime;
        if(Attack_Bool && Attack_Time_Counter >= Time_Between_Attack)
        {
            Attack_Time_Counter = 0;
            Animator.SetTrigger("Attacking");
            if(Mouse_Position.y < Up_Attack_Parameter && Mouse_Position.y > Down_Attack_Parameter || Mouse_Position.y <= Down_Attack_Parameter && Grounded())
            {
                Hit(Side_Attack_Transform, Side_Attack_Area, ref Player_State.Recoiling_X, Recoil_X_Speed);
                Slash_Effect_Angle(Slash_Effect_Object, 0, Side_Attack_Transform);
            }
    
            else if(Mouse_Position.y > Up_Attack_Parameter)
            {
                Hit(Up_Attack_Transform, Up_Attack_Area, ref Player_State.Recoiling_Y, Recoil_Y_Speed);
                Slash_Effect_Angle(Slash_Effect_Object, 80, Up_Attack_Transform);
            }
            else if(Mouse_Position.y < Down_Attack_Parameter && !Grounded())
            {
                Hit(Down_Attack_Transform, Down_Attack_Area, ref Player_State.Recoiling_Y, Recoil_Y_Speed);
                Slash_Effect_Angle(Slash_Effect_Object, -90, Down_Attack_Transform);
            }
        }
    }
    
    void Hit(Transform Attack_Transform, Vector2 Attack_Area, ref bool Recoil_Directory, float Recoil_Strength)
    {
        Collider2D[] Objects_To_Hit = Physics2D.OverlapBoxAll(Attack_Transform.position, Attack_Area, 0, Attackable_Layer);
        List<Enemy> Hit_Enemies = new List<Enemy>();
    
        if(Objects_To_Hit.Length > 0)
        {
            Recoil_Directory = true;
        }
        for(int i = 0; i < Objects_To_Hit.Length; i++)
        {
            Enemy e = Objects_To_Hit[i].GetComponent<Enemy>();
            if(e && !Hit_Enemies.Contains(e))
            {
                e.Enemy_Hit(Player_Damage, (transform.position - Objects_To_Hit[i].transform.position).normalized, Recoil_Strength);
                Hit_Enemies.Add(e);
    
                if(Objects_To_Hit[i].CompareTag("Enemy"))
                {
                    Player_Mana += Mana_Gain;
                }
            }
        }
    }
    
    void Slash_Effect_Angle(GameObject Slash_Effect, int Effect_Angle, Transform Attack_Transform)
    {
        Slash_Effect = Instantiate(Slash_Effect, Attack_Transform);
        Slash_Effect.transform.eulerAngles = new Vector3(0, 0, Effect_Angle);
        Slash_Effect.transform.localScale = new Vector2(transform.localScale.x, transform.localScale.y);
    }
    
    void Recoil()
    {
        if(Player_State.Recoiling_X)
        {
            if(Player_State.Looking_Right)
            {
                Rigidbody.velocity = new Vector2(-Recoil_X_Speed, 0);
            }
            else if(!Player_State.Looking_Right)
                Rigidbody.velocity = new Vector2(Recoil_X_Speed, 0);
        }
        if(Player_State.Recoiling_Y)
        {
            if(Mouse_Position.y < Down_Attack_Parameter)
            {
                Rigidbody.gravityScale = 0;
                Rigidbody.velocity = new Vector2(Rigidbody.velocity.x, Recoil_Y_Speed);
            }
            else if(Mouse_Position.y > Up_Attack_Parameter)
            {
                Rigidbody.gravityScale = 0;
                Rigidbody.velocity = new Vector2(Rigidbody.velocity.x, -Recoil_Y_Speed);
            }
            Air_Jump_Counter = 0;
        }
        else
        {
            Rigidbody.gravityScale = Gravity;
        }
    
        if(Player_State.Recoiling_X && Steps_X_Recoiled < Recoil_X_Steps)
        {
            Steps_X_Recoiled++;
        }
        else
        {
            Stop_Recoil_X();
        }
        if(Player_State.Recoiling_Y && Steps_Y_Recoiled < Recoil_Y_Steps)
        {
            Steps_Y_Recoiled++;
        }
        else
        {
            Stop_Recoil_Y();
        }
    
        if(Grounded())
        {
            Stop_Recoil_Y();
        }
    }
    
    void Stop_Recoil_X()
    {
        Steps_X_Recoiled = 0;
        Player_State.Recoiling_X = false;
    }
    
    void Stop_Recoil_Y()
    {
        Steps_Y_Recoiled = 0;
        Player_State.Recoiling_Y = false;
    }
    
    public void Take_Damage(float Damage_Taken)
    {
        Player_Health_Int -= Mathf.RoundToInt(Damage_Taken);
        StartCoroutine(Stop_Taking_Damage());
    }
    
    public IEnumerator Stop_Taking_Damage()
    {
        Player_State.Invincible = true;
        GameObject Blood_Spurt_Particles = Instantiate(Blood_Spurt, transform.position, Quaternion.identity);
        Destroy(Blood_Spurt_Particles, 1.5f);
        Animator.SetTrigger("Take Damage");
        yield return new WaitForSeconds(1f);
        Player_State.Invincible = false;
    }
    
    void Flash_While_Invincible()
    {
        Sprite_Renderer.color = Player_State.Invincible ?
            Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time * Hit_Flash_Speed, 1.0f)) : Color.white;
    }
    
    void Restore_Time_Scale()
    {
        if(Restore_Time)
        {
            if (Time.timeScale < 1)
            {
                Time.timeScale += Time.deltaTime * Restore_Time_Speed;
            }
            else
            {
                Time.timeScale = 1;
                Restore_Time = false;
            }
        }
    }
    
    public void Hit_Stop_Time(float New_Time_Scale, int Restore_Speed, float Delay)
    {
        Restore_Time_Speed = Restore_Speed;
        Time.timeScale = New_Time_Scale;
        if (Delay > 0)
        {
            StopCoroutine(Start_Time_Again(Delay));
            StartCoroutine(Start_Time_Again(Delay));
        }
    }
    
    IEnumerator Start_Time_Again(float Delay)
    {
        Restore_Time = true;
        yield return new WaitForSeconds(Delay);
    }
    
    public int Player_Health_Int
    {
        get { return Player_Health; }
        set
        {
            if (Player_Health != value)
            {
                Player_Health = Mathf.Clamp(value, 0, Player_Max_Health);
    
                if (On_Health_Changed_Callback != null)
                {
                    On_Health_Changed_Callback.Invoke();
                }
            }
        }
    }
    
    private void Heal()
    {
        if (Input.GetButton("Cast/Heal") && Cast_Or_Heal_Timer > 0.05f && Player_Health_Int < Player_Max_Health && Player_Mana > 0 && Grounded() && !Player_State.Dashing)
        {
            Player_State.Healing = true;
            Heal_Timer += Time.deltaTime;
            Animator.SetBool("Healing", true);
            Player_Mana -= Time.deltaTime * Mana_Drain_Speed;
            if (Heal_Timer >= Time_To_Heal)
            {
                Player_Health_Int++;
                Heal_Timer = 0;
            }
        }
        else
        {
            Player_State.Healing = false;
            Heal_Timer = 0;
            Animator.SetBool("Healing", false);
        }
    }
    
    private float Player_Mana
    {
        get { return Mana; }
        set
        {
            if (Mana != value)
            {
                Mana = Mathf.Clamp(value, 0, 1);
                Mana_Storage.fillAmount = Mana;
            }
        }
    }
    
    void Cast_Spell()
    {
        if (Input.GetButtonUp("Cast/Heal") && Cast_Or_Heal_Timer <= 0.05f && Cast_Time_Counter >= Time_Between_Cast && Mana >= Mana_Spell_Cost)
        {
            Player_State.Casting = true;
            Cast_Time_Counter = 0;
            StartCoroutine(Cast_Coroutine());
        }
        else
        {
            Cast_Time_Counter += Time.deltaTime;
        }
        if (Grounded())
        {
            Down_Spell.SetActive(false);
        }
        if(Down_Spell.activeInHierarchy)
        {
            Rigidbody.velocity = Down_Spell_Force * Vector2.down;
        }
    }
    
    IEnumerator Cast_Coroutine()
    {
        Animator.SetBool("Casting", true);
        Rigidbody.gravityScale = 0;
        yield return new WaitForSeconds(0.12f);
        Rigidbody.gravityScale = Gravity;
        if (Mouse_Position.y < Up_Attack_Parameter && Mouse_Position.y > Down_Attack_Parameter || Mouse_Position.y <= Down_Attack_Parameter && Grounded())
        {
            GameObject Fire_Ball = Instantiate(Side_Spell, Side_Attack_Transform.position, Quaternion.identity);
            if (Player_State.Looking_Right)
            {
                Fire_Ball.transform.eulerAngles = Vector3.zero;
            }
            else
            {
                Fire_Ball.transform.eulerAngles = new Vector3(Fire_Ball.transform.eulerAngles.x, 180);
            }
            Player_State.Recoiling_X = true;
        }
        else if (Mouse_Position.y > Up_Attack_Parameter)
        {
            Instantiate(Up_Spell, transform);
            Rigidbody.velocity = Vector2.zero;
        }
        else if (Mouse_Position.y < Down_Attack_Parameter && !Grounded())
        {
            Down_Spell.SetActive(true);
        }
        Player_Mana -= Mana_Spell_Cost;
        yield return new WaitForSeconds(0.11f);
        Animator.SetBool("Casting", false);
        Player_State.Casting = false;
    }
    
    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;
        }
    }
    
    void Jump()
    {   
        if (Jump_Buffer_Counter > 0 && Coyote_Time_Counter > 0 && !Player_State.Jumping)
            {
                Rigidbody.velocity = new Vector3(Rigidbody.velocity.x, JumpForce);
                Player_State.Jumping = true;
            }
        else if (!Grounded() && Air_Jump_Counter < Max_Air_Jumps && Input.GetButtonDown("Jump"))
        {
            Player_State.Jumping = true;
            Air_Jump_Counter++;
            Rigidbody.velocity = new Vector3(Rigidbody.velocity.x, JumpForce);
        }
        if (Input.GetButtonUp("Jump") && Rigidbody.velocity.y > 3)
        {
            Rigidbody.velocity = new Vector2(Rigidbody.velocity.x, 0);
            Player_State.Jumping = false;
        }
    
        Animator.SetBool("Jumping", Rigidbody.velocity.y > 0 && !Grounded());
        Animator.SetBool("Falling", Rigidbody.velocity.y < 0 && !Grounded());
    }
    
    void UpdateJumpVariables()
    {
        if(Grounded())
        {
            Player_State.Jumping = false;
            Coyote_Time_Counter = Coyote_Time;
            Air_Jump_Counter = 0;
        }
        else
        {
            Coyote_Time_Counter -= Time.deltaTime;
        }
    
        if(Input.GetButtonDown("Jump"))
        {
            Jump_Buffer_Counter = Jump_Buffer_Frames;
        }
        else
        {
            Jump_Buffer_Counter -= Time.deltaTime * 10;
        }
    }

    }

Viewing 1 post (of 1 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: