hi everyone, i am really confused by some simple stuff, i am trying to get some values from class A and return that value into class B and do something with the value. first thing that came to mind was that i should create an instance of class A in class B so i will be able to use class A’s public functions and vars. so i made an instance in B.h.
class A* someName;
i tried to use some of functions of someName in B.cpp, but the problem is when i play the game it shows that someName is nullptr. in programming viewsight its true to me. we can use class instances in another classes.
so what the problem can be?
To use other class in this example A class member functions, they need to be accessible for class B, eg they need to be declared as public or class B need to be friend class of A. Consider this simple example:
class A
{
public:
// A Constructor
A() {}
void DoSomeStuff();
};
class B
{
private:
A* _a;
public:
// B Constructor
B()
{
// Create new instance of A class
_a = new A();
}
// B Class Destructor (needed because we need to free memory we
// allocated by creating A class
~B()
{
// need to call this to free memory
delete _a;
}
void ExecuteSomeStuffInA()
{
// First check if pointer to instance is valid
if (_a != nullptr) {
// pointer is valid, execute function in A class
_a->DoSomeStuff();
}
}
};
What you doing is not instantiation but only deceleration. But variable of type with * symbol is a pointer, it points something in memory, in technical sense it a integer varable containing memory address. Just declare it won’t magically make it point to the object, same as integer it will have value 0 aka nullptr.
You need to set pointer either by instantiation or getting the pointer from diffrence sources (like get functions) if they already been created. Normally in C++ you would use new operator to create a instance, in general it is operator to dynamically allocate variable, including integer and float varables. But in UE4 you not really gonna use that, as UE4 got special function to create objects and you rarely (there are some advance cases) create integer and float pointers.
To instantiate Actor you use function in UWorld called SpawnActor and oyu get UWorld instance using in any actor:
SpawnActor has special template argument (look example 1), which allows auto casting (you don’t need to cast return varable) and automaticlly fill UClass* function argument (which oyu can see i used in argument 2)
If SpawnActor fails to spawn, it will print reason in the log and return nullptr
To instantiate UObject oyu use NewObject, similar as Spawn actor, but this time you need to define outer object which in most cases are object you creating object in
someName = NewObject<A>(this);
But what im saying so far is just creation of object, UE4 is big and it create many objects in it’s lifetime and your world is big and each time you palce actor on the level you already creating instance of it so you dont need to create new ones, you need to get one or make newly create object to send pointer to it self somewhere else.
For example AGameMode is a core of the game code that exist in span of whole level (unlike UGameInstance which exist in spawn of entire game), it is always create by UE4 automaticly and to access it instance you need to call function in UWorld called GetAuthGameMode():
AMyGameMode* MyGameMode = ()->GetAuthGameMode();
As oyu can see this function also have template argument that do automatic casting, it will return nullptr if game mode class is not the one that you requested.
If you make single player game, you can get APlayerController same way:
If you used blueprint, you can see the exact same pattern here… yes, because blue pins and link are equivalent of object pointers in C++ and it uses mostly same functions.
Getting actor on level is a lot more tricky, if there is importent actor for a game mode oyu making, in general practice actor should send it’s pointer to GameMode where other actors can access it. For example you make some football game and oyu got ball ABall* placed in the level on BeginPlay of the ball you set varable Ball in gamemode AMyGameMode* :
()->GetAuthGameMode()->Ball = this;
this is pointer to instance of class that function is currently executing in, so object it self can tell where they are in memory. Now you can access game mode anywhere and access Ball from nearly anywhere in the code
Other way is search for a actor, you should use it as last resort as it’s most expensive way to do it… and yes it the same thing you use in blueprint, GetAllActorsOfClass:
TArray<AActor> Actors;
UGameplayStatics::GetAllActorsOfClass((),ABall::StaticClass(), Actors);
//Knowing we have only one ball on the level we just gonna grab first item of array
ABall* Ball
//checking if array is not empty before getting it
if(Actors.Num() > 0) Ball = Actors[0];
But this function was designed for blueprints that does not support iterators which oyu can use C++ and are a lot better as you can break search loop once you find actor you looking for:
A lot easier way is to make actor pointer EditAnywhere, or more optimally EditInstanceOnly:
And when you place an actor having this variable on the level you can set this variable in property editor, this allows to easily link actors together without need for them to register themselves or search or each other.
Also remeber if you declere pointer to UObject or AActor (which is also UObject) in class you need to place UPROPERTY(), this will make varbale visible for the engine and it will monitor object referencing for GC, it will also automaticly set property to nullptr if object gets destroyed, something that does not happen automatically. If object pointer won’t be nullptr when it’s destroyed, you got so called invalid pointer, pointing to invalid memory address which either points to trash data in memory or nonallocated memory and accessing it will cause a imminent crash. You Would need to use expensive IsValid() function which checks if pointer is pointing to valid created UObject that engine tracks.
hi and thaks for answring. i read the information uve mentioned. it was helpful, but just to be clear, i have a Coin class and when player overlaps coins, score variable(its int) at class Coin gets plus plus. now i want to send this score value to my playerPawn class, so i declared coin as i said and yes i know in cpp programing we use ‘‘new’’ keyword but i havnt seen that in ue4 coding as u said it rerly gets used. so story short, whats yr idea about sending class Coin’s(coins are spawning in random places of world) score var into my playerPawn class so i can send it to blueprint widgete and show the score on screen?
by the way why i am insisting to send the score to playerPawn is i cant find a way to show score on screen from Coin(which is actor) but i know how we can do it from controlling pawn(which is the pawn we play with). i created a widgetBlueprint and i bind the scoreText, then i created a variable inside the blueprint function that i made and i specified the variable type, it is working fine when i use playerPawn type, and it updates the screen accurately but Coin type is not working fine.
one basic question : coins are just objects that spawn in the world and gets overlapped, which i want to point that they have not any controller classes cuz they dont need to. can i send information and update the widgetBlueprint by only using class Coin(and basically can i send information from classes that aint my game’s main classes like the coin )which only have to spawn and gets destroy?)
well thats becuz i have many other overlapping events. i am practicing an endless game. floor has BoxComponent and when i overlap Floor’s boxComponent it spawns the next floor in world. thats why i cant really implement the score inside PlayerPawn.
Shayan,
Maybe I misunderstand but, why are you increasing score in the coin class? When your player overlaps a coin should you not be updating a score in your player rather than the coin?
But your Game Instance is persistent so you could store your players’ score in there so that it persists between levels/maps. (If that is what you mean when you say next floor). I don’t see why storing the score in the coins gives you any benefit in this situation. They will not persist between levels any more than the player pawn will? I don’t think it can be at all sensible to keep your players score in all the individual coins. I also don’t see why the amount of overlapping events has any bearing on this. When an overlap happens you find what other actor is overlapping and then decide what to do. So, if your player overlaps a coin you add score and if your player overlaps somethings else then you don’t.
O_o yes thats a good idea…
void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
so in playerPawn class that i implement OnOverlapBegin i can use OtherActor param and the logic should be if(OtherActor == Coin){score++;}
but how can i get the coin as i said at the main question it returns nullptr
If the OtherActor is a coin then ‘PointerNameULike’ will be a pointer to it. If the OtherActor is not a coin then ‘PointerNameULike’ will be null. I think that will work for you.