Welcome back. You now know that a C# script is an asset which becomes a component when attached to a GameObject. This lesson focuses on the data that component holds: player speed, health, damage, fire rate, and other numbers that define how your arena game feels.
You will create a small tuning component, then use the Inspector to change its gameplay values without rewriting code. The important distinction is that code defines the rule and structure, while serialized fields provide per-object settings you can adjust as you test.
Variables: named, typed storage
A variable is a named place to store a value. Its type says what kind of value it can contain and what operations make sense for it.
A C# variable declaration generally has this form:
type variableName = startingValue;
For example:
int startingHealth = 100;
This line does four things:
intsays the value is a whole number.startingHealthis the variable’s descriptive name.=assigns a value.100is the initial value.- The semicolon ends the C# statement.
The initial assignment is called initialization. Later, you can replace the stored value without declaring it again:
int score = 0;
score = 10;
In Unity scripts, fields such as startingHealth are usually declared near the top of the class. They belong to that particular script component instance. If you attach the same script to two GameObjects, each GameObject gets its own stored values.
C# Variables And Functions in Unity! - Beginner Scripting Tutorial
Watch Unity’s C# Variables And Functions in Unity! – Beginner Scripting Tutorial for a quick visual introduction to declaring, initializing, inspecting, and changing a variable.
Watch declaration basics to see the distinction between declaring a variable and assigning its first value. Then watch using variables for a simple example of reading a value, multiplying it, and reassigning it during Play mode.
The types you will use constantly
For this game, three simple C# value types cover a great deal of gameplay data:
| Type | Stores | Good arena-game examples |
|---|---|---|
int | Whole numbers | health, score, number of lives, ammo |
float | Numbers that may have fractions | movement speed, cooldown duration, projectile speed |
bool | true or false | melee enabled, player alive, match over |
Use an int when fractional values would be meaningless. A player with 100 health who takes 25 damage has clean, discrete values. Use a float when a fraction is useful or expected: a movement speed of 4.5 units per second or a fire interval of 0.25 seconds.
In C#, a decimal number is assumed to be a more precise double unless you say otherwise. Since Unity gameplay values commonly use float, write an f after a decimal literal:
float moveSpeed = 5f;
float reloadTime = 1.25f;
Without the f, the compiler will reject assigning 5.0 directly to a float.
A bool is not a number. It represents a yes-or-no game state:
bool meleeEnabled = true;
bool matchOver = false;
C# keywords such as int, float, bool, true, and false are lowercase. By convention, field names use camelCase, beginning with a lowercase letter and capitalizing later words: moveSpeed, damagePerHit, and shotsPerSecond.
Learn C# in Unity - Complete Course for Beginners
Game Dev Beginner’s Learn C# in Unity – Complete Course for Beginners connects variable types and Inspector-visible fields to the structure of a MonoBehaviour script.
Watch script structure for where member variables sit in a Unity script and how float, bool, and int are used. Then watch field visibility for the reasoning behind private serialized fields. Finally, watch core operators, concentrating on comparisons, arithmetic, assignment, and the important caveat about integer division.
Turning values into gameplay calculations
Variables become useful when you combine them with operators. An operator is a symbol that assigns, changes, compares, or calculates values.
The basic arithmetic operators work as expected:
| Operator | Example | Gameplay use |
|---|---|---|
+ | baseDamage + bonusDamage | Add a temporary bonus |
- | currentHealth - damage | Calculate remaining health |
* | baseDamage * damageMultiplier | Scale damage |
/ | arenaWidth / moveSpeed | Calculate travel time |
% | shotNumber % 3 | Repeat a pattern at intervals |
The calculation should have a gameplay meaning, not merely produce a number. Suppose an arena is world units wide and a player travels at units per second. Then crossing time is:
In code:
float crossingTime = arenaWidth / moveSpeed;
The units reveal whether the formula makes sense:
That is useful when tuning. Raising moveSpeed reduces crossing time, making engagements happen faster. Increasing arena width increases crossing time, giving players more room to escape.
Assignment is not comparison
The single equals sign assigns a value:
currentHealth = 75;
The double equals sign compares two values and produces a bool:
currentHealth == 0
Later, you will use comparisons such as currentHealth <= 0 to decide when a player dies. For now, recognize the difference: = changes stored data, while == asks whether two values match.
C# also offers combined assignment operators:
score += 10;
currentHealth -= damage;
These are shorthand for:
score = score + 10;
currentHealth = currentHealth - damage;
Parentheses make the intended order of a calculation clear:
float finalDamage = (baseDamage + bonusDamage) * damageMultiplier;
Without parentheses, multiplication happens before addition. In gameplay code, explicit parentheses are often worthwhile even when you know the default order, because they make later tuning safer to read.
Watch for integer division
This is a common beginner trap:
int remainingHealth = 5;
int players = 2;
int healthPerPlayer = remainingHealth / players;
The result is 2, not 2.5, because both inputs and the destination are integers. Fractions are discarded.
When the result should include a fraction, ensure at least one side of the division is a float:
float healthPerPlayer = (float)remainingHealth / players;
For a firing system, the same idea lets you calculate a time interval from shots per second:
float shotsPerSecond = 4f;
float fireInterval = 1f / shotsPerSecond;
At four shots per second, the interval is seconds. Later, you will use that interval to implement a cooldown.
Serialized fields: expose tuning, preserve control
A field marked with [SerializeField] is private to other scripts but still visible and editable in Unity’s Inspector.
[SerializeField] private float moveSpeed = 5f;
This is a particularly good default for gameplay tuning:
privateprevents unrelated scripts from directly changingmoveSpeed.[SerializeField]lets you set a useful value in the Inspector.- The
= 5finitializer supplies a default when a new component is created.
You may also see this approach:
public float moveSpeed = 5f;
A public field is also normally visible in the Inspector, but it additionally lets any script with a reference to the component change the value. That may be appropriate occasionally, but it makes it easier for a larger project to lose track of what is allowed to alter a value. Use [SerializeField] private for configuration that designers or you need to tune, but that other scripts should not freely overwrite.
Read Unity Learn’s short tips on making numerical tuning easier in the Inspector while keeping implementation fields private.
In Tip 6, read the slider tip on the [Range] attribute. Then find Tip 11, beginning with private-field tip. Focus on the separation between Inspector visibility and public access from other scripts.
[Range(min, max)] changes an Inspector number field into a slider. It is useful when you know a sensible testing range:
[SerializeField, Range(1f, 12f)] private float moveSpeed = 5f;
The slider makes values such as 5.37 easy to try, while discouraging accidental tests at an absurd speed such as 5000. It is an Inspector convenience, not a complete safety rule for every value that code elsewhere might set.

