1
\$\begingroup\$

For a 3D top-down game, how should I handle collision in melee combat? My game has no targeting system, so I can't use a simple distance check between attacker and target.

What I am thinking is have the character swing, generate a hit box, run the damage script for any characters in that hit box, and then delete the hit box. How should I handle this?

Also, I would like to use the same attack script for all players and NPCs in melee, even with different attack animations and hit boxes. However, really I can't figure out how to reliably assign who the attacker and who the target are within that script, or how to handle multiple simultaneous attacks.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Is there any reason why you need to generate the hit box when attacking, instead of keeping some simple collider on the character all the time (and simply disabling if needed)? \$\endgroup\$ Commented Oct 10, 2014 at 16:00
  • \$\begingroup\$ I agree with unholy sheep except disabling the box will not call the ontriggerexit method, which you will probably want to call... The way I solved this was by changing the size of the box depending on if it was being used or not... Kind of a hack job but that's because unity has a few issues that need fixing \$\endgroup\$
    – Savlon
    Commented Oct 10, 2014 at 23:52

1 Answer 1

1
\$\begingroup\$

I think you and the commenters are on the right track. Ideally the hitboxes wouldn't have to be recreated on each attack (unless the nature of the attack were to change, maybe?). You could add something like this to every GameObject that can attack, along with a hitbox Collider marked as a Trigger.

public class HitController : MonoBehavior {

private Queue hitQueue;
private int health;
private int damage;
private bool attacking;

public void Start() {
    hitQueue = new Queue();
    health = 10;
    damage = 3;
    attacking = false;
}

public void Update() {
    // rudimentary attack input..
    if (Input.GetKeyDown(KeyCode.Space)) {
        // play an animation, etc...
        attacking = true;
    } else {
        attacking = false;
    }
    //  ...
    HandleHits();
    //  ...
}

private void HandleHits() {
    if (hitQueue.Count > 0) {
        Hashtable hitData = hitQueue.Dequeue();
        string name = hitData["name"];
        // do something with the attacker's name if you like
        int dmg = hitData["damage"];
        // could do further processing with attacker's damage..
        health -= dmg;
        if (health <= 0) {
            //however you wanna handle this
        }
    }
}

public void SignalHit(Hashtable hitData) {
    hitQueue.Enqueue(hitData);
}

public void OnTriggerEnter(Collider c) {
    // we only care about collisions if we're attacking
    if (attacking) {
        HitController hc = c.gameObject.GetComponent<HitController>();
        // this will hit other HitControllers, but not handle other collisions
        if (hc != null) {
            Hashtable h = new Hashtable();
            h.Add("name", this.name);
            h.Add("damage", this.damage);
            hc.SignalHit(h);
        }
    }
}
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .