I’m currently trying to access properties of the PlayerController from the following code:
UClass* AGame_TeamDeathMatch::GetDefaultPawnClassForController_Implementation(AController* InController)
{
APlayerController* PlayerController = Cast<APlayerController>(InController);
if (PlayerController->TestValue == NULL) {
UE_LOG(LogTemp, Log, TEXT("Value is null"));
}
}
Unfortunately, any property I try to access on the PlayerController ends up being NULL. TestValue is a uint8 that is being declared in the public section of the PlayerController.h file.The code compiles as it should. Any help to solve this issue would be greatly appreciated.
I think you misunderstanding what NULL (or rether nullptr) is considering you trying to use it against uint8
in C and C++ null is exclusively state of a pointer, pointer is a varable that points some other varable in the memory, it technically works like intiger of size of memory address size used in running platfrom, it contains memory address, which pointing to something. it is marked by *
symbol and in UE4 it is properly used on class objects, but any type technically can be turned in to pointer. Problem is pointer can point to unallocated memory and be invalid and CPU can not check memory allocation since this is not done on CPU level (OS does that). Because there a need to reset state of pointer when thing that is pointed is deleted or just no longer there, and this is done by setting pointer to 0 value… which you know as NULL ;] if pointer is 0 it means it is in unset state and you know it points to nothing.
Before introduction of nullptr in C++11 standard, C++ standard libraries used special macro called NULL which contains variable for pointer indicating null (unset) state for a pointer, which in most cases is value 0 (memory address 0), it was macro just in case if platform you compile to use something different. In C++11 this been replaced by special hard coded key word nullptr and this is one you should use, NULL macro is still there for backward compatibility with older code. There for NULL = 0 in x86 systems, so what you really doing here is this:
if (PlayerController->TestValue == 0) {
UE_LOG(LogTemp, Log, TEXT("Value is zero"));
}
It works since as i said pointers technically works like integers, so NULL is compatible with uint8 type and you don’t get any error doing so. This however would not work with non-numerical types (this excludes bool which accepts 0 as false and any other value as true, thats why if’ing !Object for example work)
The non-pointer variables like yoru uint8 are statically allocated and they are always allocated automatically by compiler and they can’t have null state or else we talking about variables in class and structure, as based on those compiler tracks variables on specific offset from memory address of first byte of object of structure or class, regardless if it’s a pointer or statically allocated object. So they be allocated whatever object it self is allocates, so in your case if PlayerController
it’s not null pointer it in most cases (since there still possibility of having invalid type in pointer, if you play with void pointers and some crazy casting) means TestValue is there on specific memory offset, it works, it just have state of 0, NULL = 0 so TestValue == NULL returns true.
Thank for you the in depth response to my issue. I guess I should have been more clear in my first post but TestValue is actually set to 1 and isn’t changed throughout the code. I started to use the TestValue variable as a way to try to simplify the issue I was having in hopes of solving it. I will describe the original issue that I was having below.
I have two variables ClassA and ClassB declared in the PlayerController.h file.
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Classes") TSubclassOf<APawn> ClassA;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Classes") TSubclassOf<APawn> ClassB;
I have then made a blueprint class with the parent class set to the PlayerController. Inside of the blueprint I have set ClassA and ClassB as two different characters.
However when trying to access ClassA or ClassB from inside of the AGame_TeamDeathMatch::GetDefaultPawnClassForController_Implementation
using similar casting of InController as above, both ClassA and ClassB are returned as NULL.
In further testing I have moved the declaration of ClassA and ClassB to the AGame_TeamDeathMatch header. Created another blueprint class with the parent of AGame_TeamDeathMatch. Set ClassA and ClassB in the blueprint using the same two characters as before and I’m correctly able to reference them.
This makes me wonder if my casting of the AController to the APlayerController is incorrect in some way?
Sorry for late reponce
No deceleration can be elsewhere, it does not matter, compiler in cpp needs it recognize function and UHT needs a include in cpp to hatch all the markers, they can be seperated. Fact that you successfuly compile and oyu dont get crash means that compiler see ->TestValue and it is casted correcly sicne if pointer was null you would definitly get crash from doing PlayerController->TestValue
, you could double check by trying PlayerController == NULL
, Cast function is returning null pointer if cast is incorrect or you giving it null pointer. There no mistake on that as Cast function is UE4 function and checks UClass of the object to verify if you casting correctly. If PlayerController is casting and don’t give null pointer everything iis ok and potentially issue is in setting TestValue
Also why you altering APlayerController? It’s better to do new class on your module as modifying engine makes workflow harder as you need to add building enigne to process.