What am I not quite understanding here?

I’m asking as much about better understanding and interpreting the documentation as seeking an answer to specific issue.

Basically, I want to use GetRandomReachablePointInRadius() in code. So I look up the documentation and find this: UNavigationSystemV1::GetRandomReachablePointInRadius | Unreal Engine Documentation

I proceed to write this:

FNavLocation newLocation;
	ANavigationData newNavData;
	FSharedConstNavQueryFilter queryFilter;
	UNavigationSystemV1::GetRandomReachablePointInRadius(thisEnemy->GetActorLocation(), 500.0f, newLocation, newNavData, queryFilter);

My understanding is that it:

  1. Needs an origin, so I pass that in.
  2. Needs a radius, so I set something
  3. Will generate a location, which is the whole point so of course I store that
  4. That it needs NavData but itll default to MainNavData on Null so I just created one to fill the space
  5. Wants a filter (that I don’t fully understand tbh but this isn’t uncommon, just a further step of usefulness that I can learn about later) so I create an empty one since I’m not filtering anything anyway

Of course, it’s not working. The error is “A non-static member reference should be relative to a specfic object”. Clearly I’m misunderstanding something but I don’t know what and I’d like to learn how to better read the docs to better troubleshoot and understand issues like this one.

I figured out that in this instance there was just a better system to use. The code looks like this:

UNavigationSystemV1* navSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
	FVector newLocation;
	navSys->K2_GetRandomReachablePointInRadius(GetWorld(), thisEnemy->GetActorLocation(), newLocation, 500.0f);

I’m not really sure what “K2” is or means but it’s a more straightforward option and I also realized I need to get the nav system from my game to begin with.

K2 = Kismet 2 also known as Blueprint.

Ah, okay, that makes sense. So it’s a Kismet Library just part of the Nav system.

This is a C++ issue though, not UE related.

The error you got is telling you that you cannot call non static method without an instance to call it on.

The method you want to call (GetRandomReachablePointInRadius) is non static method of a class, so you first need to get an instance of that class to call that method on.

Usually there are global getters for such things:
const UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(&World)

As you found yourself.

In the second post you call the K2_GetRandomReachablePointInRadius on an instance of an object.

Methods that are prefixed with “K2” are indeed meant to be called from blueprints, because they have slightly different signature (notice UObject* WorldContextObject as first param + sometimes other things).

The reason why it’s prefixed is that UFUNCTION() doesn’t do overloads. There is one name for one ufunction. So it’s “safer” to prefix it with K2_name so you can have your C++ name be declared UFUNCTION as well if needed. (at least that’s why I differentiate the names)

Even after figuring out I needed to get the instance of the class, I still wasn’t getting the function to work - although I admittedly came across the K2 solution around the same time so I didn’t see if the error was different. The K2 solution was appealing for it’s straight forward vector use over the FNavLocation use to be honest.

Is there anything else I may have been doing wrong in the initial code?

NULL is something totally different. Instance of anything (empty/default class) is definitely not a null.

FSharedConstNavQueryFilter is a type alias to TSharedPtr of FNavigationQueryFilter, so it also takes NULL if instance is not required.

Last two parameters of this function have default values (NULL), so you can omit them

FNavLocation Result;
GetRandomReachablePointInRadius(thisEnemy->GetActorLocation(), 500.0f, Result)

2 Likes

I really appreciate you answering this! I feel stupid because I should’ve realized a new empty nav data wouldn’t be the same as it being null.

I have some follow-up questions if you don’t mind:

In looking into it further, I’m not seeing a clear way to grab nav data but it also looks like you generally never need to? Is that right?

Is there any practical difference between using the K2 version vs the non-K2 version?

If you have more than one NavMesh this is probably useful. (I’m not an expert on nav ;))

When using C++, there is no need to use functions with the K2_* prefix, because they take values that you should already have on hand.

If you already have an instance of a given class, you can call its function directly. K2_ functions are static, so they first have to find an instance and therefor call the function on it, so it is completely unnecessary.
It looks something like this:

int USomeClass::GenerateSomeValue()
{
   // impl
   returnValue;
}

static int USomeClass::K2_GenerateSomeValue()
{
   UWorld* World = /* FindWorld */
   USomeClass* SomeClassInstance = World->GetSomeClassInstance();
   return SomeClassInstance->GenerateSomeValue();
}
1 Like

Ah! So basically the K2 function is more a crutch because it’s just finding and using the base function anyway. I’ll definitely look into that more.

Thank you very much for taking the time to respond and explain!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.