Replicating a 2D dynamic array

Hello everyone…

I have a 2d dynamic array of structures.

What is the best way to replicate it? I went through this https://docs.unrealengine.com/latest/INT/Gameplay/Networking/Replication/Implementation/DynamicArrays/index.html#implementation but this doesn’t say anything specifically about 2D arrays.

Another thing I am thinking about is using a Client RPC function call to update the value of each slot.

The data the structure contains is really small(3-4 ints at max). So any one knows how does 2D dynamic arrays and replication work together?

How to Make BP Friendly 2D Arrays That Replicate

Dear Envenger,

I have a full code sample for 2D BP-friendly / replicating arrays here:


**New Code Sample Just For You**

To create a UPROPERTY() compatible 2D array you should actually make a struct

Then you can also use RepRetry

Also make sure to make **each member a UPROPERTY(**) in the ustruct or it wont get replicated

Full code sample for you, that I just wrote:



```



//You dont necessarily need this Data Unit struct if your fundamental data type is simple like float or FString.
USTRUCT(BlueprintType)
struct FYourDataUnit
{
	GENERATED_USTRUCT_BODY()

	//Whatever your core data of the array is, make sure you use UPROPERTY()
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="2D Array")
	FVector Location;
	
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="2D Array")
	FLinearColor FlowerColor;

        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="2D Array")
	uint8 NumPetals;

	FYourDataUnit()
       {
           //always set defaults for ustruct simple data types.
           NumPetals = 5;
           Location = FVector::ZeroVector;
           FlowerColor = FLinearColor::Red;
       }
};

USTRUCT(BlueprintType)
struct FYourDataRow
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="2D Array")
	TArray<FYourDataUnit> Cols;
	
        //or could be using a simple data type instead of a Data Unit Struct
        //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="2D Array")
	//TArray<FString> Cols;

	FYourDataRow(){}
};

USTRUCT(BlueprintType)
struct FYourDataArray
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="2D Array")
	TArray<FYourDataRow> Rows;
	
	FYourDataArray(){}
};


```



Replication



//And you can replicate it like this
UPROPERTY(Replicated,RepRetry)
FYourDataArray Your2DDataArray;



**Access**



```


//then you can access a member like this
Your2DDataArray.Rows[x].Cols[y];


```



Benefits

While this might look a bit cumbersome it results in an entirely BP-friendly 2D array that can also be replicated over the network.

I was told by Epic to use this multi-ustruct arrangement for a BP-friendly 2D array when I asked about 2D arrays during the UE4 Beta.

It’s worked great for me :slight_smile:

My test case was large 2D Maze generation and performance was great.

Rama

Hello Rama, thanks for the reply :slight_smile:

I have done something exactly similar.


USTRUCT(BlueprintType)
struct FStorageUnit
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY()
	FItemStruct ItemStruct;

	FStorageUnit()
	{

	}

	FStorageUnit(const FItemStruct NewItemStruct)
	{
		ItemStruct = NewItemStruct;
	}
};

USTRUCT(BlueprintType)
struct FStorageRow
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY()
	TArray<FStorageUnit> Columns;

	void AddNewColumn()
	{
		Columns.Add(FStorageUnit());
	}
	//default properties
	FStorageRow(){}
};

USTRUCT(BlueprintType)
struct FStorageArray
{
	GENERATED_USTRUCT_BODY()

        UPROPERTY()
	TArray<FStorageRow> Rows;

	void AddNewRow()
	{
		Rows.Add(FStorageRow());
	}

	void AddUninitialized(const int8 RowCount, const int8 ColCount)
	{
		//Add Rows
		for (int32 i = 0; i < RowCount; i++)
		{
			AddNewRow();
		}
		//Add Columns
		for (int8 i = 0; i < RowCount; i++)
		{
			for (int8 j = 0; j < ColCount; j++)
			{
				Rows*.AddNewColumn();
			}
		}
	}
	FStorageArray()
	{}
};

/** A simple 2d int32 structure */
USTRUCT()
struct FStorageLoc
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY()
	int8 RowNum;

	UPROPERTY()
	int8 ColNum;

	FStorageLoc()
	{
		RowNum = -1;
		ColNum = -1;
	}

	FStorageLoc(int8 Row, int8 Col)
	{
		RowNum = Row;
		ColNum = Col;
	}
};

But I think when replicating a structure, the whole structure is replicated. So wont it be a bit less efficient network wise?

I’m not entirely sure, but I think yes. though since it’s only int8’s you’ll probably be fine ? Idk exactly. I’d also like to know for sure.

Well not int8s… The whole Array will be replicated each time a element in the array is changed. That’s something i want to avoid.

I was just saying your data type is small. Meaning the amount of elements in row or col, is limited. It would be allot different replicating a 2d array of say int64 in rol or col.

You might need to do your own change management implemented with replicated functions.

That is, setting the array members through functions that signal that the member needs to also be replicated. You could either do this with every single change, or batch the changes and send several at once.

Hiya, I realize this is old, but I wanted to add something that is SUPER IMPORTANT that I just ran into.

If you are going to replicate an array you should be VERY VERY careful about how you remove your items. RemoveAtSwap or RemoveAllSwap should always be used in preference to RemoveAt and RemoveAll. If you have a large array where you will be removing elements with any frequency, it’s super important that you are not letting the array dynamically rearrange itself because you will kill your performance in a networked game. One thing you can do simply is to just let your array changes be sent by RPC rather than by replication (probably the best way), but just worth being aware of.

My array size doesn’t change. Only the elements present inside it change so it quite good…

This helped me to optimize my TArray code a bit.