2
\$\begingroup\$

I'd like to do the following:

  • Characters (player, enemies) have a collider for collision with the world (= other characters/obstacles/etc)
  • Characters have another collider acting as a hurtbox (most likely larger than the collision)

Now what I tried is a layout is like roughly this:

Character root GameObject [layer is "default"]
  - Rigidbody2D (kinematic, full kinematic collision)
  - BoxCollider2D (rather small, just the feet of the sprite)
  - `MovementController` script with collision detection using `rigidbody.Cast` and MovementFilter set to layer "default"
  * `Hurtbox` child object [layer is "hurtbox"]
    - BoxCollider2D (covers most of the sprite (or more to make some enemies easy to hit))

LayerMatrix: Two user defined layers: Hitbox, Hurtbox. There's no interaction with the predefined layers and the only interactions among these is

Hitbox - Hurtbox [used for damage, etc: when a hitbox collides with a hurtbox, things happen]

Now the problem seems to be that all the Colliders in the child objects attach themselves to the ribidbody in the parent even though they're on different layers. And so the rigidbody.Cast uses the combined shape of both the "collision" box collider AND the "hurtbox" box collider.

How can I fix this?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Have you considered using footCollider.Cast() instead of rigidbody.Cast()? \$\endgroup\$
    – DMGregory
    Commented Sep 30, 2022 at 18:46
  • \$\begingroup\$ Lovely! This should solve it. I did not know that the colliders themselves also have the Cast method. (But out of curiosity: Is it possible to solve it at the level of the Rigidbody? The use case would be: The intended collision shape is a composite of several colliders, the intended hitbox is a composite of other colliders. Of course I could then do a foreach and cast all the hitbox colliders but it'd be great for my understanding if there's a top-level solution). \$\endgroup\$ Commented Sep 30, 2022 at 18:56
  • 1
    \$\begingroup\$ I'm not aware of a rigidbody-level solution offhand. I'd recommend posting an answer showing a solution with Collider2D.Cast for now, and see if any other suggestions arise. \$\endgroup\$
    – DMGregory
    Commented Sep 30, 2022 at 19:02

1 Answer 1

2
\$\begingroup\$

Here's the solution as proposed by @DMGregory.

The key is to use the collider itself for the .Cast instead of the rigidbody

Old code - irrelevant parts omitted

private Rigidbody2D rb;

void Start()
{
  rb = GetComponent<Rigidbody2D>();
}

private bool HasCollision(Vector2 direction)
{
  int count = rb.Cast(
    direction,
    movementFilter,
    collisions,
    collisionOffset
  );

  return count > 0;
}

New code - irrelevant parts omitted:

private Rigidbody2D rb;
private Collider2D collider;

void Start()
{
  rb = GetComponent<Rigidbody2D>();
  collider = GetComponent<Collider2D>();
}

private bool HasCollision(Vector2 direction)
{
  // Here's the key change!
  int count = collider.Cast(
    direction,
    movementFilter,
    collisions,
    collisionOffset
  );

  return count > 0;
}

This works, but it'd be still great to hear about a solution solely based on nested objects and layers. The use case would be to allow for composite colission shapes without resorting to something like a foreach where every step in the iteration does a .Cast.

\$\endgroup\$

You must log in to answer this question.

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