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
structis a reference type here — storing the same struct in two list slots shares it; reassign withnewfor an independent copy.- Building a new
List<T>every frame allocates. In a hotUpdateloop, reuse one list andClear()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.