How do I set a range on my bot to detect a player?

So at the moment as soon as I step onto a nav mesh, all of my bots respond. How do I set a range for the bots to respond to?

My code in my AIController. Can I just set a range in the behaviour tree?

 void AFPSAIController::SearchForEnemy()
 {
     APawn* MyBot = GetPawn();
     if (MyBot == NULL)
     {
         return;
     }
 
     const FVector MyLoc = MyBot->GetActorLocation();
     float BestDistSq = MAX_FLT;
     AFPSCharacter* BestPawn = NULL;
 
     for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; ++It)
     {
         AFPSCharacter* TestPawn = Cast<AFPSCharacter>(*It);
         if (TestPawn)
         {
             const float DistSq = FVector::Dist(TestPawn->GetActorLocation(), MyLoc);
             if (DistSq < BestDistSq)
             {
                 BestDistSq = DistSq;
                 BestPawn = TestPawn;
             }
         }
     }
     if (BestPawn)
     {
         SetTargetEnemy(BestPawn);
     }
 }
 
 void AFPSAIController::SetTargetEnemy(class APawn *InPawn)
 {
     //Checks for the blackboard
     BlackboardComp->SetValueAsObject(EnemyKeyID, InPawn);
     BlackboardComp->SetValueAsVector(EnemyLocationID, InPawn->GetActorLocation());
 }

You talk about distance range ? Like exposing your BestDistSq ?

Ye setting a distance range for the bots to react too. Would I just use a value on my BestDistSq?

are you using “ray trace” on enemies to detect the player?

Looking at your code you already have your range which is BestDistSq. For now your range is 3.402823466e+38F which is pretty big but if you expose it as a UPROPERTY(EditAnywhere) you can edit it in your controller BP

Apparently not, he is getting every AFPSCharacter actor in the scene and checking distance

so that sounds to be a really heavy process. try some other ways like using “AI Move To” or “Ray tracing” then you can play with distance and many other options.

I don’t know about “AI move to” in c++ but if you wanna try ray casting in c++ I can help you.

I do use tracing in my weapon class but not in my controller. I also use a move to, in my behaviour tree for the bot. Will try what zimzimdz suggested first. Would be interested how you use tracing in the bot class though.

I can’t seem to get it to show up, I never had a BP originally for the controller, but made one to have a look. I have put BestDistSq as a property.

I have already written some functions on my bot that traces toward the player and if hit the player and if the length of that trace equals a specific number then the bots start chasing the player.
these are my functions:
I commented some lines of my code for you.
I hope it be helpful

void AEnemyBot::See()
{
	FVector EyeLocation = GetMesh()->GetSocketLocation("Eye"); // Eye is socket on head of Bot to use as start_trace

	FVector Start_Trace = EyeLocation;
	FVector End;

	ASwatCharacter* Swat = Cast<ASwatCharacter>(UGameplayStatics::GetPlayerCharacter(this, 0));
	if(Swat)
	{
		FVector End_Trace = Swat->GetActorLocation(); // here I used the location of my player as end of trace(End_trace) so the bot always traces toward player.
		End = End_Trace;
	}

	const FHitResult Impact = Detect(Start_Trace, End); // it calls Detect() function. 

	Process(Impact, Start_Trace, End); // it calls process() function.

	

}

FHitResult AEnemyBot::Detect(FVector Start_Trace, FVector End_Trace)
{
	FCollisionQueryParams TraceParams(FName(""), true, this);
	TraceParams.bTraceAsyncScene = true;
	TraceParams.bReturnPhysicalMaterial = true;
	TraceParams.bTraceComplex = true;
	TraceParams.AddIgnoredActor(this);


	FHitResult Hit(ForceInit);

	GetWorld()->LineTraceSingleByChannel(Hit, Start_Trace, End_Trace, TRACE_WEAPON, TraceParams);
	DrawDebugLine(this->GetWorld(), Start_Trace, End_Trace, FColor::Blue, true, 1000, 10.f);// it draws a blue line and shows the trace
	GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Black, "Detecting");

	return Hit;
}

void AEnemyBot::Process(const FHitResult & Impact, const FVector & Orgin, const FVector End)
{

	const FVector EndPoint = Impact.GetActor() ? Impact.ImpactPoint : End;// here calculate the end_trace again and sees if the trace hit the player or something else in its way something like a wall. if hit something the end point would be the impact point. 
    
	DrawDebugLine(this->GetWorld(), Orgin, EndPoint, FColor::Yellow, true, 1000, 15.f);// draws a yellow line to say, hey i have hit something in my way
	


	

	const FVector Length = Orgin - EndPoint;// here calculates the length of the trace by subtracting the start_trace(orgin) with Endpoint.

	ASwatCharacter* Swat = Cast<ASwatCharacter>(Impact.GetActor());
	if (Swat && Length.Size()<1500 )// here we say if that length equals 1500 means that bot is seeing us.
	{
		GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Blue, "You are seen");  ////*****
		IsChasing = true;
		Chase(); /// this is a task 

		
	}
	else
	{
		GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Blue, "You ran away"); // if that length increases or you go behind a wall the bots can not see you.
		IsChasing = false;
		
		
	}
	
}

those are some really simple functions copy them to visual studio and then read them.

Sorry I’m still trying to understand quite a bit in Unreal so my questions are probably stupid. How has the chase been done? Do I still need the chase as I have a BTService blueprint which follows the player once an enemy has been found?

i think this tutorial is what you need

but all the function in it are implemented in blueprint but is good for you to begin.
you can understand about chasing the player by that.

Ok thank you for your help, much appreciated, I have implemented your code, with the chase commented out at the moment. Currently nothing happens or appears. So still figuring it out.

for those function like chase() that you don’t know about you can just print a message like"chasing is happening"
in my code chase() is a UFUNCTION(BlueprintImplementableEvent) that can be implemented in blueprint and called in c++.

feel free to ask about that code. :slight_smile:

for the forth parameter of this function you need to define it in your “project name.h”
GetWorld()->LineTraceSingleByChannel(Hit, Start_Trace, End_Trace, TRACE_WEAPON, TraceParams);

so go to your “project name.h” copy this there: #define TRACE_WEAPON ECC_GameTraceChannel1

that is a custom trace channel

I do have a custom channel set up for my weapon already. I assumed I would have to create a second one for the bot?

no. no need to create a second one.

Can I ask? hehe. Sorry I think I’m getting mixed up as I’m use to doing it in the AIController rather than the AICharacter. I also originally set up a service which executes the SearchForEnemy. Then in my behaviour tree on the select I use the service which executes searchForEnemy. If any of that makes sense? Then I use a Move To Enemy. So I switched the service to execute “See” Instead. Expecting it to work.