How to inquiry the nearest actor?

Hello!
I’ve been trying to accomplish a series of things that seem deceptively simple.

  1. Find the nearest actor with the tag “Interactable.”
  2. Select that actor.
  3. Check if the distance to said actor is small than the variable “MaxInteractRange” stored within the actor.
  4. If so, run whatever function is in there.

Can anyone help?

5 Likes

I don’t know how often you wish to do this “query” to find the nearest actor, nor how many actors you will have with this particular tag. But you might want to consider either

  1. When ever the actors are created/spawned, that they register with a blueprint, giving their location, and when they move, updating that location. Then the Blueprint that knows where everything is, can break the game playing area up into quadrants, knowing all actors in a particular quadrant, and then can answer queries from the other actors that need to know. I would set the quadrant size to be the MaxInteractRange, that you mentioned. Granted, the actors that would be querying, will hardly ever be centered in the quadrant they are asking from, so more than one quadrant will need to be inspected.

  2. Create a static mesh component that remains invisible, that you have centered on the actor that is going to query. Then invoke the function of get all overlapping actors. Again you can set the size of the static mesh component to be the MaxInteractRange. This method allows you either see the actors behind you or not, and how much to the sides of the actor that is going to query, because the shape of the static mesh, is going to determine what actors are returned from the query.

Hope this helps,

theres probably a better way to go about it depending on your circumstance, such as overlap events or line traces which would be easy to implement and possibly more optimal.

but to give a brief overview of what you asked for. you would first need a get all actors with tag node, this should return an array which contains all actors that have the tag your looking for. you then need to parse this array to find out which actor is closest. to do this you need to use a foreachloop which gets the distance to (get distance to node) the player from the actor, then compares that distance to the distance of the other actors. the way i implement this is to have a variable which contains the closest actor then compare each other actors distance to the current closest, if the new actor is closer then you set it as the current closest and move on. once you find the closest you can then move on to the rest of what your looking to do by comparing the “distance to” to the max interact range. then you can do the last part though im not entire sure what you mean there but im assuming your trying to call an event in the actor.

7 Likes

Hello.

While I’m sure this works, I’m actually unable to replicate your code.

I thought that maybe my version was outdated after I couldn’t find the “Cast to Pickup” or “Use” function anywhere, so I reinstalled it all. It took ages, since I’ve never really had good internet…

But since I still can’t find “Cast to Pickup” anywhere, I have to ask if there’s something I’m missing here?

Pickup is a custom class you’d need to create yourself. The same goes for the Use function - it belongs to the Pickup class ThompsonN13 created.

No need to reinstall the anything.

Ah, thank you! I still ended up needing to download something (The C++ redistributable) but I’m sure it’ll be much easier now. Thank you!

yea what Everynone said.

1 Like

Yes, thank you! It works like a charm now that it’s all sorted out.

GetAllActorsOfClass is acceptable due to how UE4 handles it; remains largely performant. Still doesn’t scale well with large worlds and should be avoided. Any other GetAllActors… nodes are not performant whatsoever and should be avoided.

Interactable actors should simply add themselves to an array contained in the GameState in “On Begin Play” and unregister themselves in “OnDestroyed”, when you need them you can “Get GameState” → Cast to your game state with the array, and access them there.

No need for tags. No need for expensive lookup operations. If their interactability is toggled via tags then the actor just checks it’s own tags.

Never use GetAllActors… nodes, they will really hurt performance, level load times, etc. – For smaller games GetAllActorsOfClass (only) is acceptable.

This way the performance costs you nothing, it’s effectively free.

This however, is only answering your question in a way that’s constrained to your chosen method. There should be no need to loop every interactable actor. Simply have a trigger sphere that adds and removes themselves to an array on your character/pawn when you begin/exit overlap. Easy.

1 Like

I actually created a custom node that does exactly this since it seemed like a common problem. It takes in any array of actors (so you could use ThompsonN13’s method with “Get All Actors With Tag”, but you can replace everything else after that with this custom node. It returns a sorted struct array, the struct being (actor + distance from target). So to get the closest actor from target you would simply “get” the 0 index. To get the farthest actor from target you would “get” the last index. Or it has an option to sort in reverse order, furthest to closest from target.

Here is a link to the tutorial to add the C++ code for the node (all copy/paste)

Below is an example of the node and the struct it returns

2 Likes

Hey @Nebula Games, so I’ve tried to use your function but it’s not returning me the “distance” and a simple “actor” data, but only a “Actor Dist” type of variable. Can you help me pls?

Hey @Douglas, the functio returns a sorted array of the custom struct “Actor Dist”. If you use a “Get” node pulling out the 0 index will be the closest or furthest actor depending how you chose to sort. Once you have an individual struct variable from the “Get” node simply right click on the output pin and ask it to split the struct like any other struct variable. This should then give you access to the 2 component variables (Actor object pin, Distance float pin)

Many thanks! Not it works great. Sorry about this kind of question but I’m still learning BP and I had no clue of this “split” function haha.

No problem. I’m happy the node works for you. That was the plan to make things simple and easy :slight_smile:

Just an update, 4.27 has a new node to do most of this. " Find Nearest Actor", you will still need to feed it an array of actors from find by tag or other means. But then you will get back closest actor and distance.

2 Likes

RE #1:
Thank you. I searched this from the year 2022 and this image was enough to make what I needed.
.

RE #2:

UE4.27.2:
Is GetAllActorsOfClass with Tag - more performant than GetAllActorsOfClass?

I want to use it on checkpoint Actors. I’ll have about 5 of that exact Class in a level. And I only want to GetAll with a certain tag (which is activated when checkpoint reached).
So is GetAllActorsOfClass with Tag - performant for me in a giant level (1000 other Classes) but only 5 of the Checkpoint Actor Class? Ty
.
.
Edit: RE #3

Thank you. I ended up using this. (Unless someone tells me the first graph pic is more performant than the new Epic node.)

Before I searched for this thread, I tried to type in Get “nearest” > didnt find.

  1. I had to uncheck context specific, Then type in “Find Nearest.”
  2. Or add a GetAllActorsOfClass with Tag > drag off the Output Actors > type Find Nearest, and that worked to replace the old code:

Works great for a similar issue. 4 years later. Thanks.

Necro-ressurect to thank you for this tip!