I am new to Unreal but have a little experience from other engines.
I have a class which is mostly written in C++ but I created a BP template of that class so that I could assign the mesh to it in the UI.
I have an Array of these objects ‘PlayingCards’ already in my code (I’m porting it from an old C++ Console Application I wrote). But of course I really need an array of ‘BP_PlayingCards’ in my code.
In Unity for example we would use “Instantiate(gameObjectPrefab)”. I have read there is something called “Construct” in Unreal. But only thing I can find is ‘ConstructDynamicType’ and I can’t really make sense of what that does.
The call you need is probably UWorld::SpawnActor()
It takes a UClass of the object.
The UClass can come from a configuration property on whatever object is doing the spawning (e g, an Actor or a GameMode or whatever.)
Once you configure the property, it can point at a blueprint class, or whatever other class.
The TSubclassOf<> template is very helpful here:
Thank you for this. I have just found the SpawnActor (can’t believe I couldnt find that before :D)
Would you happen to know the syntax for Spawning Actor with an Actor I made that has parameters in its constructor.
I have variable ‘UWorld* world’ already declared and initialised in the GameManager class, but when trying to use SpawnActor<APlaying_Card>() I can’t find the right function signature to take in the parameters for the constructor.
Unfortunately there’s no such thing. When creating objects in Unreal’s framework, parameterized constructors are basically a no-go. This goes for both calls to SpawnActor and NewObject.
The result is that you’ll have to write ‘Init’ functions of some sort that are called after the object is created.
This can be a real problem for Actors since you may need it initialized before BeginPlay happens, which normally happens before you get control back from SpawnActor. Fortunately there’s a solution to this with SpawnActorDeferred. It’s basically only part of the SpawnActor call that requires you to then call SpawningFinished sometime later. BeginPlay is then called from SpawningFinished. This allows you to do your initialization between the Spawn & SpawnFinished calls.
Also on the topic of constructors, you’ll find that any structure using the USTRUCT macro is required to have a default constructor that can be called with no parameters. You can have others in addition to that, but you can’t have only parameter requiring constructors.
Ah I thought as much. However I had written another question earlier on Stack Overflow in which I had an InitCard function. But they advised me to put the parameters into the constructor
This is fun. I am slowly getting there though, I have managed to spawn from my cpp script using a blueprint object. I just need to assign their ranks etc in InitCard and should be good to go.
Will keep as rule-of-thumb for now to keep all my constructor functions clear of any parameters.
Oh sure, Stack Overflow would recommend that. It’s generally a best practice in C++. But sometimes those practices get tossed out the window once you’re inside a framework like Unreal.
This is where blueprints come in handy!
In blueprints, you can specify properties as “expose on spawn.”
Then, in the spawn actor blueprint node, if the class (or at least superclass) being spawned is known, any “expose on spawn” properties end up being exposed on that node.
Even if you’re a 100% C++ programmer, sometimes, taking advantage of what blueprints can do well, is worth it.
Sounds like great advice. Although I am trying to get properly to grips with how the C++ works with UE4 first. Hopefully after that, I can start looking at use-cases for Blueprints. Great help all round, thanks guys
In general, UE4 uses an alternative C++ approach, which I also like in general C++ (constructor-arguments end up always causing tons of exception heartache.)
Create a “blank” instance of some object.
Configure the object.
Actually start using the object.
The benefit of this is that you never end up with exceptions in constructors, causing half-initialized object nightmares, and a lot of the very wordy boilerplate template stuff needed to support “accurate” lifetime in modern C++ just falls away.
Blueprints then take this to the next level; part 2) is data-driven, using the Unreal reflection system, not just a separate C++ step.
You’re absolutely right, ‘expose on spawn’ is a way to get around this when you’re working in blueprint.
However, I’ll point out that this has the limitation that it requires that you have a class member that can be directly initialized. Also any construction parameters that might be transformed (and not directly stored anywhere) or any work that you might want to perform before BeginPlay is called still don’t fit well into that process.
In fact, I had this problem regularly enough within my UI code that I wrote a custom Blueprint node that finds and calls an Init function (optionally of course) and exposes the input parameters to Init on the node in the same way as the “expose on spawn” parameters. I use this custom node for allocating widgets over the engine version almost exclusively.
I have definitely had my fair share of problems with constructors during my C++ learning journey :D. Especially seeing as I started with C# and Unity and then moved to C++.
I’m sure to use Blueprints at some point soon, but for now I use them purely for stuff that I want to assign in the UI (so far just the Mesh, and the reference to my actual BP class objects for if I want to use it in a script.)
You don’t need an Init() function, you can lazily configure everything you need in some place like BeginPlay() (actors) or OnConstructed() (widgets.)
It really is a different way to structure C++ code than the current “approved way,” but having used this other method on and off for very long, I would like to offer the observation that it’s often pretty great
Also, it’s kind-of confusing that Blueprints play two different roles:
I’m not sure I understand what you’re suggesting. Since neither of those functions take inputs you’d either have to a) access an external data source that has the data to be used to initialize but not be stored locally or b) just use “expose on spawn” parameters regardless, do the work during BeginPlay/OnConstructed and just live with members that have no purpose afterwards or c) something else?
a) is frankly an awful idea, completely breaking any capability for encapsulation and any meaningful reusability.
b) is fine if that’s the way you want to work. I don’t really like the idea of being required to make a copy of all the information I want to use construct the object. Maybe it’s a premature optimization, for sure it doesn’t really matter for a few integers or pointers to other things, but to force it for a structure or even an array where making a copy could easily become expensive? That just doesn’t sit right with me. I don’t really like to be forced to store things I don’t want to keep, but not everyone is me .
To be clear, I wasn’t saying the approach was wrong. Only that it had a specific limitation worth being aware of and how I adjusted for that limitation (because it was important to me). I understand that not everyone will care about that limitation enough to bother working around it.
UCLASS(BlueprintType, Blueprintable)
class MYGAME_API APlayingCard : public AActor {
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString MyStringInitInConstructor;
public:
APlayingCard()
{
MyStringInitInConstructor = TEXT("This is string built from C++ constructor.");
}
};
I’m not sure I understood the struggle.
That’s the result of a Blueprint created from APlayingCard class, but with its own default values while spawned from C++.
I think the point that you’re missing is that the goal is that the string (in your example) should be able to be provided by the code calling SpawnActor and not hard-coded as part of the constructor.
I’m proposing something more like b). Create the bare actor. Configure whatever properties are needed. Then start playing, which will setup the actor based on the config. The config, if you use deferred spawning and not blueprints, can come through expose-on-spawn pins, or it can be done by poking at either a “spawn config” struct member, or a number of known specific members.
Whether those members are “wasted” is a bit of a philosophical question. Their cost is not particularly high, and if your game wants to support “reset player to initial state” without having to re-load the world from scratch, it can come in quite handy!