Array of other objects with pointers

Hi All,

This is probably a complete noob question but I’ve been playing with it for awhile and still can’t quite figure out the best method.

Scenario is I want a grid based map (for turn based strategy game) with fast lookup for each grid based on a Vector2D( basically 2 dimensional array)

I started working on just using C++ array as I couldn’t determine if TArray allows quick lookup by index, i know in blueprints it has the function “Get” but I can’t find this in C++ and not sure how it works because I don’t want it to have to iterate through the array until you reach the index you specify as the array could 10’s of thousands long (total number of grids) If someone can clarify this that would be great?

I had seen you can create 2 dimensional arrays with structs and TArrays and that makes sense to me but not sure if you can access directly though index numbers (Maybe TMaps are more what i would want?) I just want a static array that doesn’t change over the course of the game to store the pointers for each grid on the map. Initialize at the map generation and then just delete the whole thing when finishing the game\level.

Either way I still want to learn more about C++ anyway so I started work on using a native C++ array:

.H



	UCLASS()
	class WORLDSCOLLIDE_API AGalaxy : public AActor
	{
		GENERATED_BODY()

		// pointer to array of pointers to each grid object
		AGrid **GridLookup;

	public:	

		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Galaxy")
		int32 GalaxySize;

		// Sets default values for this actor's properties
		AGalaxy();

		// Called when the game starts or when spawned
		virtual void BeginPlay() override;
	
		virtual void OnConstruction(const FTransform& Transform) override;

		/*
		// return the grid object located at the 2d Grid position
		*/
		AGrid* GetGrid(const FVector2D &GetLocation);

		// remove this from memory
		void Destroy();
	};

.CPP

// Sets default values
AGalaxy::AGalaxy()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = false;

	GalaxySize = 15;

	int N = GalaxySize * GalaxySize;
	GridLookup = new AGrid*[N]();
}

// Called when the game starts or when spawned
void AGalaxy::BeginPlay()
{
	Super::BeginPlay();
}


void AGalaxy::OnConstruction(const FTransform& Transform)
{

	if (GridLookup) delete[] &GridLookup;

	int N = GalaxySize * GalaxySize;
            GridLookup = new AGrid*[N]();
}

AGrid* AGalaxy::GetGrid(const FVector2D &GetLocation)
{
	int N = (GetLocation.X * GalaxySize) + GetLocation.Y;
	return GridLookup[N];
}

void AGalaxy::Destroy()
{
	if (GridLookup) delete[] &GridLookup;
}

I’m sure I haven’t done the memory management part right as probably have to delete all AGrids that get created in the array before deleting it, but just trying to get it a step at a time. and currently the above code crashes UE4 because of “GridLookup = new AGrid*N;” in the CPP file. As said I am a C++ noob so probably something obvious or an easier way of doing it but I’m just happy to learn even if I am doing it the long way :slight_smile:

FYI “AGrid” is just a UCLASS I setup which is completely bare at the moment, eventually it will contain a TArray of all units on the grid and any other stats like territory ownership, sensor details as required.

I’ll be grateful for any help or issues with my code you can point out!

Thanks,

First of all, dangling raw pointers in UE4 can be dangerous because that way UE4 never knows if an object is still referenced in memory. UE4 uses it’s own system to support garbage collection (among many other things) and it does so with the uses of macros (like UCLASS, UFUNCTION, UPROPERTY, USTRUCT, etc)

Secondly, if you want array of something, using C style array over containers is pretty much always wrong. Use TArray instead, which is the Unreal 4 version of the std vector. So yes, you can use index accessor [] with TArrays.

So basically :

Instead of:

AGrid **GridLookup;

Use:

UPROPERTY()    
TArray<AGrid*> GridLookup;

After that, you will basically never have to use the “new” and “delete” operators in Unreal as they have their own allocation mecanism for UObjects and AActor. In your case, your AGrid class is an AActor( I assume, because of the ‘A’ in the name).

To spawn an AActor, you need to use SpawnActor.
Here is the documentation page :
Spawning Actors | Unreal Engine Documentation

An example useage in your case would be :

AGrid* myNewGrid = GetWorld()->SpawnActor<AGrid>();

I hope this is enough to get you going!

Mick

Thanks Mick,

Didn’t think of trying [] as I was looking for a .get() function or something similar… lol

Think that should get me started using that with a TInlineAllocator. Haven’t got to the spawn actor yet but think I understand what to do there :slight_smile:

Cheers,