Skip to content

Collections

NexusScript ships the everyday .NET collections. You write them with normal C# syntax — list.Add(x), list[i], foreach, dict[key] — and the compiler maps that to the engine bindings. This page is about what's available and the few gotchas.

List

A growable array. The workhorse — rosters, spawn pools, queues of work.

List<string> names = new List<string>();
names.Add("Ada");
names.Insert(0, "Grace");
string first = names[0];          // indexer
names[0] = "Grace H.";            // set
int n = names.Count;
bool has = names.Contains("Ada");
names.Remove("Ada");
names.RemoveAt(0);
foreach (string s in names) Debug.Log(s);
names.Sort();
names.Reverse();
string[] arr = names.ToArray();

Add · Insert · Remove · RemoveAt · Clear · Contains · IndexOf · LastIndexOf · Find · FindIndex · Sort · Reverse · ToArray · Count · [i].

Dictionary

Key → value lookups (scores by player id, config by name).

Dictionary<string, int> score = new Dictionary<string, int>();
score["ada"] = 10;                       // add/overwrite
score["ada"] += 5;
if (score.ContainsKey("ada")) { }
int v;
if (score.TryGetValue("ada", out v)) Debug.Log(v);   // safe read
score.Remove("ada");
foreach (string key in score.Keys) Debug.Log(key + " = " + score[key]);

[key] get/set · Add · Remove · Clear · ContainsKey · ContainsValue · TryGetValue · Keys · Values · Count.

TryGetValue over [key] for reads

Reading a missing key with dict[key] throws. Use TryGetValue (or guard with ContainsKey) when the key might not be present.

HashSet, Queue & Stack

HashSet<string> seen = new HashSet<string>();
if (seen.Add(playerId)) FirstVisit(playerId);   // Add returns false if already present
seen.UnionWith(other); seen.IntersectWith(other); // set algebra

Queue<GameObject> spawnQueue = new Queue<GameObject>();
spawnQueue.Enqueue(obj);
GameObject next = spawnQueue.Dequeue();          // FIFO
GameObject peek = spawnQueue.Peek();

Stack<string> history = new Stack<string>();
history.Push("room1");
string back = history.Pop();                     // LIFO
  • HashSet — unique membership: Add · Remove · Contains · UnionWith · IntersectWith · ExceptWith · IsSubsetOf · Overlaps · Count.
  • Queue (FIFO) — Enqueue · Dequeue · Peek · Contains · Clear · Count.
  • Stack (LIFO) — Push · Pop · Peek · Contains · Clear · Count.

Filtering and transforming

LINQ method chains are not available

list.Where(…), .Select(…), .Any(…), .OrderBy(…), .ToList() and the rest of the LINQ chain do not compile. Filter and transform with a foreach — it is a couple more lines, allocates less, and is the pattern every example on this wiki uses.

string[] players = Networking.GetPlayers();

// "Where" — filter into a new list
List<string> nearby = new List<string>();
foreach (string id in players)
{
    if (Player.IsInRange(myId, id, 10f)) nearby.Add(id);
}

// "Any" — stop at the first match
bool anyClose = false;
foreach (string id in players)
{
    if (Player.IsInRange(myId, id, 2f)) { anyClose = true; break; }
}

// "Select" — project into a new list
List<Vector3> positions = new List<Vector3>();
foreach (string id in nearby) positions.Add(Player.GetPosition(id));

// "OrderBy" — track the best as you go (no sort needed for "the closest one")
string closest = "";
float bestDist = float.MaxValue;
foreach (string id in nearby)
{
    float d = Player.GetDistanceTo(myId, id);
    if (d < bestDist) { bestDist = d; closest = id; }
}

A lambda you store works and is callable directly, which keeps a reusable test readable:

Func<string, bool> isClose = id => Player.IsInRange(myId, id, 10f);
foreach (string id in players) if (isClose(id)) nearby.Add(id);

Things to remember from the language subset

  • struct is a reference type here — storing the same struct in two list slots shares it; reassign with new for an independent copy.
  • Building a new List<T> every frame allocates. In a hot Update loop, reuse one list and Clear() it, or track the running best (as in the "closest" example) instead of collecting at all.

Tuples

Tuples are the lightweight way to group or return a few values without a class, and they work as collection elements:

var points = new List<(int, int)>();
points.Add((3, 4));
int x = points[0].Item1;

var spawns = new Dictionary<string, (int count, int total)>();
spawns["wave1"] = (5, 100);
int n = spawns["wave1"].count;      // named access works through the collection

Tuples have their own full page — literals, named elements, deconstruction, switch patterns, equality, and more.

Tuples — the complete guide.

Quick reference

Type Calls
Tuples (a, b) · t.Item1/named t.count · var (x,y)=t / (a,b)=t · (int,int) F() · ==/!= · t switch { (0,0)=>… } / case (0,_): · List<(int,int)>
List<T> Add · Insert · Remove · RemoveAt · Clear · Contains · IndexOf · Find · Sort · Reverse · ToArray · Count · [i]
Dictionary<K,V> [key] · Add · Remove · ContainsKey · TryGetValue · Keys · Values · Count
HashSet<T> Add · Remove · Contains · UnionWith · IntersectWith · ExceptWith · Count
Queue<T> / Stack<T> Enqueue/Dequeue/Peek · Push/Pop/Peek
Filter / transform a foreach that builds a new list (LINQ method chains are not available)

→ Back to Basics for the full language subset, or Storage to persist what you collect.