Files
Colosseum/AGENTS.md
dal4segno 7016b3c575 [Docs] AGENTS.md 추가
프로젝트 가이드라인 및 코딩 컨벤션 문서

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-11 02:58:50 +09:00

330 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Colosseum - Unity Game Project
## Project Overview
Multiplayer arena game built with **Unity 6000.3.10f1** and **Unity Netcode for GameObjects**.
- **Language**: C# 9.0
- **Target Framework**: .NET Standard 2.1
- **Root Namespace**: `Colosseum`
- **Assembly Definition**: `Colosseum.Game` (Assets/Scripts/Colosseum.Game.asmdef)
## Game Design Documentation
Design docs are maintained in Obsidian Vault: `C:\Users\dal4s\OneDrive\문서\Obsidian Vault\Colosseum`
### Game Concept
- **Genre**: Online multiplayer co-op action RPG (3rd person)
- **Theme**: Gladiator survival boss raid in Colosseum
- **Roles**: Multi-role system - players can hybridize (e.g., Tank 0.5 + DPS 0.5) instead of fixed Tank/DPS/Healer
### Stats System
| Stat | Abbr | Description | Derived Formula |
|------|------|-------------|-----------------|
| Strength | STR | Weapon damage | Physical Damage = STR × 2 |
| Dexterity | DEX | Ranged aim/damage, melee speed | Ranged Damage = DEX × 2 |
| Intelligence | INT | Magic damage | Magic Damage = INT × 2 |
| Vitality | VIT | Max health | Max HP = VIT × 10 |
| Wisdom | WIS | Healing power | Heal Power = WIS × 1.5 |
| Spirit | SPI | Max mana | Max MP = SPI × 5 |
### Damage Calculation
```
Final Damage = baseDamage + (statDamage × statScaling)
```
| DamageType | Base Stat | Description |
|------------|-----------|-------------|
| Physical | STR | Melee weapon damage |
| Magical | INT | Spell damage |
| Ranged | DEX | Bow/ranged damage |
| True | None | Fixed damage, no stat scaling |
### Stat Modifier System
Modifiers are applied in order:
1. **Flat**: Add fixed value
2. **PercentAdd**: Sum percentages, then multiply
3. **PercentMult**: Multiply individually
```
Final = (Base + FlatSum) × (1 + PercentAddSum) × PercentMult1 × PercentMult2...
```
### Skill System
- **Active Skills**: 6 slots (L-click, R-click, 1, 2, 3, 4)
- **Passive Skills**: Tree-based progression from center
- **Effects**: Triggered via animation events (`OnEffect(index)`)
- **Animation**: Start clip + optional end clip
## Build/Run Commands
This is a Unity project. Use Unity Editor for building and testing.
```bash
# Open in Unity Editor (requires Unity Hub)
# Build via: File > Build Settings > Build
# Run tests in Unity Editor
# Window > General > Test Runner > EditMode / PlayMode
```
### Build from Command Line (Windows)
```bash
# Build Windows standalone (adjust paths as needed)
"C:\Program Files\Unity\Hub\Editor\6000.3.10f1\Editor\Unity.exe" -batchmode -projectPath . -buildWindows64Player ./Builds/Windows/Colosseum.exe -quit
```
## Project Structure
```
Assets/
Scripts/
Abnormalities/ # Buff/debuff system
Editor/ # Unity editor extensions
Network/ # Network management
Player/ # Player controllers
Skills/ # Skill system
Effects/ # Skill effects (damage, heal, etc.)
Stats/ # Character statistics
UI/ # User interface
```
## Code Style Guidelines
### Namespaces
Follow `Colosseum.{Subnamespace}` pattern:
```csharp
namespace Colosseum.Player { }
namespace Colosseum.Skills { }
namespace Colosseum.Skills.Effects { }
namespace Colosseum.Stats { }
namespace Colosseum.Network { }
namespace Colosseum.Abnormalities { }
```
### Using Statements Order
Organize imports in this order, separated by blank lines:
1. System namespaces
2. UnityEngine namespaces
3. Unity.Netcode / Unity packages
4. Colosseum namespaces
```csharp
using System;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
using Colosseum.Stats;
using Colosseum.Player;
```
### Naming Conventions
| Element | Convention | Example |
|---------|------------|---------|
| Classes | PascalCase | `PlayerNetworkController` |
| Interfaces | IPascalCase | `IDamageable` |
| Methods | PascalCase | `TakeDamageRpc()` |
| Public Properties | PascalCase | `MaxHealth`, `IsStunned` |
| Private Fields | camelCase | `currentHealth`, `characterStats` |
| Constants | PascalCase or SCREAMING_SNAKE | `SKILL_STATE_NAME`, `MaxValue` |
| Enum values | PascalCase | `DamageType.Physical` |
### Serialization & Inspector
Use `[SerializeField]` with `[Header]` and `[Tooltip]` for organization:
```csharp
[Header("References")]
[Tooltip("CharacterStats component (auto-searched if null)")]
[SerializeField] private CharacterStats characterStats;
[Header("Settings")]
[Min(0f)] [SerializeField] private float baseDamage = 10f;
[SerializeField] private DamageType damageType = DamageType.Physical;
```
### Documentation
Use XML documentation comments in **Korean**:
```csharp
/// <summary>
/// 플레이어 네트워크 상태 관리 (HP, MP 등)
/// </summary>
public class PlayerNetworkController : NetworkBehaviour
{
/// <summary>
/// 대미지 적용 (서버에서만 실행)
/// </summary>
[Rpc(SendTo.Server)]
public void TakeDamageRpc(float damage)
{
// ...
}
}
```
### Network Code Patterns
Use Unity Netcode patterns:
```csharp
// Network variables for synchronized state
private NetworkVariable<float> currentHealth = new NetworkVariable<float>(100f);
// Server RPCs for client-to-server calls
[Rpc(SendTo.Server)]
public void TakeDamageRpc(float damage)
{
currentHealth.Value = Mathf.Max(0f, currentHealth.Value - damage);
}
// Check authority before modifying
if (IsServer)
{
currentHealth.Value = MaxHealth;
}
```
### Expression Body Members
Use for simple properties and methods:
```csharp
public float MaxHealth => vitality.FinalValue * 10f;
public bool IsStunned => stunCount > 0;
public bool CanAct => !IsStunned;
```
### Switch Expressions
Prefer switch expressions for concise mapping:
```csharp
public CharacterStat GetStat(StatType statType)
{
return statType switch
{
StatType.Strength => strength,
StatType.Dexterity => dexterity,
StatType.Intelligence => intelligence,
_ => null,
};
}
```
### ScriptableObjects for Data
Use ScriptableObject for configuration data:
```csharp
[CreateAssetMenu(fileName = "NewSkill", menuName = "Colosseum/Skill")]
public class SkillData : ScriptableObject
{
[SerializeField] private string skillName;
[SerializeField] private List<SkillEffect> effects;
public string SkillName => skillName;
public IReadOnlyList<SkillEffect> Effects => effects;
}
```
### Error Handling
- Use `Debug.LogWarning()` for recoverable issues
- Use `Debug.LogError()` for critical failures
- Null-check parameters in public methods
```csharp
public void ApplyAbnormality(AbnormalityData data, GameObject source)
{
if (data == null)
{
Debug.LogWarning("[Abnormality] ApplyAbnormality called with null data");
return;
}
// ...
}
```
### Events
Use C# events with `Action<T>` or custom delegates:
```csharp
public event Action<ActiveAbnormality> OnAbnormalityAdded;
public event Action<ActiveAbnormality> OnAbnormalityRemoved;
public event Action OnAbnormalitiesChanged;
// Invoke with null-conditional
OnAbnormalityAdded?.Invoke(newAbnormality);
```
## Key Dependencies
| Package | Purpose |
|---------|---------|
| Unity.Netcode.Runtime | Multiplayer networking |
| Unity.InputSystem | New input system |
| Unity.TextMeshPro | Text rendering |
| Unity.Networking.Transport | Low-level networking |
## Common Patterns
### MonoBehaviour Components
```csharp
public class ExampleComponent : MonoBehaviour
{
[Header("References")]
[SerializeField] private Animator animator;
public Animator Animator => animator;
private void Awake()
{
if (animator == null)
animator = GetComponentInChildren<Animator>();
}
}
```
### NetworkBehaviour Components
```csharp
public class NetworkedComponent : NetworkBehaviour
{
private NetworkVariable<int> value = new NetworkVariable<int>();
public override void OnNetworkSpawn()
{
// Initialize networked state
}
public override void OnNetworkDespawn()
{
// Cleanup
}
}
```
## Notes
- All code comments and documentation should be in Korean
- Use `[Min()]` attribute for numeric minimums in Inspector
- Use `[TextArea]` for multi-line string fields
- Private fields should use `camelCase` (no `m_` or `_` prefix)
- Prefer `IReadOnlyList<T>` for exposing collections