# Unity Csharp Scripting

> >

- **Type:** Skill
- **Install:** `agentstack add skill-gamedev-skills-awesome-gamedev-agent-skills-unity-csharp-scripting`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [gamedev-skills](https://agentstack.voostack.com/s/gamedev-skills)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [gamedev-skills](https://github.com/gamedev-skills)
- **Source:** https://github.com/gamedev-skills/awesome-gamedev-agent-skills/tree/main/skills/unity/unity-csharp-scripting

## Install

```sh
agentstack add skill-gamedev-skills-awesome-gamedev-agent-skills-unity-csharp-scripting
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Unity C# Scripting (MonoBehaviour)

Write correct, idiomatic gameplay scripts in Unity 6. Get the lifecycle, component
access, serialization, and coroutines right so behaviour is deterministic and the
Inspector stays useful. Targets **Unity 6 (6000.0 LTS)**, C# / .NET Standard 2.1.

## When to use

- Use when authoring or fixing a `MonoBehaviour`: choosing the right lifecycle callback,
  reading/caching components, exposing fields to the Inspector, or running timed logic
  with coroutines.
- Use when the project has `*.cs` files, an `Assembly-CSharp` or `*.asmdef`, and a
  `ProjectSettings/` folder.

**When *not* to use:** moving rigidbodies / collision response → `unity-physics`; reading
player input → `unity-input-system`; shared data assets / config → `unity-scriptableobjects`;
Animator parameters → `unity-animation`. This skill owns the *script lifecycle and C#
plumbing*, not those subsystems.

## Core workflow

1. **Pick the callback by purpose, not habit.** `Awake` (cache references, runs once on
   load), `OnEnable` (subscribe to events), `Start` (init that depends on other objects'
   `Awake`), `Update` (per-frame logic/input polling), `FixedUpdate` (physics), `LateUpdate`
   (camera follow after movement), `OnDisable`/`OnDestroy` (unsubscribe/cleanup).
2. **Cache component lookups in `Awake`** — never call `GetComponent` every frame.
3. **Expose tunables with `[SerializeField] private`**, not public fields, so other code
   can't mutate them but designers can edit them in the Inspector.
4. **Scale per-frame values by `Time.deltaTime`** in `Update` (and `Time.fixedDeltaTime`
   semantics are automatic in `FixedUpdate`).
5. **Use coroutines for time-sequenced logic** (delays, tweens, "do X then wait then Y");
   start them with `StartCoroutine` and stop them deterministically.
6. **Verify in Play mode**: check the Console for null-reference exceptions, confirm values
   in the Inspector update as expected, and watch the Profiler if `Update` is hot.

## Patterns

### 1. Lifecycle + cached components (the canonical skeleton)

```csharp
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]      // auto-adds the dependency, prevents null refs
public class PlayerController : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 6f;   // editable in Inspector, private in code
    private Rigidbody _rb;                            // cached, not fetched per frame

    private void Awake() => _rb = GetComponent();  // cache once on load

    private void Update()
    {
        // Per-frame, non-physics work. Scale by deltaTime so it is frame-rate independent.
        transform.Rotate(0f, 90f * Time.deltaTime, 0f);
    }

    private void FixedUpdate()
    {
        // Physics work belongs here (fixed timestep). See the unity-physics skill.
        _rb.MovePosition(_rb.position + transform.forward * moveSpeed * Time.fixedDeltaTime);
    }
}
```

### 2. Safe component access with `TryGetComponent`

```csharp
// Avoids allocating a null and is clearer than GetComponent + null check.
if (other.TryGetComponent(out var health))
    health.Apply(-10);
```

### 3. Serialization that shows up correctly in the Inspector

```csharp
[SerializeField, Range(0f, 1f)] private float volume = 0.8f;  // slider
[SerializeField] private string playerName = "Hero";          // private but serialized

[System.Serializable]                 // REQUIRED for a plain class to serialize/show
public class Stats { public int hp = 100; public int mana = 50; }

[SerializeField] private Stats stats = new();  // nested struct-like data in the Inspector
```

### 4. Coroutines for time-sequenced logic

```csharp
private void Start() => StartCoroutine(FlashThenHide());

private System.Collections.IEnumerator FlashThenHide()
{
    yield return new WaitForSeconds(0.5f);   // wait half a second of game time
    GetComponent().enabled = false;
    yield return null;                       // resume next frame
}
```

## Pitfalls

- **`GetComponent` in `Update`** — it searches every frame and tanks performance. Cache the
  reference in `Awake`/`Start`.
- **Physics in `Update`** — moving a `Rigidbody` with forces or `MovePosition` outside
  `FixedUpdate` causes jitter and timestep-dependent behaviour. Read input in `Update`,
  apply physics in `FixedUpdate`.
- **Relying on `Start` order across objects** — `Start` runs after *all* `Awake`s, but order
  among `Start`s is undefined. Do cross-object wiring in `Start`, self-setup in `Awake`.
- **`public` fields just to show them in the Inspector** — that also lets any script mutate
  them. Use `[SerializeField] private` instead.
- **`gameObject.tag == "Enemy"`** allocates a string and is slower; use
  `gameObject.CompareTag("Enemy")`.
- **Coroutines stop when the GameObject is disabled** — a disabled object's coroutines are
  killed; re-`StartCoroutine` in `OnEnable` if it must survive toggling.
- **`Update` never runs before `Start`, but the *first* `Update` can run on the same
  frame as `Start`** — guard against not-yet-initialised fields if you split setup oddly.

## References

- For the full event-execution-order table and advanced coroutine patterns (custom
  `CustomYieldInstruction`, stopping by handle, `WaitUntil`/`WaitWhile`), read
  `references/lifecycle-and-coroutines.md`.
- Primary docs: Unity Manual "Event function execution order"
  (`https://docs.unity3d.com/Manual/execution-order.html`) and `ScriptReference/MonoBehaviour`.

## Related skills

- `unity-physics` — `Rigidbody`, collisions, and `FixedUpdate` motion.
- `unity-input-system` — reading player input into these scripts.
- `unity-scriptableobjects` — sharing data/config between scripts without singletons.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [gamedev-skills](https://github.com/gamedev-skills)
- **Source:** [gamedev-skills/awesome-gamedev-agent-skills](https://github.com/gamedev-skills/awesome-gamedev-agent-skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-gamedev-skills-awesome-gamedev-agent-skills-unity-csharp-scripting
- Seller: https://agentstack.voostack.com/s/gamedev-skills
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
