Programmatically locate nearby actors from component

So I have a Combat cpp/h component which lives on any character who can fight- its only job is to hold a function that gets a list of references to every Actor within some radius r of the actor that component is attached to, and hands it off to whatever specialized functions I write to handle combat. There are two extremely simple things I’m having trouble with:

  1. How do I get a reference to the specific actor the component is attached to? Does each component start with a reference to its actor, or do I need to manually locate what it’s childed to?

  2. What’s the easiest way to query a certain radius for actors? Unity has spherecasts, which are essentially raytraces in a spherical radius instead of a straight line, but the references to spheretrace in the unreal API seem to be a completely different functionality from what I’m looking for.

  1. I belive this is the function you are looking for: https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Components/UActorComponent/GetOwner/index.html
  2. Use EQS(Environmental Query System) or an actor iterator and for each actor check if it is in proper radius.

Ooh, GetOwner is perfect, thank you!

I’m looking at the EQS reference now, and can it be called exclusively from code? The quickstart guide illustrates how to use it through the behavior tree, but as this is being used in combat, where button mashing could call it multiple times within a very short span, I’m basically trying to run a single ActorsOfClass search that gives me a TList of everything within the search radius.

For (2), you can use UWorld::OverlapMulti (GetWorld()->OverlapMulti):
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UWorld/OverlapMulti/2/index.html
where for the CollisionShape you can use this function to make a sphere shape:
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/FCollisionShape/MakeSphere/index.html

This allows you to do an instantaneous collision query, this type of query is called a sweep in UE4 terminology, not sure if thats general or not. Another option would be to add a SphereComponent to your actor and binding a function to it that is called whenever a collision occurs with it. This may be more efficient if you want to check every tick.

By the way, while this function doesn’t allow you to specify which specific actor classes or component classes you want to check for, you can make use of trace channels to limit the check to only objects you want. For example, make a “CombatInteractable” trace channel that any damageable actor has a blocking or overlap response to. Then call the OverlapMulti on that channel and try to cast any hit actors/components to your desired class and see if it succeeds.

That’s perfect, thank you! Sweep is the word I was looking for, this is the exact functionality I was trying to describe. I do see that this returns a bool based on whether it finds blocking hits, is there a variant that returns the actual list of hits?

This is less programming and more UE workflow, but are Actors the smallest unit that can have trace channels, or can different components on a single actor have different channels? I ask because I’m implementing a lot of functionality with super hyper-aggressive component hierarchies- I make objects damageable by giving them a Damage component, and that component’s only job is to receive a GotHit event from anything that does damage, and message its actor and fellow child components to inform them that they’ve been hit. This lets me do a lot of neat things, like handle hostile NPCs and breakable terrain in the exact same way, but it means that I try to keep all functionality-specific stuff (like tracechannels for combat) specific to the component, not the actor that it lives on.

If you use OverlapMulti, the first parameter is a TArray of HitResults. You pass a TArray by reference and the hit results are stored into that array. Those are your actual results. The bool that is returned just represents whether the sweep detected a blocking hit. Note that it only returns true when the sweep ends with a blocking result, overlaps don’t count. So it can be that you have overlap results in your TArray but the boolean returned is false.

Ooh that’s perfect, thank you very much for clarifying :slight_smile:

You’re welcome, gl!