I have a C++ class that doesn’t inherit from any Unreal classes. In it I have a callback where I would like to manipulate the rotation of an actor in the level. Is there a way to access an actor of a certain class?
I tried the following. First I made APoseCube a subclass of AActor, and put it in the scene. I added a Transform component to it. Then I tried this code in my standalone C++ class:
TArray<AActor*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), APoseCube::StaticClass(), FoundActors);
I kept getting unidentified identifier errors with GetWorld. When I found some wacky #include statements to make it work and I hit play, Unreal straight up crashed. I believe it’s because I tried to use FoundActors later in the code, but it was null, so now I’m still trying to find a way to get the actors in a scene from my standalone C++ code. Any help would be appreciated.
Would you know how to pass a valid World pointer into a class that doesn’t inherit from UObject? That’s kind of where I am stuck. Maybe there’s a way without using the GetAllActorsOfClass method I used above; I just wrote that to show what I tried so far.
So the code you’ve posted above is a C++ class that doesn’t inherit from UObject or anything else? If that’s the case then what is GetWorld()? In an AActor and many other classes in Unreal, GetWorld is defined but if you’re not inheriting from anything, or if you are inheriting from something like UObject which has no implementation of GetWorld then you must have implemented GetWorld yourself.
If whatever GetWorld returns is not valid then it won’t be able to iterate through all actors. You need a valid instance of your current world in order to iterate through all actors of class.
You might find it easier to pass a valid World pointer into your method which contains the code you pasted above.
Let’s call your class MyCustomClass and the method containing your code RotateActor. You’re .h file would include something like:
static void RotateActor(const class UWorld* WorldObject);
Now, you need to call RotateActor from somewhere. This could be from another actor, a game instance, some UI or pretty much anywhere else. Let’s say we’re calling it from an Actor in the world called AMyActor. Your cpp file would contain something like:
void AMyActor::MyMethod()
{
MyCustomClass::RotateActor(GetWorld());
}
That works if MyCustomClass RotateActor is static as shown above. If you don’t want it to be static then you’ll need to cache a pointer to MyCustomClass somewhere can use MyCustomClassPointer->RotateActor(GetWorld());
Whatever calls MyMethod depends entirely on your game. Perhaps its in response to taking damage or hitting a trigger volume. It doesn’t really matter so long as whatever it is that calls MyCustomClass::RotateActor has an implementation of GetWorld(). If it doesn’t then you’ll need to have a way to pass a World object to that method too, or have some consistent way of being able to access it.
For example, I have manager classes like UWaypointManager which inherits from UObject which in itself doesn’t have a GetWorld implementation. Instead, when the Manager class is created by the game instance, I cache a pointer to GameInstance withing the Manager and I can then use that to GetWorld whenever needed.
Out of interest, why is your class not inheriting from UObject or some other UE4 class? You certainly don’t have to but unless their is a specific reason not to then you’re probably better off using a UE4 class as a base (certainly helps with memory management)
Well you’re right maybe I should explain the whole story. I’m using a plugin called UROSBridge. A message will be received over TCP, and I have to setup a ‘subscriber’ for it in Unreal. Each subscriber inherits from an abstract class which looks like this:
#include "CoreMinimal.h"
#include "Json.h"
#include "ROSBridgeMsg.h"
class UROSBRIDGE_API FROSBridgeSubscriber
{
protected:
FString Topic;
FString Type;
public:
FROSBridgeSubscriber(FString InTopic, FString InType):
Topic(InTopic), Type(InType)
{
}
virtual ~FROSBridgeSubscriber()
{
}
virtual FString GetType() const
{
return Type;
}
virtual FString GetTopic() const
{
return Topic;
}
virtual TSharedPtr<FROSBridgeMsg> ParseMessage(TSharedPtr<FJsonObject> JsonObject) const = 0;
virtual void Callback(TSharedPtr<FROSBridgeMsg> Msg) = 0;
};
Upon receiving a message, Callback() is called, and it is here where I have to manipulate an actor in the scene. In particular, I will be receiving orientation messages which I want to use to set the rotation of a cube actor. For this reason I don’t think I will be able to start from the actor and call this method. I have to start from the callback somehow. I thought I could put GetWorld() in the constructor, but that doesn’t work.
Woops I messed up the reply. Anyway I think I figured it out. Pretty sure it turned out to be a style issue. I just extended the abstract class as usual but added another method SetupCube() where I pass in the cube. I call SetupCube after initializing the Subscriber. I was stuck since I didn’t want to change the constructor signature to pass the cube there, but for some reason I was hesitant to add more functions than the AC specified… Sorry for the trouble
No problem, I was just about to start writing a reply suggesting the same thing.
Just one thing to note is that before you try and perform any action in the callback, you should be checking that your cube actor is still valid, otherwise you might be attempting to setup a cube which no longer exists which will cause crashes.