Forum begins after the advertisement:


[Part 3.5] After jumping and falling, damage is not counted.

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 3.5] After jumping and falling, damage is not counted.

  • This topic has 28 replies, 4 voices, and was last updated 1 week ago by Da.
Viewing 6 posts - 31 through 36 (of 36 total)
  • Author
    Posts
  • #17227
    Lukas Kazda
    Level 14
    Gold Supporter (Patron)
    Helpful?
    Up
    0
    ::

    i guess you could also attach and configure a boxcollider2d in the coroutine (for the duration of however many frames you want), instead of creating a overlapbox every frame. and then at the end of the coroutine you destroy(or remove from player gameobject(?)) the boxcollider2d. this would eliminate the problem of having multiple collisions on the same enemy with a single attack, however if an enemy is exactly on the edge of the spawned boxcollider2d and moves in and out it might trigger twice. to fix that, you could do a list that collects collisions, and on adding a new collision you check if the list already has an object with the same enemy gameobject as its triggersource, if it doesnt, add to list and call the deal damage function. i am a bit to lazy to figure out a code for this right now, its 3 am for me xD sorry

    #17228
    Ser Apustaja
    Level 3
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    No problem, Lukas! It sounds like you’re trying to manage enemy collisions in a Unity game, and you’re considering using a BoxCollider2D to simplify your collision detection for a temporary attack. Here’s how you can implement the idea you have in mind.

    Step 1: Create a Coroutine to Manage the BoxCollider2D

    You can create a coroutine that will enable a BoxCollider2D, check for collisions, and then disable or destroy it after a certain duration.

    Step 2: Use a List to Track Collisions

    You can maintain a list of enemies that have already been hit to prevent applying damage multiple times.

    Sample Code

    Here’s an example of how you might implement this:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PlayerAttack : MonoBehaviour
    {
        public BoxCollider2D attackCollider; // Assign this in the Inspector
        public float attackDuration = 0.5f; // Duration the collider is active
        private List hitEnemies = new List();
    
        private void Start()
        {
            // Make sure the collider is disabled at the start
            attackCollider.enabled = false;
        }
    
        public void PerformAttack()
        {
            StartCoroutine(AttackCoroutine());
        }
    
        private IEnumerator AttackCoroutine()
        {
            // Enable the collider
            attackCollider.enabled = true;
    
            // Wait for the specified duration
            yield return new WaitForSeconds(attackDuration);
    
            // Disable the collider
            attackCollider.enabled = false;
    
            // Clear the list for future attacks
            hitEnemies.Clear();
        }
    
        private void OnTriggerEnter2D(Collider2D collision)
        {
            // Check if the collided object is an enemy
            if (collision.CompareTag("Enemy"))
            {
                // Check if we have already hit this enemy
                if (!hitEnemies.Contains(collision.gameObject))
                {
                    // Add the enemy to the list and deal damage
                    hitEnemies.Add(collision.gameObject);
                    DealDamage(collision.gameObject);
                }
            }
        }
    
        private void DealDamage(GameObject enemy)
        {
            // Implement your damage logic here
            Debug.Log($"Dealt damage to {enemy.name}");
        }
    }

    Explanation:

    1. BoxCollider2D: The collider is assigned in the Inspector and is disabled by default.
    2. PerformAttack: This method starts the coroutine to handle the attack.
    3. AttackCoroutine: This coroutine enables the collider, waits for the specified duration, and then disables it.
    4. OnTriggerEnter2D: This method checks for collisions with enemies. If an enemy collides and is not already in the hitEnemies list, it adds the enemy and calls the DealDamage method.
    5. DealDamage: This method contains the logic to apply damage to the enemy.

    Notes:

    • Make sure that your enemy GameObjects have the tag “Enemy” set in the Inspector.
    • Adjust the attackDuration as needed to fit your game.
    • You may want to implement additional logic to handle what happens when an enemy takes damage or is defeated.

    Feel free to modify this code to suit your specific gameplay mechanics! If you have any further questions or need clarification, just let me know.

    #17237
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::
    Not quite. Let’s call the attack method itself “Attack” and the attack animation “Attack_1”. In Attack, when the button is pressed and the attack silence time has passed (you can attack), a hit is registered. But the problem is that registration only happens at this moment. I want the registration to continue for some time after pressing the button (without having to press the button again), regardless of Attack_1 (I’m happy with the animation playback, it doesn’t matter here in principle, as I think it doesn’t matter. You can set it up later). For example, take circular attacks or sustained attacks (for example, in dark souls). They use the same logic, that is, after pressing the key, hits are registered for a while. About the array of colliders. This is a separate issue (or maybe a common one with the previous one). Let’s say we’ve made the “Hit” method work for a while after pressing a key. Now we need to record all the colliders that fall under our area of attack. This does not pose any problems if the method itself is instantaneous (only at the moment when the attack is pressed). When it should last for a certain amount of time, the question arises how to remember all the colliders that were hit at these points in time. This point is still unclear to me, although the previous post suggested to me that we should introduce a common array of colliders and write there from a buffer (another array of colliders), everything that got into it at some point in time. After that, there is also a problem of how to eliminate repetitions so that there is no double damage (that is, to exclude repeated hits of identical colliders).

    If I understand you correctly, you want your attacks to be active for multiple frames right? Something like this:

    Attack frames

    Where you want the attack to be active for multiple frames?

    The code I shared above works like that, but it is missing an array that records all hit enemies (so that enemies who are hit don’t get hit again) for each attack.

    I will be doing a stream tomorrow. I can address this on the stream.

    #17244
    Da
    Level 3
    Participant
    Helpful?
    Up
    1
    ::

    Yes, that’s it. I saw this message late, but I’ve already figured it out (not without the help of your posts). I used a list, entered all the colliders that were hit within 0.2 seconds (I used enumeration, a cycle of five times 0.04 seconds) and, so that there would be no repeated damage, I gave invulnerability to the hit enemy (for a few seconds).

    has upvoted this post.
    #17248
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::
    Yes, that’s it. I saw this message late, but I’ve already figured it out (not without the help of your posts). I used a list, entered all the colliders that were hit within 0.2 seconds (I used enumeration, a cycle of five times 0.04 seconds) and, so that there would be no repeated damage, I gave invulnerability to the hit enemy (for a few seconds).

    That’s great to hear.

    If you don’t mind, I’ll really appreciate it if you can share your code here.

    #17253
    Da
    Level 3
    Participant
    Helpful?
    Up
    1
    ::

    Code using attack frames and invulnerability. Character:

    private IEnumerator Attack()
    {
        TimeSinceAttack += Time.deltaTime;
        if (Input.GetButtonDown("Attack") && TimeSinceAttack >= TimeBeetwenAttack)
        {
            //attack = true;
            TimeSinceAttack = 0f;
            anim.SetTrigger("Attacking");
            for (int i = 0; i < 5; i++)
            {
                Hit(SideAttackTransform, SideAttackArea);
                yield return new WaitForSeconds(0.08f);
            }    
            /*yield return new WaitForSeconds(0.15f);
            Hit(SideAttackTransform, SideAttackArea);
            //attack = false;
            */
        }
    }
    private void Hit(Transform _attackTransform, Vector2 _attackArea)
    {
        Collider2D[] objectsToHit;
        objectsToHit = Physics2D.OverlapBoxAll(_attackTransform.position, _attackArea, 0, attackableLayer);
    
        //Debug.Log($"Attack Position: {_attackTransform.position}, Area: {_attackArea}");
    
        for (int i = 0; i < objectsToHit.Length; i++)
        {
            if (objectsToHit[i].GetComponent<Enemy_1>() != null && !Enemy_1.xz.invincible)
            {
                objectsToHit[i].GetComponent<Enemy>().EnemyHit(damage, (transform.position - objectsToHit[i].transform.position).normalized, 100);
                objectsToHit[i].GetComponent<Enemy_1>().Invincible_1();
            }
        }
    
        if (objectsToHit.Length > 0)
        {
            Debug.Log("Hit!");
        }
        else if (objectsToHit.Length <= 0)
        {
            Debug.Log("No Hit!");
        }
    }

    Enemy:

    [SerializeField] public bool invincible = false;public IEnumerator Invincible()
    {
        invincible = true;
        yield return new WaitForSeconds(0.4f);
        invincible = false;
    }
    public void Invincible_1()
    {
        StartCoroutine(Invincible());
    }
    has upvoted this post.
Viewing 6 posts - 31 through 36 (of 36 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: