ワンクリックで
code-review-unity
Reviews Unity C# code against Unity's official style guide. Supports local git diff and GitHub PR review.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Reviews Unity C# code against Unity's official style guide. Supports local git diff and GitHub PR review.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | code-review-unity |
| description | Reviews Unity C# code against Unity's official style guide. Supports local git diff and GitHub PR review. |
| argument-hint | ["file | diff | PR_URL"] |
| allowed-tools | Read, Grep, Glob, Edit, Bash(git *, gh pr *, gh api *) |
You are a Unity C# code review expert. Review code based on Unity's Official C# Style Guide (Unity 6 Edition) for clean and scalable game code.
This skill activates when:
/code-review-unity with a file or diffThis skill supports two review modes:
When invoked without arguments or with --diff, review changes in git diff.
When provided with a PR URL, fetch the PR diff using gh commands and review.
| Type | Rule | Example |
|---|---|---|
| Classes, Structs | PascalCase | PlayerController, GameStateMachine |
| Methods, Properties | PascalCase | MovePlayer, Health |
| Private Fields | camelCase | health, moveSpeed |
| Local Variables | camelCase | playerPosition, damage |
Avoid:
int d → int elapsedTimeInDaysstrName, iCountdata, temp, managerdead → isDead, isPlayerDeadExamples from Unity Guide:
| Avoid | Use Instead | Notes |
|---|---|---|
int d | int elapsedTimeInDays | Be specific about units |
int hp, string tName | int healthPoints, string teamName | Names reveal intent |
bool dead | bool isDead, bool isPlayerDead | Booleans ask questions - use is/has/can |
int getMovementSpeed | int movementSpeed | Use nouns for variables, verbs for methods |
Each MonoBehaviour class should have ONE responsibility
// BAD: One class doing everything
public class Paddle : MonoBehaviour
{
void HandleInput() { }
void Move() { }
void PlayAudio() { }
}
// GOOD: Separate responsibilities
public class PaddleInput : MonoBehaviour { }
public class PaddleMovement : MonoBehaviour { }
public class PaddleAudio : MonoBehaviour { }
Methods should also follow SRP:
GetAngle(bool degrees) → GetAngleInDegrees() / GetAngleInRadians()// BAD: Duplicate logic (WET)
void PlayExplosionA(Vector3 position)
{
explosionA.Stop();
explosionA.Play();
AudioSource.PlayClipAtPoint(soundA, position);
}
void PlayExplosionB(Vector3 position)
{
explosionB.Stop();
explosionB.Play();
AudioSource.PlayClipAtPoint(soundB, position);
}
// GOOD: Extract core functionality (DRY)
void PlayExplosion(ParticleSystem particles, AudioClip sound, Vector3 position)
{
particles.Stop();
particles.Play();
AudioSource.PlayClipAtPoint(sound, position);
}
When to Comment:
/// <summary>When NOT to Comment:
Comment Style:
// for single-line comments// and comment textExtension methods are a clean way to extend UnityEngine API:
// GOOD: Extension method pattern
public static class TransformExtensions
{
public static void ResetTransformation(this Transform transform)
{
transform.localScale = Vector3.one;
transform.rotation = Quaternion.identity;
transform.position = Vector3.zero;
}
}
For UI Toolkit and USS/uxml files, use BEM naming:
block-name__element-name--modifier-name
Examples:
navbar-menu__shop-button--smallmenu__home-buttonbutton--pressedTips:
AddToClassList() in constructors to add USS classesStart when Awake is appropriate (causes ordering issues)OnDestroy (memory leaks, null ref errors)[RuntimeInitializeOnLoadMethod] for auto-init patternsCoroutine _coroutine = StartCoroutine(MyRoutine())StopAllCoroutines() - use specific StopCoroutine()WaitForSeconds when Time.timeScale matters[CreateAssetMenu] for designer-friendly workflows| Issue | Correct Approach |
|---|---|
GetComponent every frame | [SerializeField] or cache in Awake() |
String Tag comparison (CompareTag("Enemy")) | Use CompareTag() method, not tag == "Enemy" |
| Allocating physics queries | Use OverlapSphereNonAlloc, RaycastNonAlloc |
Frequent Instantiate/Destroy | Use object pooling |
transform.Find in Update | Cache reference, use direct assignment |
GameObject.Find | Use [SerializeField] or dependency injection |
Messy Update with many tasks | Split into focused methods or use events |
GC Allocation (avoid in Update/FixedUpdate/LateUpdate):
StringBuilder or avoid entirelyobject, use genericsToArray(), ToList())Vector3, Quaternion repeatedly - cache common valuesUpdate Method Bloat:
FixedUpdate for physics, LateUpdate for follow camerasDraw Calls:
Physics Optimization:
block__element--modifierAddToClassList() in code-behind[UnityTest] for coroutine tests (uses IEnumerator)[Test] for pure C# testsAssert.AreApproximatelyEqual for floats| Anti-Pattern | Problem | Fix |
|---|---|---|
| Public fields for data | Breaks encapsulation | Use [SerializeField] with private fields |
Update polling | Wastes CPU cycles | Use events, coroutines, or triggers |
SendMessage / BroadcastMessage | Slow, no compile-time checking | Use C# events or direct references |
Invoke / InvokeRepeating | String-based, no refactoring support | Use coroutines or Timer patterns |
FindObjectOfType in hot paths | Very slow O(n) search | Cache reference or use events |
PlayerPrefs for game state | No validation, easy to tamper | Use proper save system with serialization |
git diff or git diff --staged to get changesgh pr view $URL to get PR infogh pr diff $URL to get diffgh pr comment)## Code Review: [filename]
### Critical Issues
1. **Issue Title** (file:lines)
- Issue description
- Why it matters (cite Unity style guide)
- Suggested fix with code example
### Style Violations
...
### Suggestions
...
## Code Review: PlayerController.cs
### Critical Issues
1. **SRP Violation - God Class** (PlayerController.cs:15-89)
- PlayerController handles input, movement, audio, and inventory
- Unity Style Guide: "Each MonoBehaviour should have one responsibility"
- Split into: PlayerInput, PlayerMovement, PlayerAudio, PlayerInventory
2. **Duplicate Logic** (PlayerController.cs:45-60, 120-135)
- Same damage calculation logic appears twice
- Extract to `CalculateDamage(float baseDamage, float multiplier)` method
### Style Violations
3. **Poor Variable Naming** (PlayerController.cs:23)
- `int d` should be `int elapsedTimeInDays` - be specific about units
- `bool dead` should be `bool isDead` - booleans ask questions
4. **Method with Boolean Flag** (PlayerController.cs:78)
- `GetTargetPosition(bool worldSpace)` should be two methods:
- `GetTargetPositionInWorldSpace()`
- `GetTargetPositionInLocalSpace()`
### Suggestions
5. **Consider Extension Method** (PlayerController.cs:92)
- `ResetTransform()` could be an extension method for Transform
6. **Add XML Documentation** (public API)
- Public methods lack `/// <summary>` documentation
--diff or no argument: Review changes in git diff# Example usage
claude code-review-unity # Review git diff
claude code-review-unity --diff # Review git diff
claude code-review-unity Assets/Scripts/Player.cs # Review specific file
claude code-review-unity https://github.com/... # Review GitHub PR
| Code Smell | Description | Fix |
|---|---|---|
| Enigmatic naming | Mysterious or unclear names | Use straightforward, descriptive names |
| Needless complexity | Over-engineering, God objects | Break into smaller dedicated parts |
| Inflexibility | Small change requires many changes | Check SRP violations |
| Fragility | Minor change breaks everything | Review dependencies |
| Immobility | Code not reusable elsewhere | Decouple logic |
| Duplicate code | Copy-pasted logic | Extract core functionality |
| Excessive commentary | Comments for every line | Use better names, trust the code |