Make AI react to grenade

Hi,

throwing a grenade to an enemy AI (without being seen), how can I make the AI react to the grenade ? I want the AI first say something like “oh my God…” and then runs for cover.
I attached an AIPerceptionStimuliSource to the grenade and give it also a tag. But the AI only shows some reaction when he sees the player throwing it.

You can add collision sphere component with specific radius on AI. And just detect if overlapped actor is grenade from your collision sphere event.

I already tried something similar by attaching a sphere collision component to the grenade. This works partially and is not really accurate. If I make the radius too small, the AI doesn’t react to the grenade although it lands right before the AIs eyes. If I make the radius too big, then AIs would notice the grenade although they stand behind a wall and shouldn’t notice it.
When I kill an enemy, another enemy should react to the body accordingly. This does work for some reason.* But when I drop a grenade, the AI only reacts when it sees me throwing it.
I don’t know if it is a good idea according performance, but I converted the grenade actor to a pawn, but the result is the same. Can’t figure out, what the mistake is. Maybe I will also post this in the C++ forum, since I don’t really mind trying it out in C++ …I’m looking for an elegant and efficient way to do this, since this is something, that can happen all the time. (The player could throw grenades really often and the AI always should react to that logically.)

*PS: I made it work by setting the actor’s tag from “Enemy” to “Killed”. But I get warnings in the log, like “Trying to access index 1 of an array with length 1.” Which I don’t understand since I am setting the tags-array manually.

Make the radius on the AI not the grenade.
Also I would suggest a cylinder over a sphere. really a circle at the floor Z would be best, but because 3d space, a 1m tall cylinder attached to the bottom of the collision capsule would probably be best.
Then the AI needs to react to the grande.

What I would do is memorize all overlapped components via events.
OnBeginOveralp - add to array
OnEndOverlap - remove form array
When adding you do the check to see if one is indeed a grande (or anything else you need to check) and set a corresponding Boolean (“grande in range”). then the AI can see that variable and appropriately react however you script it. Including catch and throw back.

Because the overlaps are events they don’t run on tick. the reason I would keep an array of active elements is for convenience if the array of overlapped stuff doesn’t match the array of components you know that whatever overlapped is “new” and you can loop though again.
You definitely don’t have to and can just check if the components match what you need. Usually the overlap returns 1 to 2 components at most so the loop isn’t expensive.

Also, doing it this way it doesn’t matter what the Grenade is. actor, static mesh, pawn, vehicle.
You just check whatever you want to check - including a cast to fail/success right from the Overlapped Component node.

TL; DR

  1. Add a cylinder/something mesh to use as collision radius to AI char
  2. in BP Begin Play, bind event on ComponentBeginOverlap/EndOverlap, create and connect 2 custom events.
  3. Cast result to Grenade, if success set bool. - on overlapend unset bool.
  4. Set AI to react based on bool.
1 Like

I have bad experience regarding collision components that are attached to AICharacters. When I have lots of them, they start to overlap each others collision comps, which caused a heavy fps drop. Is there any other way ? For example embedding it into the percpetion system ?
The AI should logically also react when the grenade is on its way (still in the air) towards the AI (to trigger a dodging behavior). I guess with just a collision comp attached it just reacts when the grenade is right at the AI. Or do I miss something ?

Why do you have more then 1 collision component?
You can exclude the components from overlapping each other in their respective event checks. or by properly setting the collision settings.

Either way it’s an AI, it needs to react to stuff, so it needs to know what Stuff is where.

If you use Events instead of on tick you will have no drawbacks at all, not even with multiple collision components.

Just add a large sphere of a bout 5m radius at 0,0,0 on the character and use that for checking.

Then add a variable to the grande to know if it’s “moving” or “still”.
Once you detect the grande you can tell if it’s flying or on the floor in the same cast and set variables for the AI to react accordingly.

5m - half character height overhead might be too big - I prefer cylinder components because of that.

Remember that OnBeginOverlap activates Once, so you can’t re-check the status of the grande or anything else unless the overlap happens again.

