Hey guys,
first of all, i am sorry for my English.
So i need to say that i am in the beginning of GameDev. I know the basics of c++, and so on, and therefore i wanted to look into Unreal Engine.
My Problem is something like this:
why is it not possible to call, for example, GetOwner() in the Constructor of a component? I thought the Owner is created in the hierachy above the component, and therefore it can refer to the Owner. But why isnt this the case?
Why we need to call GetOwner() in the BeginPlay function?
Is it because the Object or the Instance of the OwnerClass is only then crrated, when i begin to play? So it would be created in the Super::BeginPlay() function?
Is this the same for âGetWorld()â ?
If this is true, is then every object only created after the Super::BeginPlay() function?
I dont know if you guys could understand my question.
Before i wanted to start to learn the Unreal Engine, I programmed some simple stuff in my IDE and i knew what is happening because if i compile and run, the âmainâ function started, if you guys know what i mean. But here i dont really know where is what happening. I know that if i click play, the BeginPlay() function gets called, but where are the objects created and so on?
And again, i am so sorry for my english, i hope that i could express my problem.
First of all, your English is perfectly understandable
Here are the times Iâve found in which the constructor is called (Iâm assuming we are talking about an AActor or UActorComponent subclass):
When the engine is starting up, the constructor is called to make the CDO (Class Default Object)
When the class is hot-reloaded, the constructor is called again to remake the CDO
When you load a level (in game or in editor), the constructor is called on every instance of the class in the level.
When you play a level, the constructor is called on every instance of the class in the level before BeginPlay is called.
So when you load the level in the editor, that is the first time your object is created. When you click âPlayâ, the objectâs
constructor get called again. So as a general rule, put code that you want run in the editor (before you hit play) and in the game in the constructor and put the code that you want run only in the game in the BeginPlay function.
(I hope this makes sense)
The CDO is a bit tricky to understand. It is not placed in a level and has nothing to do with you. However, the CDO is made before UWorld is made. If you want to use GetOwner or GetWorld in the constructor,
put the code using it inside this if statement:
if (!HasAnyFlags(RF_ClassDefaultObject)) { /* GetWorld() */ }
What this does is it makes that section only run on your ârealâ objects that you placed in the level and not on the CDO, which gets built during engine startup before the UWorld is created.
Summary: Use the constructor for code that only has to do with setting up your object, use BeginPlay for gameplay actions.
If this doesnât fully solve your problem and your object is a UActorComponent, try looking into overriding PostInitProperties.
You are asking some really fundamental questions about the engine here and answering all of those accurately would take forever. A lot of what you ask can be read-up in the documentation, but I still want to try to make some things clearer for you.
why is it not possible to call, for
example, GetOwner() in the Constructor
of a component?
It is absolutely possible to do that, but you probably mean that often a nullptr is returned from that function in the constructor. A constructor is called whenever an instance of the corresponding class is created. The engine creates and recreates instances of your actor and component classes many times in many different situations, not only when you press BeginPlay. If you place this line of code in the constructor of your classes
FString Name;
GetName(Name);
UE_LOG(LogTemp, Error, TEXT("Ctor called for %s."), *Name)
you will realize just how many instances of your objects the engine constantly creates even outside your game, e.g. during start-up, when you open a Blueprint, when you compile a Blueprint etc. A lot of this has to do with what is called âReflectionâ, which is essentially what allows you to actually see and modify your assets within the editor. The owner of a component may or may not exist when its constructor is called, it depends on the situation. Do not confuse the inheritance hierarchy in C++ with the Entity-Component system of the engine. For C++, yes the base class constructor is always called before the child class constructor, but this has (almost) nothing to do with the Actor-Component hierarchies you create for your game or when ownership gets assigned.
But here i dont really know where is
what happening.
Welcome to the world of software development. Unreal Engine is a huge system and I can assure you that the vast majority of users doesnât know either. The point is, you usually donât need to know. Following the code from main to the point where your actorâs constructor gets called is a very long and tedious road, and you most likely wonât understand a lot either if you donât already have a strong understanding of game engine design. The Unreal interface is really good and especially designed so that you donât need to know these things to make games.
The Unreal framework is kind of specific about what you can/should do in the constructor. Usually you use it to create subobjects and initialize default values. However, there are other functions that get called after the constructor by the engine that make certain guarantees on what is and what is not initialized at that stage. You can override these functions and put your own initialization logic in there. Reference: Actor Lifecycle | Unreal Engine Documentation
If you are content with my answer please mark it as accepted
Thank you so so much! I thought there is a general rule when or where an Instance or Object of a class is created. So i think i should maybe dont use get-functions of classes or other stuff that can be created, in the constructor. Or i should catch the potential errors, nullptr here, if something fails at least, totally forgot about it. Thank you so much for your explanation!!