You've made an Udon script and got a Cube moving. But you were copying sample code, and what it says is still unclear.
There isn't that much to learn. Most world gimmicks are made from just four parts.
This article uses those four in order, inside a single example. We'll build a button that changes three lights' color on each press and returns to the start after three.
What You'll Learn
- Variables: boxes that hold values
- if: a fork in the road, yes or no
- for: repeating the same thing
- Functions: giving a name to a piece of logic
Start from being able to create scripts, from getting started with UdonSharp.
It's made from four parts
Think of programs as incantations and the amount to learn looks infinite. In practice there are only four kinds of thing going on.

| Part | What it does | In one word |
|---|---|---|
| Variable | Stores a value | A box |
| if | Forks by condition | A fork in the road |
| for | Repeats the same thing | Repetition |
| Function | Names a piece of logic | A named procedure |
Combine these four and you can write doors, lighting, and counters.
New gimmicks can be thought through within these four too. What do I store, where does it fork, what do I repeat, where do I split it. Answer those four and the code takes shape naturally.
Looking at them one at a time
Variables: boxes that hold values
A variable is a box. You put a value in and later take it out or overwrite it.

int pressCount = 0; // Made a "box for whole numbers" and put 0 in it
int is "the kind of box," pressCount is "the box's name," and 0 is "the value it starts with."
Boxes have kinds. Text doesn't go in a whole-number box.
| Written as | What it holds | Examples |
|---|---|---|
int | Whole numbers | 0 3 -5 |
float | Decimals | 0.5f 3.14f |
bool | Yes / no | true false |
string | Text | "Opened" |
The f on float values is a C# rule. Forgetting it gives an error, but the error tells you, so don't worry about it.
A box's contents can be changed as often as you like.
pressCount = pressCount + 1; // Add 1 to what's in there and put it back
= doesn't mean "equals" — it means "put the thing on the right into the box on the left." That's the first hurdle, so keep it in mind.
if: a fork in the road, yes or no
An if is a fork. If the condition is yes, the inside runs; if no, it's skipped.

if (pressCount >= 3)
{
pressCount = 0; // Three or more, so back to 0
}
What goes in the ( ) is a question whose answer is yes or no.
| Written as | Meaning |
|---|---|
a == b | Are a and b the same |
a != b | Are a and b different |
a > b / a < b | Is a greater than b, less than b |
a >= b / a <= b | At least, at most |
Two == is for comparing; one = is for putting in. Everyone gets this wrong once too.
To do something on "no" as well, add an else.
if (isOpen)
{
// What happens when open
}
else
{
// What happens when closed
}
for: repeating the same thing
A for is repetition. It runs the same logic a set number of times.

The first time you need a for in world building is when there are several of the same thing. Three lights, five chairs, four signs. You could write each one out, but adding more means rewriting.
for (int i = 0; i < 3; i++)
{
// This runs 3 times. i goes 0, 1, 2
}
The ( ) splits into three parts.
| Part | Meaning |
|---|---|
int i = 0 | Make a counting box, starting at 0 |
i < 3 | Repeat while this condition holds |
i++ | Add 1 after each pass |
i++ is shorthand for i = i + 1.
Combined with arrays, it shows its worth.
for (int i = 0; i < lights.Length; i++)
{
lights[i].enabled = true; // Turn every light on
}
lights.Length is "how many are in the array." Since you don't write the count as a number, adding lights doesn't require editing the code.
Functions: giving something a name
A function is a piece of logic with a name. It groups a procedure you use repeatedly so you can call it by name.

private void ApplyColor(Color color)
{
// Logic that applies the color
}
Reading it out:
| Part | Meaning |
|---|---|
private | Used only inside this script |
void | Returns no value when called |
ApplyColor | The name |
(Color color) | What you pass when calling it |
Calling it means just writing the name.
ApplyColor(Color.red);
There are two reasons to split things out. You avoid writing the same logic repeatedly. And the name becomes the explanation.
Seeing ApplyColor tells you "ah, it applies a color" without reading the body. Code is something you read back six months later. Naming things helps that version of you.
Hands-On: A button that changes color by press count
Build a button that changes three lights' color on each press and returns to the start after three. All four parts appear.
1. Place the lights and the button
In a scene with a floor, place the following.
| Name | How to make it, and settings |
|---|---|
Light1 Light2 Light3 | Point Light. (-2, 2.5, 3) (0, 2.5, 3) (2, 2.5, 3). Range 6, Mode "Realtime" |
ColorButton | Cube. (0, 1, 1), Scale (0.4, 0.4, 0.4) |

