Is there a way to disable collision but not overlaps on a per-actor or per-component basis?

We would like to have a team blocker that blocks players from the enemy team from passing through it but generates overlap events for players of the same team. Currently, we’re adding the blockers to the MoveIgnoreActors for teammates and adding a separate actor for overlap checks, but we would like to have this all in one actor.

Hi Nathan.

There’s an existing answer on the public Answerhub that goes into this: How to block one pawn but ignore another? - World Creation - Epic Developer Community Forums

Please let us know if that helps, or if you need more information.

Cheers

I was hoping for a way to do this without channels. If we have team-specific channels for pawns, that becomes a HUGE undertaking to ensure that all pawn collision accounts for pawn collision on each team. Also, I don’t want to blow the channel limit (18, I think?) by adding a bunch of team-specific stuff.

Is there no way to ignore collision on a per-component level rather than a per-actor level, so we could have 1 actor with 2 components (one for blocking, one for overlaps) and just ignore the blocking component on the same team?

Nathan,

There is a MaskFilter you could use to achieve this type of goal. It’s not a well documented (or at least, not a well known) feature, I’ll admit.

Here’s a snippet of code that defines the FMaskFilter type:

/** This filter allows us to refine queries (channel, object) with an additional level of ignore by tagging entire classes of objects (e.g. "Red team", "Blue team")
    If(QueryIgnoreMask & ShapeFilter != 0) filter out */
typedef uint8 FMaskFilter;

The methods to set / get the filter are:

	/** Set the mask filter checked when others move into us. */
	void SetMaskFilterOnBodyInstance(FMaskFilter InMaskFilter) { BodyInstance.SetMaskFilter(InMaskFilter); }

	/** Get the mask filter checked when others move into us. */
	FMaskFilter GetMaskFilterOnBodyInstance(FMaskFilter InMaskFilter) const { return BodyInstance.GetMaskFilter(); }

Both of those are exposed on PrimitiveComponents.

There are a few caveats with this. First, while it’s a uint8 you can really only use 3 bits IIRC. This is a limitation imposed by PhysX, unfortunately, so there isn’t much we can do.

Further, the way the bits are check (as you can see above) is true bit field masking and not just an ID system. This means you can have at most 3 unique filters (1, 2 and 4). Any other value will cause positive masking (i.e. 3 will return true for 1 and 2, and 7 will return true for all cases).

Thanks,
Jon N.

I know this topic is now 2 years old but MaskFilter still doesn’t work as I would expect (in 4.19). Now there are 6 bits available (although I think it could be extended it seems some of the filter bits are not really used). In case somebody is trying to make it work, this is what works for me:

  1. SetMaskFilter() doesn’t work on components welded to another body on its own; calling BodyInstance.UpdatePhysicsFilterData() helps.

  2. There is a bug in FBodyInstance::UpdatePhysicsShapeFilterData(). When calling CreateShapeFilterData() instead of MaskFilter it should use BI->MaskFilter. This issue will come up only when components in the same actor have different MaskFilter set up.

  3. PhysXSimFilterShader() seems to totally ignore MaskFilter, so you’ll have to add a check for that there. Something like

    FMaskFilter Filter0 = 0;
    GetCollisionChannelAndExtraFilter(filterData0.word3, Filter0);
    FMaskFilter Filter1 = 0;
    GetCollisionChannelAndExtraFilter(filterData1.word3, Filter1);
    if ((Filter0 & Filter1) != 0)
    {
    	return PxFilterFlag::eSUPPRESS;
    }
1 Like