I’m trying to implement a simple “bump” reaction when the player character collides with an NPC — for example, the NPC plays a short knock-back animation or steps aside slightly.
I’ve run into two conflicting issues depending on how I set up collision:
Using OnComponentHit (or OnComponentBeginOverlap with Block collision):
The event fires many times per frame as long as the characters are in contact. This causes the reaction animation to restart constantly (“chattering” or “jittering”), making it impossible to play a smooth, one-time animation.
Using OnComponentBeginOverlap with Overlap collision:
The event fires only once (as desired), but the moment the player and NPC capsules intersect, the physics system instantly pushes the NPC away in a random direction — it “pops” or “flies off” as if resolving penetration. This happens even though neither mesh has Simulate Physics enabled, and both are Character-based with CapsuleComponent as root.
Additionally, when the player runs into the NPC, sometimes either the NPC or the player gets launched upward or sideways, which suggests the collision resolution is applying unintended impulses.
Question:
How can I get a one-time bump reaction on contact without event spam and without the NPC being physically pushed away by the engine’s collision resolution?
Any help or best practices would be greatly appreciated!
lets work on both starting with your “2” the reason one or both are flying off to Narnia is to do with the collision system that is related to the physics system, but it isn’t “impulse” that is being applied it is absolute velocity,
when the Collision system detects there is an overlap of 2 Colliders marked as Blocking, and they are not set to WorldStatic the system will “attempt” to find the vector in the direction “away from” each Blocking Collider, and absolutely away from any blocking collider set to World static.
it works out that given 3 bodies all set to “Block”: the Floor (WorldStatic), EntityA(Pawn) , EntityB(Pawn); if both EntityA and EntityB are overlapping and both are in “close proximity to the ground” then when the collision system will attempt to find a vector for Both EntityA and EntityB away from each other, and then also adding a negation of any vector that would cause an additional “next frame collision”, but because they are “close to the ground” to avoid a next frame collision with the ground it when add an amount away from the floor (most often in the +Z direction but this is only “bad” in specific situations). The problem is that the resulting angle is somewhere between 45 and 50 degrees from the ground, and therefore equal too or slightly greater then the velocity away from the collision. if EntityB is also WorldStatic then the velocity applied to EntityA is doubled.
in fact you might see slightly more “realistic” effect if you did enable physics, because then the “detect overlap of blocking colliders” would apply an impulse/force rather then a absolute velocity set.
but I am guessing there is a logic bug that is causing this result
the second reason they are flying off to Narnia has to do with the direction of travel, where you are taking the probably 2 overlap colliders in addition to the Blocking colliders (this situation should be impossible without both of them having a blocking collider), and then somehow getting the vector between them (LocationA - LocationB) which you then apply to both of them in some fashion “attempting” to push them appart.
if 2 colliders are just rubbing against each other the collision resolution system will only generate that they are “colliding” and apply a velocity that should amount to a little more then floating point error distance between them.
it is only when they are overlapping that the system starts to possibly take on an exponential response.
the biggest issue is that when a WorldStatic is involved the resulting Velocity Vector can appear almost random, but often “upward” (most often the correction gets a +Z component even if the collision is along the XY plane)
double check your math that you are applying for the “step back” I have a feeling that the Sign is reversed on one or both of them, and then on top of that the “step back” animation is not happening fast enough (the engine when detecting a intersection or interpenetrating collision only knows the current colliders involved, and the current velocities of anything not marked as “worldStatic”, so it doesn’t know that you intend to move them apart on the next frame by a little. the collision resolution system is trying to fix a potentially catastrophic situation NOW.
your number “1” where the Animation keeps starting and stopping if you are using Characters, and Animations. if the “A_stepBack” is in fact an AnimMontage then you can use the fact that both flavors to Play AnimMontage in Blueprints have a “finished”/”Completed”,
create and set a bool for “IsSteppingBack” you will still get the rubbing effect of collisions every frame,
then before you do anything out of the OnBlockingHit() check to see if it is currently SteppingBack.
if they are not currently steppingBack then check to see if they should be steppingBack
set the IsSteppingBack to true
when the animation finishes set the bool to false
there is a secondary situation where if they are already stepping back you take their current motion of travel (the negation of their forward Vector) and do a dotProduct with the NormalVector of the collision and if less then say .8 you intervene in the pawns overall rotation (especially if you are using RootMotion