A subtle but important point: after Unity has saved an Inspector value for a component in a scene or prefab, that serialized value takes precedence over the code initializer. If you later change:
[SerializeField] private float moveSpeed = 5f;
to:
[SerializeField] private float moveSpeed = 8f;
an existing Player component that was already saved with 5 may remain at 5. This protects intentional per-object tuning. It also explains why changing a number in code does not always visibly update the Inspector.
Build a small gameplay-tuning component
Now make the concepts concrete. This component does not move or shoot yet. Instead, it exposes values you will use in later lessons and reports a few calculated results when the scene begins.
- In the Hierarchy, create an empty GameObject and name it
GameplayTuning. - In your
Scriptsfolder, create a C# script namedGameplayTuning. - Attach that script to the
GameplayTuningGameObject. - Open the script and replace its contents with the following code. Ensure the filename and class name both remain
GameplayTuning.
using UnityEngine;
public class GameplayTuning : MonoBehaviour
{
[SerializeField, Range(1f, 12f)] private float moveSpeed = 5f;
[SerializeField] private float arenaWidth = 20f;
[SerializeField] private int startingHealth = 100;
[SerializeField, Range(1, 100)] private int damagePerHit = 25;
[SerializeField, Range(0.25f, 10f)] private float shotsPerSecond = 4f;
[SerializeField] private bool meleeEnabled = true;
private void Start()
{
float crossingTime = arenaWidth / moveSpeed;
float exactHitsToEmptyHealth = (float)startingHealth / damagePerHit;
float fireInterval = 1f / shotsPerSecond;
Debug.Log($"Arena crossing time: {crossingTime:F2} seconds");
Debug.Log($"Exact health-to-damage ratio: {exactHitsToEmptyHealth:F2}");
Debug.Log($"Time between shots: {fireInterval:F2} seconds");
Debug.Log($"Melee enabled: {meleeEnabled}");
}
}
Start is a Unity event method that runs once when the active GameObject begins in Play mode. You will study methods properly next lesson; here it simply provides a place to perform and display the calculations.
After saving, return to Unity and select GameplayTuning in the Hierarchy. Its Inspector should display:
- Move Speed as a slider
- Arena Width as a number field
- Starting Health and Damage Per Hit as whole-number fields
- Shots Per Second as a slider
- Melee Enabled as a checkbox
Try these two tuning passes outside Play mode:
| Value | First pass: slower duel | Second pass: fast duel |
|---|---|---|
| Move Speed | 3 | 8 |
| Arena Width | 24 | 16 |
| Starting Health | 120 | 80 |
| Damage Per Hit | 20 | 40 |
| Shots Per Second | 2 | 6 |
Enter Play mode after each pass and view the Console. Notice how one Inspector edit changes every calculation that depends on it. For example, reducing shotsPerSecond makes fireInterval larger, which would make shots less frequent once you implement firing.
Do not rely only on the output numbers. Ask what they imply for play:
- Does a player cross the arena so quickly that aiming matters less?
- Does high damage end a fight before players can react?
- Does a high firing rate overpower melee before melee has a role?
Those are design decisions expressed as variables. The early goal is not to find perfect values; it is to make the values easy to locate, change, test, and reason about.
Remember that Inspector edits made during Play mode normally disappear when you stop playing. Make enduring tuning changes outside Play mode, then save the scene and commit the script and scene changes when you reach a useful checkpoint.
Key takeaways
Variables store named data, and their types communicate what the data means: use int for whole quantities, float for fractional gameplay values, and bool for true-or-false states. Arithmetic operators transform these values into useful quantities such as crossing time, damage, and firing intervals; assignment operators update stored state.
Use [SerializeField] private for values you want to tune in the Inspector without making them freely editable by other scripts. Add [Range] when a slider makes testing a bounded numerical value easier.
Next, you will turn these stored values into actual gameplay rules by writing methods with parameters, return values, and conditionals.
Can't find a good explanation? Sign up and we'll make it for you
Sign up