Announcement

Collapse
No announcement yet.

Replicating a 2D dynamic array

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    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...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?
    Last edited by envenger; 03-01-2015, 04:43 AM.

    #2
    How to Make BP Friendly 2D Arrays That Replicate

    Dear Envenger,

    I have a full code sample for 2D BP-friendly / replicating arrays here:
    https://forums.unrealengine.com/show...ll=1#post27139

    ~~~

    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:

    Code:
    //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

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

    Access

    Code:
    //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

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

    Rama
    Last edited by Rama; 03-01-2015, 09:25 AM.
    UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

    ♥ Rama

    Comment


      #3
      Hello Rama, thanks for the reply

      I have done something exactly similar.

      Code:
      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[i].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?
      Last edited by envenger; 03-01-2015, 01:26 PM.

      Comment


        #4
        Originally posted by envenger View Post
        Hello Rama, thanks for the reply

        I have done something exactly similar.

        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.
        Youtube
        Machine Learning C++ Plugin
        Lindenmayer System C++ Plugin

        Comment


          #5
          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.

          Comment


            #6
            Originally posted by envenger View Post
            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.
            Youtube
            Machine Learning C++ Plugin
            Lindenmayer System C++ Plugin

            Comment


              #7
              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.

              Comment


                #8
                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.

                Comment


                  #9
                  Originally posted by mrooney View Post
                  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.
                  https://www.unrealengine.com/blog/op...or-performance

                  Comment

                  Working...
                  X