Lesson 4: C# Scripting Fundamentals - Writing Your First Gameplay Scripts

In Lessons 1–3 you learned how to navigate Unity, work with GameObjects and Components, and think in terms of Transforms and coordinates. Now it is time to add the missing ingredient: code that actually drives gameplay.

By the end of this lesson you will:

  • Understand how C# scripts attach to GameObjects as components.
  • Know the lifecycle of important Unity methods like Start and Update.
  • Read basic player input and turn it into movement.
  • Keep your code organized so future lessons feel straightforward, not overwhelming.

1. How C# scripts fit into Unity’s component system

Unity does not run C# in isolation. Instead, you create scripts that inherit from MonoBehaviour and add them as components on GameObjects.

Conceptually:

  • A GameObject is just an empty container.
  • Components (Transform, SpriteRenderer, Collider, your scripts) give it behavior and visuals.
  • Your C# scripts are how you define custom behavior that runs every frame.

When you add a script:

  • Unity compiles it when you save.
  • The script appears as a component you can add in the Inspector.
  • Public fields on the script show up as editable properties.

Keep this mental model: “Scripts are components that run logic.”

2. Script lifecycle: Start and Update

Most beginner gameplay scripts use two lifecycle methods:

  • Start – runs once when the component is enabled for the first time.
  • Update – runs every frame while the component is enabled.

Typical responsibilities:

  • Use Start to cache references and set initial values.
  • Use Update to read input, move objects, and update state over time.

This mirrors how you thought about events in previous chapters:

  • Setup once, then update each frame.

3. Creating your first player movement script

You will now connect everything you have learned so far into a simple player controller:

  1. Create a new C# script in the Project view called PlayerController.
  2. Attach it to your player GameObject (the one you moved manually in earlier lessons).
  3. Plan what this script should do:
    • Read horizontal and vertical input.
    • Convert that into a direction vector.
    • Move the Transform using that direction and a speed value.

Before worrying about code details, clarify the data you need:

  • A movement speed value (for example, 5 units per second).
  • Access to the player’s Transform (built in as transform on MonoBehaviour).

Thinking in terms of “what data and behavior does this component own?” keeps scripts focused and easier to extend.

4. Working with input conceptually

Unity’s input system gives you access to:

  • Axes (horizontal, vertical) for keyboard or gamepad movement.
  • Key presses and releases for discrete actions like jumping or firing.

Conceptually, the pattern is:

  • Each frame you ask, “Which inputs are active?”
  • You convert those answers into a direction or action.
  • You apply that to movement, animation, or other systems.

Important ideas:

  • Reading input every frame belongs in Update, because input is time-based.
  • Movement should be multiplied by Time.deltaTime so it is independent of frame rate.
  • It is often easier to work with a normalized direction vector (length 1) and then scale by speed.

This pattern will repeat across many systems: read input → compute intent → apply to Transform or other components.

5. Moving the player using the Transform

You already understand Transforms and coordinates; now you connect them to code.

The conceptual steps for frame-based movement are:

  1. Start with the current position.
  2. Build a direction vector from input.
  3. Multiply by speed and Time.deltaTime.
  4. Add that result to the current position to get a new position.
  5. Assign the new position back to the Transform.

From a game design perspective:

  • Speed controls how quickly players can cross the level.
  • The choice of axes (world vs local) affects whether movement is relative to the camera or the character.

Later lessons will swap manual position changes for physics-based movement, but this direct approach is perfect for learning.

6. Keeping scripts clean and extendable

Even in early lessons, small structure decisions pay off later.

Guidelines:

  • Keep one clear responsibility per script whenever possible.
  • Use descriptive names for variables, especially anything exposed in the Inspector.
  • Avoid copying and pasting large chunks of logic—prefer small, focused methods.
  • Group related code with comments that describe intent, not implementation details.

When you come back to this script in future lessons to add jumping, animation, or camera follow, you will be glad it is straightforward and readable.

7. Mini challenge – build a simple player controller scene

To lock in the ideas from this lesson, set up a tiny practice scene:

  • Use the layout you created in Lesson 3 (ground, platforms, start marker).
  • Attach your movement script to the player object.
  • Experiment with different movement speeds until it feels responsive but controllable.

Try these variations:

  • Restrict movement to one axis (for a lane runner feel).
  • Allow movement on both X and Z to test diagonal movement.
  • Change the pivot and parenting setup to see how it affects motion.

The goal is not to build a full character controller yet—it is to build confidence working with C# and Transforms together.

Troubleshooting

The script does not seem to run at all
Check that the script is attached to an active GameObject in the scene, and that the component is enabled.

Movement speed feels different on different machines
Confirm that any manual movement code is multiplied by Time.deltaTime so it scales with frame time instead of frame count.

The player moves, but not in the expected direction
Verify whether you are treating input as world-space directions or relative to the character’s facing. Also check that your axes are mapped to the keys you expect.

Inspector values do not match what you see in play mode
Remember that changing public fields during Play Mode will reset when you stop. When you find values that feel good, stop the game and enter them again in Edit Mode.

Summary

In this lesson you learned how C# scripts plug into Unity’s component system, how the Start and Update methods define a lifecycle for your gameplay logic, and how to connect input, Transforms, and movement conceptually. You now have the mental model you need to start turning static scenes into interactive prototypes.

In the next lesson you will build on this by creating a more complete player controller that includes jumping, simple gravity, and camera-friendly movement, preparing the foundation for combat and interactions later in the course.