Returning a TArray of FVector2D to blueprint

TL;DR: How do you return a TArray of FVector2Ds created in a C++ function to Blueprint?


I’ve been trying to return a TArray of FVector2D, but whenever I call the function in Blueprint and/or want to use the result, all it does is crash. How do I properly return a TArray of FVector2D?

This is my current header and implementation:

/** Generates sample points in 2D space using Poisson Disc distribution. **/
UFUNCTION(BlueprintCallable, meta = (FriendlyName = "2D Distribute (Poisson Disc)", Keywords = "Random Poisson Disc Distribution 2D"), Category = "Random|Distribution")
static TArray<FVector2D> Generate2D(float fWidth = 1.0f, float fHeight = 1.0f, float fSampleDistance = 0.5f, int32 iMaxNewPoints = 30);

TArray<FVector2D> UPoissonDisc2D::Generate2D(float fWidth, float fHeight, float fSampleDistance, int iMaxNewPoints) {
	unsigned int iCells, iCellsX, iCellsY; double dCellSize;
	unsigned int iCell, iCellX, iCellY;
	FVector2D* v2DSample; FVector2D** v2DSamples;
	TDoubleLinkedList<FVector2D*>* v2DList;
	UE_LOG(LogTemp, Log, TEXT("PoissonDisc2D: Starting generation with parameters: %f, %f, %f, %d."), fWidth, fHeight, fSampleDistance, iMaxNewPoints);

	// Calculate cell size, cell count and sample count.
	dCellSize = fSampleDistance / sqrt(2.0); iCellsX = ceil(fWidth / dCellSize); iCellsY = ceil(fHeight / dCellSize); iCells = iCellsX * iCellsY;
	UE_LOG(LogTemp, Log, TEXT("PoissonDisc2D: Calculated Grid of size %d, %d using cell size %f (Total cells: %d)."), iCellsX, iCellsY, dCellSize, iCells);
	
	// Create Arrays containing our elements temporarily.
	v2DSamples = new FVector2D*[iCells];
	v2DList = new TDoubleLinkedList<FVector2D*>();
	for (unsigned int n = 0; n < iCells; ++n)
		v2DSamples[n] = NULL;

	// Generate starting point at random position. and insert it into the data structure.
	v2DSample = new FVector2D(((float)rand() / (float)RAND_MAX) * fWidth, ((float)rand() / (float)RAND_MAX) * fHeight);
	iCellX = (int)(v2DSample->X / dCellSize); iCellY = (int)(v2DSample->Y / dCellSize);	iCell = iCellX + (iCellY * iCellsX);
	v2DSamples[iCell] = v2DSample; v2DList->AddTail(v2DSample);
	UE_LOG(LogTemp, Log, TEXT("PoissonDisc2D: Created sample at %f, %f in cell %d, %d."), v2DSample->X, v2DSample->Y, iCellX, iCellY);
	
	// Lots of commented out code.

	// Create output array of samples and fill it.
	TArray<FVector2D>* v2DOutputArray = new TArray<FVector2D>();
	for (unsigned int n = 0; n < iCells; ++n) {
		if (v2DSamples[n] != NULL)
			v2DOutputArray->Add(*v2DSamples[n]);
	}

	// Destroy temporary arrays.
	delete v2DSamples; delete v2DList;

	// Return created output array.
	return *(v2DOutputArray);
}

Why don’ you try debuging to see whee it crashing or atleast see logs?

The last entry in the logs is “Lighting”, even when i define custom log categories. And in debug mode the editor just closes.
Here’s the log from the latest run in debug mode: Log file open, 08/31/14 13:27:08LogInit:Display: Running engine for game: Mons - Pastebin.com

Nevermind, I’m just stupid. It created a dump file and i found out why it is crashing without a message. Though I still wonder if i need to manually clean up the returned pointers to FVector2D, or if i can just keep it this way.

#Pass by Reference

You should definitely be passing by Reference!

 static TArray<FVector2D> Generate2D(float fWidth = 1.0f, float fHeight = 1.0f, float fSampleDistance = 0.5f, int32 iMaxNewPoints = 30);

becomes

 static void Generate2D(TArray<FVector2D>& v2DOutputArray, float fWidth = 1.0f, float fHeight = 1.0f, float fSampleDistance = 0.5f, int32 iMaxNewPoints = 30);

You dont have to use new inside of the function any more for this output array

This should make your life much easier :slight_smile:

1 Like

Thanks, that indeed made my life much easier. It also works now without crashing the editor.