plugins/unity-master/skills/unity-csharp-scripting/SKILL.md
C# scripting in Unity for gameplay, behavior, and engine integration. PROACTIVELY activate for: (1) writing Unity C# scripts, (2) MonoBehaviour lifecycle (Awake/OnEnable/Start/Update/FixedUpdate/LateUpdate), (3) coroutines and async/await in Unity, (4) delegates, events, Action/Func patterns, (5) ScriptableObject creation and serialization, (6) GetComponent / TryGetComponent and component caching, (7) physics scripting (Rigidbody, raycast, collision/trigger callbacks), (8) animation scripting (Animator parameters, state machines, IK), (9) NavMesh and NavMeshAgent scripting, (10) input handling (Input System package), (11) custom serialization and SerializeField. Provides: lifecycle reference, coroutine vs async patterns, ScriptableObject templates, Rigidbody/collision recipes, NavMesh examples, and Input System setup.
npx skillsauth add JosiahSiegel/claude-plugin-marketplace unity-csharp-scriptingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Core C# scripting reference for Unity development. Covers MonoBehaviour lifecycle, physics and collision APIs, animation scripting, audio, navigation, common design patterns, serialization, and ECS/DOTS coding patterns.
Awake() -> OnEnable() -> Start() -> FixedUpdate() -> Update() -> LateUpdate() -> OnDisable() -> OnDestroy()
| Method | When Called | Use For |
|--------|-----------|---------|
| Awake() | Once, when object instantiates (before Start) | Self-initialization, caching references |
| OnEnable() | Each time object becomes active | Subscribe to events, reset state |
| Start() | Once, before first Update (after all Awake) | Cross-object initialization |
| FixedUpdate() | Fixed timestep (default 0.02s) | Physics, Rigidbody movement |
| Update() | Every frame | Input, non-physics logic |
| LateUpdate() | After all Update calls | Camera follow, post-movement adjustments |
| OnDisable() | When object deactivates | Unsubscribe events, save state |
| OnDestroy() | When object is destroyed | Final cleanup, resource release |
[DefaultExecutionOrder(N)] or Script Execution Order settingsOnValidate() for editor-time validation of serialized fieldsIEnumerator SpawnWaves(int count, float delay)
{
for (int i = 0; i < count; i++)
{
SpawnEnemy();
yield return new WaitForSeconds(delay);
}
}
// Start: Coroutine handle = StartCoroutine(SpawnWaves(5, 1f));
// Stop: StopCoroutine(handle); or StopAllCoroutines();
| Yield Instruction | Behavior |
|-------------------|----------|
| yield return null | Wait one frame |
| yield return new WaitForSeconds(t) | Wait t seconds (affected by timeScale) |
| yield return new WaitForSecondsRealtime(t) | Unscaled time |
| yield return new WaitForFixedUpdate() | Wait for next FixedUpdate |
| yield return new WaitForEndOfFrame() | After rendering |
| yield return new WaitUntil(() => condition) | Wait until predicate is true |
| yield return StartCoroutine(other) | Wait for nested coroutine |
For Unity 2023+/Unity 6, Awaitable is built-in. For older versions, use UniTask.
async Awaitable LoadLevelAsync(string sceneName)
{
await Awaitable.WaitForSecondsAsync(1f);
var op = SceneManager.LoadSceneAsync(sceneName);
while (!op.isDone)
{
progressBar.value = op.progress;
await Awaitable.NextFrameAsync();
}
}
// Publisher
public class Health : MonoBehaviour
{
public event System.Action<float> OnDamaged; // event keyword prevents external invocation
public event System.Action OnDeath;
public void TakeDamage(float amount)
{
currentHealth -= amount;
OnDamaged?.Invoke(amount);
if (currentHealth <= 0) OnDeath?.Invoke();
}
}
// Subscriber
void OnEnable() => health.OnDamaged += HandleDamage;
void OnDisable() => health.OnDamaged -= HandleDamage;
void HandleDamage(float amount) => /* react */;
Decouple systems without direct references. Create GameEvent as a ScriptableObject asset, invoke from publishers, and listen from subscribers via GameEventListener MonoBehaviours. See references/design-patterns.md for full implementation.
| Task | Method | Where |
|------|--------|-------|
| Continuous force | rb.AddForce(dir * force) | FixedUpdate |
| Instant impulse | rb.AddForce(dir * force, ForceMode.Impulse) | FixedUpdate |
| Direct velocity | rb.linearVelocity = dir * speed | FixedUpdate |
| Kinematic move | rb.MovePosition(target) | FixedUpdate |
| Rotation | rb.MoveRotation(targetRot) | FixedUpdate |
Note: In Unity 6, Rigidbody.velocity is renamed to Rigidbody.linearVelocity.
if (Physics.Raycast(origin, direction, out RaycastHit hit, maxDistance, layerMask))
{
Debug.Log($"Hit {hit.collider.name} at {hit.point}");
}
// Use Physics.RaycastAll or Physics.RaycastNonAlloc for multiple hits
// 2D: Physics2D.Raycast, Physics2D.OverlapCircle, etc.
| Callback | Requires | Use For |
|----------|----------|---------|
| OnCollisionEnter/Stay/Exit | Both have colliders, at least one Rigidbody, isTrigger=false | Physical impacts |
| OnTriggerEnter/Stay/Exit | One collider has isTrigger=true, at least one Rigidbody | Zones, pickups, detection |
Always use CompareTag("Enemy") instead of other.tag == "Enemy" (avoids GC allocation).
[RequireComponent(typeof(Animator))]
public class CharacterAnimation : MonoBehaviour
{
static readonly int SpeedHash = Animator.StringToHash("Speed");
static readonly int JumpTrigger = Animator.StringToHash("Jump");
Animator _anim;
void Awake() => _anim = GetComponent<Animator>();
void Update()
{
_anim.SetFloat(SpeedHash, moveSpeed);
if (jumped) _anim.SetTrigger(JumpTrigger);
}
}
Cache Animator.StringToHash results as static readonly fields to avoid per-frame hashing. Use Animation Events for gameplay-timed callbacks (footsteps, hit frames). For IK, implement OnAnimatorIK(int layerIndex) with SetIKPosition/Rotation/Weight.
[RequireComponent(typeof(AudioSource))]
public class SFXPlayer : MonoBehaviour
{
[SerializeField] AudioClip[] clips;
AudioSource _source;
void Awake() => _source = GetComponent<AudioSource>();
public void PlayRandom() => _source.PlayOneShot(clips[Random.Range(0, clips.Length)]);
}
Use AudioSource.PlayOneShot() for overlapping SFX. Use AudioMixer with exposed parameters for volume control. Use snapshots for state transitions (combat vs. exploration).
| Type | Serialized | Notes |
|------|-----------|-------|
| public fields | Yes | Visible in Inspector |
| [SerializeField] private | Yes | Preferred -- maintains encapsulation |
| [HideInInspector] public | Yes, hidden | Serialized but not shown |
| [NonSerialized] public | No | Opt-out of serialization |
| Properties | No | Never serialized by Unity |
| Dictionaries | No | Use serialized list + rebuild, or Odin/SerializedDictionary |
| Interfaces | No | Use abstract ScriptableObject or SerializeReference |
Use [SerializeReference] for polymorphic serialization of interfaces and abstract types.
| Pattern | When to Use | Approach | |---------|------------|----------| | Singleton | Global managers (Audio, GameState) | ScriptableObject-based or lazy MonoBehaviour | | Observer | Decoupled communication | C# events or SO event channels | | Command | Input/undo systems | Command interface + history stack | | State Machine | AI, player states | Enum + switch, or class-based states | | Object Pool | Bullets, particles, enemies | Queue<T> with pre-instantiation | | Service Locator | Testable global access | Static registry with interface keys |
For detailed implementations and code examples, see references/design-patterns.md.
| Concept | Role | |---------|------| | Entity | Lightweight ID (no MonoBehaviour) | | IComponentData | Pure data struct on entities | | SystemBase / ISystem | Logic operating on component queries | | EntityQuery | Filter entities by component sets | | Jobs (IJobEntity) | Multithreaded systems | | Burst Compiler | SIMD-optimized native code |
For ECS architecture patterns and migration guidance, see references/design-patterns.md.
references/design-patterns.md -- Full implementations of singleton, observer, command, state machine, object pool, service locator, and ECS patternsreferences/physics-animation-audio.md -- Detailed physics setup (2D and 3D), advanced animation (blend trees, IK, root motion, Animation Rigging), and audio architecturedevelopment
This skill should be used when the user asks to train, debug, scale, or improve ML models. PROACTIVELY activate for: (1) PyTorch, TensorFlow/Keras, JAX, Flax, Hugging Face Trainer/Accelerate training loops, (2) distributed training, DDP/FSDP/DeepSpeed, TPU/GPU setup, (3) mixed precision AMP/bf16, gradient accumulation, checkpointing, seeding, (4) overfitting, imbalance, loss functions, regularization, LR schedules, warmup, (5) memory optimization, gradient checkpointing, offloading, quantization-aware training. Provides: reproducible training best practices across deep learning and classical ML.
development
This skill should be used when the user asks to productionize, track, version, govern, monitor, or automate ML systems. PROACTIVELY activate for: (1) MLflow, Weights & Biases, Neptune, Comet, ClearML experiment tracking, (2) model registry, model versioning, artifact lineage, reproducibility, (3) Kubeflow, SageMaker Pipelines, Vertex AI Pipelines, Azure ML pipelines, Databricks workflows, (4) CI/CD, continuous training/evaluation, A/B tests, canary/shadow deployments, (5) drift detection, model monitoring, data validation, responsible AI governance. Provides: end-to-end MLOps architecture and operational safeguards.
development
This skill should be used when the user asks to optimize, export, serve, compress, or accelerate ML inference. PROACTIVELY activate for: (1) latency, throughput, p95/p99, batching, concurrency, KV cache, memory, or cost issues, (2) quantization INT8/INT4, GPTQ, AWQ, bitsandbytes, pruning, sparsity, distillation, (3) ONNX export, ONNX Runtime, TensorRT, TorchScript, torch.compile, XLA, OpenVINO, Core ML, TFLite, (4) Triton, TorchServe, TF Serving, BentoML, Seldon, KServe configuration, (5) edge deployment, CPU/GPU/TPU/Inferentia serving. Provides: hardware-aware inference optimization and safe benchmarking.
testing
This skill should be used when the user asks to tune hyperparameters, run sweeps, optimize search spaces, or use AutoML. PROACTIVELY activate for: (1) Optuna, Ray Tune, FLAML, AutoGluon, Hyperopt, Nevergrad, KerasTuner, W&B sweeps, (2) grid search, random search, Bayesian optimization, TPE, Gaussian processes, evolutionary search, (3) ASHA, Hyperband, successive halving, multi-fidelity optimization, population-based training, (4) learning-rate finder, batch-size search, early stopping, pruning, (5) reproducible sweep design and experiment analysis. Provides: budget-aware hyperparameter search strategy.