【VRChat】Arrays and Data Structures: Design Techniques Without List/Dictionary

Created: 2025-12-19

How to use arrays for efficiently managing multiple data. Alternative implementations for List and Dictionary in an environment without generics support, and considerations for [UdonSynced] arrays.

Overview

As world creation becomes more advanced, the amount of data to handle increases. For example, managing all participating players' scores in a game, coordinates for multiple spawn points, or the state of each puzzle piece—managing these as individual separate variables is inefficient and not scalable.

Arrays become a powerful tool in such situations. By using arrays, you can group multiple data of the same type into one variable and manage/operate on them efficiently.

This article covers everything from basic array usage in UdonSharp to how to manage complex data under the constraint that C# standard data structures like List<T> and Dictionary<T, K> are not available.

1. Array Basics

An array is a series of elements of the same data type arranged with sequential indices. Indices start from 0.

Declaring Arrays

Declare by adding [] after the data type, like DataType[] arrayName;.

// Declare an int array
int[] scores;

// Declare a Transform array
public Transform[] spawnPoints;

// UdonSharpBehaviour arrays are also possible
public PlayerCard[] playerCards;

Initializing Arrays and Accessing Values

To use an array, you need to initialize it with a specified element count after declaration.

void Start()
{
    // Create an int array with 5 elements
    scores = new int[5];

    // Assign values to each element using indices
    scores[0] = 100;
    scores[1] = 85;
    scores[2] = 92;
    scores[3] = 78;
    scores[4] = 88;

    // Retrieve values using indices
    Debug.Log($"Second player's score: {scores[1]}"); // Output: 85

    // Public arrays can have size and contents set in Inspector
    // Teleport to the position of the first spawn point
    Networking.LocalPlayer.TeleportTo(spawnPoints[0].position, spawnPoints[0].rotation);
}

Combining with for Loops

The true power of arrays is revealed when combined with for loops. Get the element count with the array's Length property and repeatedly execute the same processing on all elements.

// Sum all players' scores
int totalScore = 0;
for (int i = 0; i < scores.Length; i++)
{
    totalScore += scores[i];
}
Debug.Log($"Total score: {totalScore}");

// --- Example of touring with delayed events ---
// Note: Since SendCustomEventDelayedSeconds cannot pass arguments,
// manage the index with a field like this

private int currentPointIndex = 0;

public void StartTour()
{
    currentPointIndex = 0;
    MoveToNextPoint();
}

public void MoveToNextPoint()
{
    if (currentPointIndex < spawnPoints.Length)
    {
        // Move to current point
        Debug.Log($"Moving to point {currentPointIndex}");
        currentPointIndex++;

        // If there's a next point, move there after 5 seconds
        if (currentPointIndex < spawnPoints.Length)
        {
            SendCustomEventDelayedSeconds(nameof(MoveToNextPoint), 5.0f);
        }
    }
}

2. Syncing Arrays

Arrays can also be made subject to network synchronization by adding the [UdonSynced] attribute. This allows all players in the instance to share the same array data.

[UdonSynced]
private int[] playerScores = new int[8];

public void UpdateScore(int playerId, int newScore)
{
    // Update score using playerId as index
    if (playerId >= 0 && playerId < playerScores.Length)
    {
        Networking.SetOwner(Networking.LocalPlayer, this.gameObject);
        playerScores[playerId] = newScore;
        RequestSerialization();
    }
}

public override void OnDeserialization()
{
    // Update UI etc. using the synced score array
    UpdateScoreboard();
}

Note: Syncing an entire array can result in large data amounts. Be particularly careful of network load when syncing arrays with many elements or frequently changing contents.

3. Advanced Data Structures in UdonSharp

In standard C#, convenient data structures like resizable List<T> and key-value pair Dictionary<T, K> are commonly used. However, since generics are not supported in UdonSharp, these cannot be used directly. However, by cleverly using arrays, you can replicate some of their functionality.

List Alternative: Array with Counter

Functionality like adding elements later, similar to lists, can be pseudo-implemented by pre-allocating a large array and managing how many elements are currently used with a separate int variable.

// Alternative to a list that can record up to 100 names
private string[] nameList = new string[100];
private int nameCount = 0;

public void AddName(string newName)
{
    // Only add if there's space in the array
    if (nameCount < nameList.Length)
    {
        nameList[nameCount] = newName;
        nameCount++;
    }
}

Dictionary<T, K> Alternative: Two Arrays

If you want to manage values (e.g., scores) corresponding to specific keys (e.g., player names) like a dictionary (associative array), prepare two arrays—one for keys and one for values—and associate them by using the same index.

// Alternative to dictionary associating player names with scores
private string[] playerNames = new string[8];
private int[] playerScores = new int[8];

// Get score by player name
public int GetScoreByName(string targetName)
{
    for (int i = 0; i < playerNames.Length; i++)
    {
        if (playerNames[i] == targetName)
        {
            return playerScores[i]; // Return score at corresponding index
        }
    }
    return -1; // If not found
}

This isn't an efficient method, but it's one approach to achieving dictionary-like functionality under UdonSharp's constraints.

Summary

  • Arrays are a fundamental data structure for handling multiple data of the same type together.
  • By combining arrays with for loops, you can efficiently write iterative processing over all elements.
  • Adding [UdonSynced] to arrays enables network synchronization of contents, but be mindful of data volume.
  • Since List<T> and Dictionary<T, K> cannot be used in UdonSharp, you need to pseudo-implement their functionality by combining arrays with other variables.
  • Since array size cannot be changed once created, design considerations like pre-allocating a larger size anticipating needed elements are required.

Mastering arrays is unavoidable when building complex systems like player management, item management, and stage management. Understand UdonSharp's constraints and master techniques for skillfully manipulating data using arrays.