2. Write the code
In Assets/Scripts, choose "Create → U# Script" and make ColorCycleButton.
using UdonSharp;
using UnityEngine;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class ColorCycleButton : UdonSharpBehaviour
{
[SerializeField] private Light[] targetLights; // The three lights
[SerializeField] private Color[] colors; // Three colors
private int pressCount = 0; // (1) Variable
public override void Interact()
{
pressCount = pressCount + 1;
// (2) if: once it hits 3 or more, go back to the start
if (pressCount >= colors.Length)
{
pressCount = 0;
}
// (4) Call the function
ApplyColor(colors[pressCount]);
Debug.Log("[ColorCycle] color index " + pressCount);
}
// (4) Function: apply the color to every light
private void ApplyColor(Color color)
{
// (3) for: repeat for as many lights as there are
for (int i = 0; i < targetLights.Length; i++)
{
if (targetLights[i] == null) continue; // (2) if: skip empty slots
targetLights[i].color = color;
}
}
}
All four parts are gathered in one place.
| Number | Part | Where and what it does |
|---|---|---|
| (1) | Variable | Stores the press count in pressCount |
| (2) | if | Returns to 0 at 3 or more. Skips empty light slots |
| (3) | for | Repeats for as many lights as there are, applying the color to all |
| (4) | Function | Names the color-applying procedure ApplyColor |
continue means "skip this pass and go to the next." It keeps an empty light slot from erroring.
Because it uses colors.Length, growing to four colors requires no code change. Writing >= 3 would have. That's why you use Length.
3. Assign and confirm
Add a Udon Behaviour to ColorButton and set ColorCycleButton.
| Field | What to set |
|---|---|
| Target Lights | Set Size to 3 and drag in Light1 through Light3 |
| Colors | Set Size to 3 and set white, blue, and orange |
| Interaction Text | Change color |

Press Play and try it.
| Press | Light color | Console output |
|---|---|---|
| First | Blue (index 1) | color index 1 |
| Second | Orange (index 2) | color index 2 |
| Third | Back to white (index 0) | color index 0 |
| Fourth | Blue | color index 1 |
It returns to the start after three. That's proof the if is working.
Deliberately clear the Light3 assignment and press. No error, and only the remaining two change color. That's the continue if doing its job.
Common mistakes
Here are the first ones beginners hit. Everyone goes through all of them.
- Mixing up
=and==→ One to put in, two to compare - Forgetting
fon afloat→ Write0.5f, not0.5 - Forgetting
;→ Lines end with;. The error's line number sometimes points one line down - Mismatched
{ }→ Every open needs a close. The editor auto-indents, so suspect it when the indentation looks off - Going past the end of an array → An array of 3 has no
[3]. It runs0to2 - Misspelling a variable name → Case matters.
pressCountandpresscountare different things
Errors are a good thing. Failing silently is far more troublesome. Read the line number in the error message and suspect the area around it.
Bonus: Good to Know Up Front
- You don't have to memorize: Forget the syntax and you can look back at this article or code you wrote before. What to remember is just the framework: there are four parts
- Long names are fine:
pressCountreads better later thanpc. Cut the effort of reading, not the effort of typing - Write comments: Anything after
//doesn't execute. Writing down what something does helps you six months from now - Try small: Rather than writing it all at once, start by writing one
Debug.Logand running it. Growing something that works is faster - Arrays are next: We used them here, and variables and data types covers them in detail
Summary
Programs are made from four parts.
- Variables: boxes that hold values, and they have kinds
- if: forks by condition. Use
==to compare - for: repeats the same thing. Strong when paired with arrays
- Functions: name a piece of logic. The name becomes the explanation
The question to ask when building something new is: "What do I store, where does it fork, and what do I repeat?" Answer that and the shape of the code is already visible.
To learn value types in detail, go to variables and data types. To call logic selectively, go to methods and custom events.