Arrays
An array holds a fixed number of values of the same type, decided in advance. The length can’t change afterward.
List and Dictionary aren’t available, so arrays hold multiple values together.
Forms that compile (53)
Section titled “Forms that compile (53)”| Syntax | Description | Note |
|---|---|---|
new int[4] | Generation with a fixed length | |
new int[count] | Generation with the length from a variable | |
new int[] { 1, 2, 3 } | Generation with listed initial values | |
int[] a = { 1, 2, 3 } | Initialization at declaration | |
new[] { 1, 2, 3 } | Inferring the element type | |
var a = new int[4] | Inferring the variable’s type | |
new int[4][] | Generating a jagged array | |
new int[][] { ... } | Initializing a jagged array | |
new int[2][][] | 3 levels of nesting | |
new int[2][][][] | 4 levels of nesting | |
new int[4, 4] | Generating a 2D array | Each element is boxed on the way in and out, so it takes more instructions than a one-dimensional array or an array of arrays of the same size. |
new string[4] | Element is a reference type | |
new Vector3[4] | Element is a struct | |
new GameObject[4] | Element is a runtime type | |
a[0] = 10 | Writing to an element | |
int x = a[0] | Reading an element | |
a[0] += 10 | Compound assignment | |
a[0]++ | Increment and decrement | |
a[i] = 10 | Specifying the index with a variable | |
a[^1] | Index from the end | It points at the same position as a[a.Length - 1]. |
a[1..] | Slicing a range | The original array is unchanged. |
points[0].x = 5f | Writing to a field of a struct element | |
Vector3 v = points[0] | Retrieving a struct element | |
a.Length | Getting the element count | |
a.Rank | Getting the rank | |
a.GetLength(0) | Getting the length of a given dimension | |
a.GetValue(0) | Reading regardless of type | |
a.SetValue(9, 0) | Writing regardless of type | |
a.Clone() | Cloning | |
System.Array.Copy(a, b, 3) | Copying to another array | |
System.Array.Clear(a, 0, 3) | Clearing a range | |
Grow(ref a) | Passing to a method of your own with ref | What you may pass is a local variable or a parameter of the calling method. |
System.Array.Sort(a) | Sorting | It works only on an array of a value type that can be ordered — int and float can, Vector3 cannot. |
System.Array.Reverse(a) | Reversing the order | It works only on arrays whose elements are value types. |
System.Array.IndexOf(a, 8) | Finding an element | It is -1 when there is none. LastIndexOf, which searches from the back, takes the same shape. It works only on arrays whose elements are value types. |
System.Array.BinarySearch(a, 20) | Searching a sorted array | It works only on an array of a value type that can be ordered. |
foreach (int v in a) | Iterating all elements | |
foreach (var v in a) | Iteration with the type inferred | |
for (int i = 0; i < a.Length; i++) | Iteration by index | |
private int[] buffer | Holding as a field | |
public GameObject[] targets | Assigning via a public field | |
[UdonSynced] private int[] values | Sync | |
Fill(scores) | Passing as an argument | |
params int[] values | Receiving as a variable number of arguments | |
int[] Make() | Returning as a return value | |
int[] alias = original | Assigning to another variable | |
a == null | Comparing with null | |
object boxed = scores | Storing in object | |
object[] boxes = names | Assigning to an array with a wider element type | It only passes in the direction that widens the element type. |
boxes[0] = scores | Storing in an element of an object array | |
other.SetProgramVariable("values", a) | Writing by specifying a name | |
(int[])other.GetProgramVariable("values") | Reading by specifying a name | |
SendCustomNetworkEvent(..., a) | Specifying as an argument to a network event |
Forms that don’t compile (15)
Section titled “Forms that don’t compile (15)”| Syntax | Description | Error | Reason |
|---|---|---|---|
int[,,] a = new int[2, 2, 2]; | Multidimensional arrays with 3 or more dimensions | TUKI0001 | not yet |
new int[2, 2] { { 1, 2 }, { 3, 4 } } | Listed initial values for a 2D array | TUKI0001 | undecided |
foreach (int v in grid) | Iterating a 2D array | TUKI0001 | by design |
Bump(ref a[0]) | Passing an element with ref | TUKI0001 | by design |
boxed is Vector3[] | Type test for whether something is an array type | TUKI0001 | not yet |
System.Array.Resize(ref a, 5) | Changing the length | TUKI0001 | undecided |
System.Array.Sort(targets) | Element types that sorting and searching do not take | TUKI0001 | by design |
new List<int>() | List (variable-length sequence) | TUKI0102, TUKI0101 | runtime |
new Dictionary<int, int>() | Dictionary | TUKI0102, TUKI0101 | runtime |
using System.Linq; | LINQ query expressions | CS0234 (the namespace itself doesn’t exist) | runtime |
foreach (int v in list) | Iterating something other than an array | TUKI0001, TUKI0101, TUKI0102 | runtime |
s[^1] | Index from the end of a string | TUKI0001 | not yet |
points[1..] | Slicing an array of a type you declared yourself | TUKI0001 | not yet |
System.Index i = 0; | A type that represents a position | TUKI0102, TUKI0101, TUKI0099 | runtime |
System.Range r = 0..1; | A type that represents a range | TUKI0102, TUKI0099 | runtime |
Forms to use instead
Section titled “Forms to use instead”| Form you want to use | Alternative |
|---|---|
| List | An array sized larger than needed, plus a variable for how many are in use |
| Dictionary | If the key is a small integer or an enum, an array indexed by the key. Otherwise, hold a key array and a value array as a pair and search through them in order. |
| Arrays with 3 or more dimensions | A jagged array (int[2][][]), or a single array using z * w * h + y * w + x |
| Iterating a 2D array | A nested for using GetLength(0) and GetLength(1) |
Passing an element with ref or out | Take it into a local variable first, then assign that to the element |
| Element types that sorting and searching do not take | Pull the indexes or the compared values into an array of a value type that can be ordered, sort that, and reorder the original array with the result |
Declaration and generation
Section titled “Declaration and generation”Generation with a fixed length
Section titled “Generation with a fixed length”using UnityEngine;using Tsukimi;
public class ArraysDeclareFixedLength : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[4]; }}Generation with the length from a variable
Section titled “Generation with the length from a variable”using UnityEngine;using Tsukimi;
public class ArraysDeclareVariableLength : TsukimiBehaviour{ public int count = 4;
private int[] scores;
void Start() { scores = new int[count]; scores[0] = 10; }}Generation with listed initial values
Section titled “Generation with listed initial values”using UnityEngine;using Tsukimi;
public class ArraysDeclareInitializer : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[] { 1, 2, 3 }; }}Initialization at declaration
Section titled “Initialization at declaration”You can omit new int[] when writing it at the same time as the declaration.
using UnityEngine;using Tsukimi;
public class ArraysDeclareShortInitializer : TsukimiBehaviour{ private int[] scores = { 1, 2, 3 };
void Start() { scores[0] = 10; }}Inferring the element type
Section titled “Inferring the element type”using UnityEngine;using Tsukimi;
public class ArraysDeclareInferredInitializer : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new[] { 1, 2, 3 }; }}Inferring the variable’s type
Section titled “Inferring the variable’s type”using UnityEngine;using Tsukimi;
public class ArraysDeclareVar : TsukimiBehaviour{ private int[] scores;
void Start() { var made = new int[4]; made[0] = 10; scores = made; }}Generating a jagged array
Section titled “Generating a jagged array”using UnityEngine;using Tsukimi;
public class ArraysDeclareJagged : TsukimiBehaviour{ private int[][] grid;
void Start() { grid = new int[4][]; Debug.Log(grid[0] == null); // => true grid[0] = new int[4]; grid[0][0] = 1; Debug.Log(grid[0][0]); // => 1 }}Initializing a jagged array
Section titled “Initializing a jagged array”using UnityEngine;using Tsukimi;
public class ArraysDeclareJaggedInitializer : TsukimiBehaviour{ private int[][] grid;
void Start() { grid = new int[][] { new int[] { 1, 2 }, new int[] { 3 } }; grid[0][0] = 10; }}3 levels of nesting
Section titled “3 levels of nesting”using UnityEngine;using Tsukimi;
public class ArraysDeclareJaggedThreeLevels : TsukimiBehaviour{ private int[][][] deep;
void Start() { deep = new int[2][][]; deep[0] = new int[2][]; deep[0][0] = new int[2]; deep[0][0][0] = 1; }}4 levels of nesting
Section titled “4 levels of nesting”Up to 4 levels have been confirmed.
using UnityEngine;using Tsukimi;
public class ArraysDeclareJaggedFourLevels : TsukimiBehaviour{ private int[][][][] deep;
void Start() { deep = new int[2][][][]; deep[0] = new int[2][][]; deep[0][0] = new int[2][]; deep[0][0][0] = new int[2]; deep[0][0][0][0] = 1; Debug.Log(deep[0][0][0][0]); // => 1 }}Generating a 2D array
Section titled “Generating a 2D array”Up to two dimensions.
using UnityEngine;using Tsukimi;
public class ArraysMultidimensional : TsukimiBehaviour{ void Start() { int[,] grid = new int[4, 4]; grid[0, 0] = 1; Debug.Log(grid[0, 0]); // => 1 Debug.Log(grid.GetLength(1)); // => 4 }}Element is a reference type
Section titled “Element is a reference type”using UnityEngine;using Tsukimi;
public class ArraysElementReferenceType : TsukimiBehaviour{ private string[] names;
void Start() { names = new string[4]; Debug.Log(names[0] == null); // => true names[0] = "hello"; Debug.Log(names[0]); // => "hello" }}Element is a struct
Section titled “Element is a struct”using UnityEngine;using Tsukimi;
public class ArraysElementStructType : TsukimiBehaviour{ void Start() { Vector3[] points = new Vector3[4]; points[0] = new Vector3(1f, 2f, 3f); }}Element is a runtime type
Section titled “Element is a runtime type”Types the runtime exposes can also be elements.
using UnityEngine;using Tsukimi;
public class ArraysElementObjectType : TsukimiBehaviour{ void Start() { GameObject[] targets = new GameObject[4]; targets[0] = gameObject; }}Element access
Section titled “Element access”Writing to an element
Section titled “Writing to an element”using UnityEngine;using Tsukimi;
public class ArraysWriteElement : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[4]; scores[0] = 10; }}Reading an element
Section titled “Reading an element”using UnityEngine;using Tsukimi;
public class ArraysReadElement : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; int first = scores[0]; Debug.Log(first); // => 1 }}Compound assignment
Section titled “Compound assignment”using UnityEngine;using Tsukimi;
public class ArraysCompoundAssign : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[4]; scores[0] += 10; }}Increment and decrement
Section titled “Increment and decrement”using UnityEngine;using Tsukimi;
public class ArraysIncrementElement : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[4]; scores[0]++; }}Specifying the index with a variable
Section titled “Specifying the index with a variable”using UnityEngine;using Tsukimi;
public class ArraysIndexByVariable : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[] { 1, 2, 3 }; int i = 1; scores[i] = 10; }}Index from the end
Section titled “Index from the end”^1 is the last element.
using UnityEngine;using Tsukimi;
public class ArraysIndexFromEnd : TsukimiBehaviour{ void Start() { int[] a = { 1, 2, 3 }; Debug.Log(a[^1]); // => 3 }}Slicing a range
Section titled “Slicing a range”A new array is created and the elements in the given range are copied into it.
using UnityEngine;using Tsukimi;
public class ArraysRangeSlice : TsukimiBehaviour{ void Start() { int[] a = { 1, 2, 3 }; int[] b = a[1..]; Debug.Log(b.Length); // => 2 Debug.Log(b[0]); // => 2 }}Writing to a field of a struct element
Section titled “Writing to a field of a struct element”using UnityEngine;using Tsukimi;
public class ArraysStructElementFieldWrite : TsukimiBehaviour{ void Start() { Vector3[] points = new Vector3[4]; points[0].x = 5f; }}Retrieving a struct element
Section titled “Retrieving a struct element”What is assigned to the variable is a copy, so modifying that variable doesn’t change the array’s element.
using UnityEngine;using Tsukimi;
public class ArraysCopyStructElement : TsukimiBehaviour{ void Start() { Vector3[] points = new Vector3[4]; Vector3 copy = points[0]; copy.y = 9f; Debug.Log(copy); // => runtime value }}Members
Section titled “Members”Getting the element count
Section titled “Getting the element count”using UnityEngine;using Tsukimi;
public class ArraysLength : TsukimiBehaviour{ void Start() { int[] scores = new int[4]; int n = scores.Length; Debug.Log(n); // => 4 }}Getting the rank
Section titled “Getting the rank”using UnityEngine;using Tsukimi;
public class ArraysRank : TsukimiBehaviour{ void Start() { int[] scores = new int[4]; int r = scores.Rank; Debug.Log(r); // => 1 }}Getting the length of a given dimension
Section titled “Getting the length of a given dimension”using UnityEngine;using Tsukimi;
public class ArraysGetLength : TsukimiBehaviour{ void Start() { int[] scores = new int[4]; int n = scores.GetLength(0); Debug.Log(n); // => 4 }}Reading regardless of type
Section titled “Reading regardless of type”The return value is object, so a conversion is needed to use it.
using UnityEngine;using Tsukimi;
public class ArraysGetValue : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; object first = scores.GetValue(0); Debug.Log(first); // => 1 }}Writing regardless of type
Section titled “Writing regardless of type”using UnityEngine;using Tsukimi;
public class ArraysSetValue : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[3]; scores.SetValue(9, 0); }}Cloning
Section titled “Cloning”The return value is object, so a conversion is needed to use it.
using UnityEngine;using Tsukimi;
public class ArraysClone : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; object copy = scores.Clone(); Debug.Log(copy); // => System.Object[] }}Copying to another array
Section titled “Copying to another array”using UnityEngine;using Tsukimi;
public class ArraysArrayCopy : TsukimiBehaviour{ private int[] destination;
void Start() { int[] source = new int[] { 1, 2, 3 }; destination = new int[3]; System.Array.Copy(source, destination, 3); }}Clearing a range
Section titled “Clearing a range”using UnityEngine;using Tsukimi;
public class ArraysArrayClear : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; System.Array.Clear(scores, 0, 3); }}Passing to your own method with ref
Section titled “Passing to your own method with ref”The array itself can be replaced.
using UnityEngine;using Tsukimi;
public class ArraysRefToUserMethod : TsukimiBehaviour{ private void Grow(ref int[] target) { int[] bigger = new int[target.Length + 1]; System.Array.Copy(target, bigger, target.Length); target = bigger; }
void Start() { int[] scores = new int[2]; Grow(ref scores); Debug.Log(scores.Length); // => 3 }}Sorting
Section titled “Sorting”Sorts in ascending order.
using UnityEngine;using Tsukimi;
public class ArraysArraySort : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 30, 10, 20 }; System.Array.Sort(scores); Debug.Log(scores[0]); // => 10 Debug.Log(scores[2]); // => 30 }}Reversing the order
Section titled “Reversing the order”Reverses the order.
using UnityEngine;using Tsukimi;
public class ArraysArrayReverse : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; System.Array.Reverse(scores); Debug.Log(scores[0]); // => 3 }}Finding an element
Section titled “Finding an element”Returns the position that was found.
using UnityEngine;using Tsukimi;
public class ArraysArrayIndexOf : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 5, 8, 8 }; Debug.Log(System.Array.IndexOf(scores, 8)); // => 1 Debug.Log(System.Array.LastIndexOf(scores, 8)); // => 2 Debug.Log(System.Array.IndexOf(scores, 99)); // => -1 }}Searching a sorted array
Section titled “Searching a sorted array”Unless the array has already been sorted, the position that comes back is not correct.
using UnityEngine;using Tsukimi;
public class ArraysArrayBinarySearch : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 10, 20, 30 }; Debug.Log(System.Array.BinarySearch(scores, 20)); // => 1 }}Iteration
Section titled “Iteration”Iterating all elements
Section titled “Iterating all elements”using UnityEngine;using Tsukimi;
public class ArraysForeach : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; int sum = 0; foreach (int v in scores) { sum += v; } Debug.Log(sum); // => 6 }}Iteration with the type inferred
Section titled “Iteration with the type inferred”using UnityEngine;using Tsukimi;
public class ArraysForeachVar : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; int sum = 0; foreach (var v in scores) { sum += v; } Debug.Log(sum); // => 6 }}Iteration by index
Section titled “Iteration by index”using UnityEngine;using Tsukimi;
public class ArraysForIndex : TsukimiBehaviour{ void Start() { int[] scores = new int[] { 1, 2, 3 }; int sum = 0; for (int i = 0; i < scores.Length; i++) { sum += scores[i]; } Debug.Log(sum); // => 6 }}Storage
Section titled “Storage”Holding as a field
Section titled “Holding as a field”using UnityEngine;using Tsukimi;
public class ArraysFieldPrivate : TsukimiBehaviour{ private int[] buffer;
void Start() { buffer = new int[16]; buffer[0] = 10; }}Assigning via a public field
Section titled “Assigning via a public field”A public field appears in the Inspector, and you can set its value there.
using UnityEngine;using Tsukimi;
public class ArraysFieldPublic : TsukimiBehaviour{ public GameObject[] targets;
void Start() { targets[0] = gameObject; }}If you don’t specify a sync method, it uses the default method.
using UnityEngine;using Tsukimi;
public class ArraysFieldSynced : TsukimiBehaviour{ [UdonSynced] private int[] values = new int[4];
void Start() { values[0] = 10; RequestSerialization(); }}Passing as an argument
Section titled “Passing as an argument”using UnityEngine;using Tsukimi;
public class ArraysPassAsArgument : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[] { 1, 2, 3 }; Fill(scores); }
private void Fill(int[] target) { target[0] = 10; }}Receiving as a variable number of arguments
Section titled “Receiving as a variable number of arguments”using UnityEngine;using Tsukimi;
public class ArraysParamsParameter : TsukimiBehaviour{ void Start() { int total = Total(1, 2, 3); Debug.Log(total); // => 6 }
private int Total(params int[] values) { int sum = 0; for (int i = 0; i < values.Length; i++) { sum += values[i]; } return sum; }}Returning as a return value
Section titled “Returning as a return value”using UnityEngine;using Tsukimi;
public class ArraysReturnFromMethod : TsukimiBehaviour{ private int[] scores;
void Start() { scores = Make(); scores[0] = 10; }
private int[] Make() { return new int[4]; }}Assigning to another variable
Section titled “Assigning to another variable”using UnityEngine;using Tsukimi;
public class ArraysAliasSharesReference : TsukimiBehaviour{ void Start() { int[] original = new int[4]; int[] alias = original; alias[0] = 10; Debug.Log(original[0]); // => 10 }}Comparing with null
Section titled “Comparing with null”using UnityEngine;using Tsukimi;
public class ArraysCompareToNull : TsukimiBehaviour{ private int[] buffer;
void Start() { Debug.Log(buffer == null); // => true if (buffer == null) { buffer = new int[4]; } Debug.Log(buffer.Length); // => 4 }}Storing in object
Section titled “Storing in object”An array is a reference, so it goes into an object variable as is.
using UnityEngine;using Tsukimi;
public class ArraysStoreInObject : TsukimiBehaviour{ void Start() { int[] scores = new int[4]; object boxed = scores; Debug.Log(boxed); // => System.Object[] }}Assigning to an array with a wider element type
Section titled “Assigning to an array with a wider element type”A string[] can be treated as an object[].
using UnityEngine;using Tsukimi;
public class ArraysCovariantAssign : TsukimiBehaviour{ void Start() { string[] names = new string[4]; object[] boxes = names; Debug.Log(boxes.Length); // => 4 }}Storing in an element of an object array
Section titled “Storing in an element of an object array”using UnityEngine;using Tsukimi;
public class ArraysElementInObjectArray : TsukimiBehaviour{ private object[] boxes;
void Start() { int[] scores = new int[4]; boxes = new object[2]; boxes[0] = scores; }}Passing to other Behaviours
Section titled “Passing to other Behaviours”Writing by specifying a name
Section titled “Writing by specifying a name”Specify the other Behaviour’s variable name as a string to write the array.
using UnityEngine;using Tsukimi;
public class ArraysSetProgramVariable : TsukimiBehaviour{ public TsukimiBehaviour other;
void Start() { int[] scores = new int[] { 1, 2, 3 }; other.SetProgramVariable("values", scores); }}Reading by specifying a name
Section titled “Reading by specifying a name”The return value is object, so a conversion is needed to receive it.
using UnityEngine;using Tsukimi;
public class ArraysGetProgramVariable : TsukimiBehaviour{ public TsukimiBehaviour other;
void Start() { int[] got = (int[])other.GetProgramVariable("values"); Debug.Log(got.Length); }}Specifying as an argument to a network event
Section titled “Specifying as an argument to a network event”If you add [NetworkCallable] to the receiving method, you can pass an array as an argument.
using UnityEngine;using Tsukimi;using VRC.Udon.Common.Interfaces;using VRC.SDK3.UdonNetworkCalling;
public class ArraysSendAsNetworkEvent : TsukimiBehaviour{ private int[] scores;
void Start() { scores = new int[] { 1, 2, 3 }; SendCustomNetworkEvent(NetworkEventTarget.All, nameof(Receive), scores); }
[NetworkCallable] public void Receive(int[] values) { Debug.Log(values.Length); }}