# 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
///
/// 플레이어 네트워크 상태 관리 (HP, MP 등)
///
public class PlayerNetworkController : NetworkBehaviour
{
///
/// 대미지 적용 (서버에서만 실행)
///
[Rpc(SendTo.Server)]
public void TakeDamageRpc(float damage)
{
// ...
}
}
```
### Network Code Patterns
Use Unity Netcode patterns:
```csharp
// Network variables for synchronized state
private NetworkVariable currentHealth = new NetworkVariable(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 effects;
public string SkillName => skillName;
public IReadOnlyList 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` or custom delegates:
```csharp
public event Action OnAbnormalityAdded;
public event Action 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();
}
}
```
### NetworkBehaviour Components
```csharp
public class NetworkedComponent : NetworkBehaviour
{
private NetworkVariable value = new NetworkVariable();
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` for exposing collections