[Docs] AGENTS.md 추가
프로젝트 가이드라인 및 코딩 컨벤션 문서 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
329
AGENTS.md
Normal file
329
AGENTS.md
Normal file
@@ -0,0 +1,329 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user