Download

Beginner question: What „Stop” and „Play” buttons in UE really do from C++ point of view?

Hello,

This is narrowed and easy to reproduce version of my original problem described HERE (no need to read it to understand my problem thou). HERE IS full project.

So I create new blank project Games->Blank->use C++. Add to level single cube at location (600,600,0). Create new C++ Class that inheritance from „Pawn” class (MyPawn). Create a Blueprint based on that class. Create 2 C++ files and add it to the project in VS:

level.h:



#pragma once
#include <array>
extern std::array<std::array<int, 5>, 5> Level;


level.cpp:



#include "Level.h"
#include <array>
std::array<std::array<int, 5>, 5> Level =
{ 600,0,0,0,0,
0,600,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0};


in MyPawn.h add line:



UFUNCTION(BlueprintCallable) FVector GetPlayerStartPosition();


and in MyPawn.cpp add:



#include "Level.h"

…

FVector AMyPawn::GetPlayerStartPosition()
{
FVector start_position;
start_position.Set((float)Level[0][0], (float)Level[1][1], 0.0f);
Level[0][0] = Level[1][1] = 0;
return start_position;
}


I know Level[0][0] = 0 look kind a weird but this line is CRITICAL in my question point of view (see original post if you really wish to understand why I do that, tldr: it’s part of game logic).

Create Blueprint „MyGame” based on „Game Mode Base” in world settings select it in GameMode Override. In „MyGame” blueprint change default Pawn Class to MyPawn_BP. In MyPawn_BP „EventGrpah” from EventBeginnPlay drag line to „GetPlayerStartPosition” function and give what this function return to „SetActorLocation” New Location field as image show:

And now how this program behave (and what I don’t understand here). When you first time compile and run it everything seams to work as expected: player go to 600,600,0 position. But when you make 2 simple moves now: click „Stop” in Unreal Editor and then „Play” (notice that I don’t change anything in my code in between this 2 clicks!) actor start in … (0,0,0) location. As I say in my first post on this forum I’m a physicist not a programmer and this behavior really surprise me. Why this is happened??? Why variable Level[0][0] persist thru runs?

Best regards,
Yansen.

PS. Sorry for my poor English – it’s not my native language.

Trying to make this as simple as possible:

  • Play: creates a duplicate Game World of your Editor World, starts running the game
  • Stop: stops running the game, destroys the duplicate Game World, reloads your Editor World

If you are looking for “Pause”-like functionality try Eject.

You are doing a bit of an unisual behavior with your
extern std::array<std::array<int, 5>, 5> Level;

The way the lifecycle work in UE might be having different behavior than you expect.

Try this.

  1. Close unreal engine.
  2. Open your project
  3. Hit play and confirm the right behavior.
  4. Hit Stop and close unreal project.
  5. Open your project again
  6. Hit play and confirm the right behavior again
  7. Hit stop, then hit play again
  8. Observe the wrong behavior

What I expect might be happening is you are thinking all the code is 100% initiated from scratch like a typical C++ program entering int main().
That’s not what happens in UE. You need to realize this isn’t traditional “C++”, its “Unreal C++” and has slightly different rules. Especially around life time of things and when and what things get initiated, especially more-so when coming from the PIE (Play In Editor)

And when you do the
Level[0][0] = Level[1][1] = 0; You are making a change to a value that is persisted between ‘plays’

Another alternative to try is is using Standalone Game instead of Play In Editor e.g. https://i.imgur.com/NrWOzfu.png
And see if you have the right behavior. Standalone game will do a full proper re-initialization that is more aligned with the behavior of what you might expect.

I am not sure why your use-case has for the externing of your level array like you’ve done. But you might need a way to properly reset that back to default state, and not use a global variable quite like you are doing.

namrog84 - thx - you 100% right! Using “Standalone Game” work like a charm. Fun fact thou. If I make this stupid class to “simulate” 2D array:



#pragma once
#include "CoreMinimal.h"

template <class T> class TArray2D
{
 TArray<T> data;
 int32 width, height;
 public:
  TArray2D()
  {
   width = 0;
   height = 0;
  }
  void Init(int32 _width, int32 _height, T value)
  {
   data.Init(value,_width * _height);
   width = _width;
   height = _height;
  }

  T Get(int32 row, int32 col)
  {
   return data[width * row + col];
  }
  void Set(int row, int col, int value)
  {
   data[width * row + col] = value;
  }
  int32 GetWidth() { return width; }
  int32 GetHeight() { return height; }
};



and use it instead of std::array then my code work as expected even when “Play” is set to “Selected viewport”. I think that I will stick with this solution since it’s faster to test app this way. And since I’m beginner I test it even after smallest changes in code.

Best regards,
Yansen.