Sorry, I meant “When I have lots of AIs” (probably should have explained better…
When for example 7 AIs start to dodge around and sweep the collision comp of the other AI then I get big fps drops.
I thought there might be are more deeper way to implement a solution. Maybe to alter the percpetion system somehow so that the AI can see the grenade inherently.
But I will try your suggestion out, thanks.

There should not be a problem even with lot’s of AI with collision components if it’s all set right. Maybe you have some “heavy” checks in overlap events.
Make sure that you set the right collision settings - what overlaps with what.
For instance, you can also set collision channel only for grenade / bullets (or similiar) in Project settings -> Collisions and add new collision channel (call it grenade or whatever) and set it to Overlap. So you can isolate this object type from World static, dynamic etc.
But I think you need first to properly set other collisions. Try to debug to see what’s going on…print out overlap output when you get fps drops.

Here’s what I would do:

  • Create a collision sphere on the grenade
  • You can use a **BeginOverlap **event or a **OverlappingActors **node (two separate ways to access those inside the sphere)
  • If AI is in sphere, run a line trace (by object) from grenade to all AIs in sphere
  • If it hits the AI, then access an **event **in the AI that gives the location of the grenade
  • With that location, tell the AI to move in the opposite direction, probably with an inverse vector length
  • Play anim

For the custom event, I’d recommend using an interface BP, so you don’t have to cast to each AI. It’s cleaner that way.

I’m willing to help with this, just pm me about it.

[USER=“947258”]Mr. Wood[/USER]
It’s probably the casting that made everything so heavy. I had already a collision sphere attached to the AI that had to trigger an event when the player was inside it. I will definitely check the collision settings, thanks for the advice!

@Kinos141
That is really cool. I will send you a pm or a visitor message like it says.

The solution may be simpler and more efficient (though it could be better):

  • Create New Object Channel for grenade/projectile from Project Settings -> Collision

  • Create collision sphere on your AI and set collision for Projectile/Grenade on Overlap (and everything else on ignore)

  • On your grenade actor set Object Type as Grenade or Projectile (what you previously set in Project Settings) so AI Sphere collision will detect only that actor on overlap event.

  • On Begin overlap event for sphere run **Linetrace **to grenade actor (if you want to AI reacts only if he can see grenade when it’s overlap). Also, you can set additional check if AI could not see grenade but it overlaps.


    This solution is quite simple and effective and it is the first thing that came to my mind. It can probably be done better, but definitely you should use sphere collision on your AI.

Correction:
Line trace should also check for grenade actor


Edit: or better to do line trace From grenade **To **AI Actor and check if hit actor is AI (self). Note: you need to disable **Ignore self **and **Visibility **to **Block **for AI mesh in that case.
It may be better because grenade is in the air (moving).

That is what I tried before :wink: , and since the grenade sends a message to all AI-Actors that got hit by the line trace, we wouldn’t even need any collision comps I think.
But I want the grenade to do multiple line traces from the moment it is tossed until the moment where it is about to explode. Can not find the correct position in the blueprint to put it. Even when I do the line trace on tick, it happens only one time, when I toss it.

To make a little grenade system I followed this tutorial:https://youtube.com/watch?v=LFAxAvBCYII
It’s really good and simple. But I have no clue where to manage the line tracing…

That’s why it may be better to use collision components instead line trace in tick. It will only checks on overlap instead of all time in every single tick.
In terms of performance, this is a more practical solution.
Do you really need to check 30 or more times per second (Delta time) for line trace? Or you need few checks per second?
And also what do you want to check when the grenade is tossed?

Alright… here is what I tried so far:
As @Kinos141 suggested, I attached a sphere to the grenade and make line traces on overlap.
When the sphere collides with the AI, they get a message.
I find it weird, that the trace starts at the grenades first position instead at its current position.
And how big should the radius of the sphere be ? I can’t figure out right now how to set the collision to avoid the trace go through the wall…(probably too easy…lol)
(The print message “BP_Grenade” is triggered in the enemy class.)

[USER=“947258”]Mr. Wood[/USER] I will also try your suggestion out. I wanted to try this one out first.