프로젝트 가이드라인 및 코딩 컨벤션 문서 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
330 lines
8.2 KiB
Markdown
330 lines
8.2 KiB
Markdown
# 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
|