Hello, I am attempting to have an interface pointer variable that is declared in the header be VisibleAnywhere, BlueprintReadOnly in the UPROPERTY() but when I compile it gives me an error:
UPROPERTY pointers cannot be interface - did you mean TScriptInterface?
But I don’t know what that means or how TScriptInterface’s work…
If anybody can point me(excuse the pun) in the right direction or just flat out tell me how to fix this, that would greatly appreciated.
Ok, but I have three questions. How would I set the value in code like say the Constructor I was setting the variable to nullptr how would I do that with TScriptInterface? And I also set the variable in BeginPlay using a cast what would be the equivalent of that for TScriptInterface? And how would I check if TScriptInterface is valid?
You can set the value in the constructor in the same way you would set a pointer. The pointer type must be null or one derived from UObject though - an IMyInterface* won’t work:
SelfInterface = nullptr; // ok
SelfInterface = UObjectPtr; // ok
SelfInterface = (IMyInterface*)UObjectPtr; // won't work
For casting, you can just call GetObject() and cast as usual:
So I would put UMyInterface or add static class, instead of IMtInterface? When I enter GetObject it comes up with GetObjectRef, GetObjectW, and GetInterface. I really appreciate you helping clear this up for me
But if SelfInterface is already an TScriptInterface then you don’t need a cast, because you know it’s already of that type. Instead, you can just call it directly:
SelfInterface->DoThing();
You would use your code above if you needed to discover an interface other than IMyInterface (and you’d probably use Cast instead of CastChecked, if you want to handle the possibility of failure).
GetObject() will work. GetInterface() should work but doesn’t because it’ll call the FScriptInterface base class function which just returns a void* instead of InterfaceType*. TScriptInterface is in need of some API love. :-p
GetObjectW is probably cropping up because of the Windows headers, which we do not have any control over:
Ok I found out how to set the TScriptInterface’s interface to another interface. Thank you very much for you assistance! Example for better explanation below:
Called when the game starts or when spawned
void ALeverActor::BeginPlay()
{
Super::BeginPlay();
//Since I'm doing this only in BeginPlay,
//I'm gonna make a temp variable that gets deleted after BeginPlay is called
IMyInterface* tempMyInterface = nullptr;
tempMyInterface = Cast<IMyInterface>(this);
//Both of these have to be set!
SelfInterface.SetInterface(tempMyInterface);
//Since I'm getting the interface in self/this I'm setting the object for this.
SelfInterface.SetObject(this);
if (SelfInterface)
{
UE_LOG(LogTemp, Warning, TEXT("SelfInterface is valid"));
}
}
Hi, I follow what you said here. It work pretty well, appart when I’m testing if it’s valid. It’s always return false !
I’ve tested with a log, and the "TScriptInterface<>->GetObject()->GetName() print me the good think. So my pointer is not false. So I have no idea why the test is always false.
The implementation of TScriptInterface::operator bool() and TScriptInterface::operator->() are both implemented in terms of the same function, so they should be consistent.
In fact, after some verifications, the SourceObject is good (When I use GetObject(), it return me the good pointer), but the InterfacePointer is Always false.
The thing is, that the actor that implement the interface is Blueprint Actor inherited from simple Actor. And in Class Settings, I implement the interface. Maybe that is the reason why it don’t work.
I can call Interface functions from blueprint, but when I call interface functions from C++ I got a crash (BReackpoint reached)
Are you setting this TScriptInterface as a property via BPs? It can only be set by native C++, not Blueprints or any other system.
TScriptInterface is like a tuple of UObject*andIMyInterface*. It holds a UObject*to keep the GC happy and aIMyInterface*to make calls against. Setting it in native code, you have to pass theIInterface*- it will copy that and then cast back to theUObject*` to store that too.
But if you set it in any other way (e.g. reflection, via BPs), then you will only be setting the UObject* part. That sounds like it could be the reason why you have an object but no interface.
I’m setting the TScriptInterface via C++. But The Actor that implement the interface is created by BP. But I finally got it to Work like that :
IYourInterface::Execute_YourFunctionName( ActorPointerWhichExecuteTheFunction, params … );
THanks for the answers anyway.
But the thing is the IMyInterface is always at 0x00000 in debuger. (So nullptr)
I use MyTScriptInterface = MyObjectPtr to set it !