x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Office Holiday

Epic Games' offices will be on holiday from June 22nd to July 7th. During this period support will be limited. Our offices will reopen on Monday, July 8th. 

accessing function and variable of another C++ class nullptr problem

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?

Product Version: UE 4.21
Tags:
more ▼

asked May 16 '19 at 05:13 PM in C++ Programming

avatar image

Shayan.ebz99
13 3 4

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

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 GetWorld in any actor:

 someName = GetWorld()->SpawnActor<A>();

or

 someName = Cast<A>(GetWorld()->SpawnActor(A::StaticClass()));

http://api.unrealengine.com/INT/API/Runtime/Engine/Engine/UWorld/SpawnActor/4/ http://api.unrealengine.com/INT/API/Runtime/Engine/Engine/UWorld/SpawnActor/3/index.html

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

http://api.unrealengine.com/INT/API/Runtime/CoreUObject/UObject/NewObject/3/

 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 = GetWorld()->GetAuthGameMode();

http://api.unrealengine.com/INT/API/Runtime/Engine/Engine/UWorld/GetAuthGameMode/1/index.html

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:

https://api.unrealengine.com/INT/API/Runtime/Engine/Engine/UWorld/GetFirstPlayerController/1/index.html

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* :

 GetWorld()->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:

http://api.unrealengine.com/INT/API/Runtime/Engine/Kismet/UGameplayStatics/GetAllActorsOfClass/index.html

 TArray<AActor> Actors;
 UGameplayStatics::GetAllActorsOfClass(GetWorld(),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:

https://wiki.unrealengine.com/Iterators:_Object_%26_Actor_Iterators,_Optional_Class_Scope_For_Faster_Search

A lot easier way is to make actor pointer EditAnywhere, or more optimally EditInstanceOnly:

 UPROPERTY(EditInstanceOnly, Category="Related Actors")
 ABall* Ball;

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.

more ▼

answered May 16 '19 at 06:54 PM

avatar image

Shadowriver
36.6k 931 169 1111

avatar image Shayan.ebz99 May 17 '19 at 07:04 AM

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?

avatar image Shayan.ebz99 May 17 '19 at 07:19 AM

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?)

avatar image Podgyhodgy May 17 '19 at 08:46 AM

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?

avatar image Shayan.ebz99 May 17 '19 at 09:05 AM

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.

avatar image Podgyhodgy May 17 '19 at 09:55 AM

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.

avatar image Shayan.ebz99 May 17 '19 at 11:32 AM

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

avatar image Podgyhodgy May 17 '19 at 02:34 PM

just like in blueprints you try casting it to the coin class and see if it is a coin. If your coin instance is of class ACoinClass then, you do this:-

 ACoinClass* PointerNameULike = Cast<ACoinClass>(OtherActor);
 

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.

avatar image Shayan.ebz99 May 17 '19 at 04:09 PM

thanQ so much very helpful indeed.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

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();
     }
   }
 };



Hope this simple example helps.

more ▼

answered May 16 '19 at 05:29 PM

avatar image

Vertex Soup
288 4 22 16

avatar image Shayan.ebz99 May 17 '19 at 06:56 AM

hi and thank you for answering, i tried to use public vars and functions of class A but as i said it shows that i didnt instantiate A in correct way.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question