- PlayerActionState로 이동, 점프, 스킬 입력 가능 여부를 통합 - 기절과 침묵 이상상태 데이터 및 효과 에셋을 추가 - 로컬 플레이어용 이상상태 디버그 HUD와 자동 검증 러너를 추가 - 플레이어 이동, 스킬 입력, 네트워크 상태를 새 행동 상태 기준으로 정리
8.8 KiB
8.8 KiB
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:
- Flat: Add fixed value
- PercentAdd: Sum percentages, then multiply
- 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.
# 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)
# 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:
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:
- System namespaces
- UnityEngine namespaces
- Unity.Netcode / Unity packages
- Colosseum namespaces
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:
[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:
/// <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:
// 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:
public float MaxHealth => vitality.FinalValue * 10f;
public bool IsStunned => stunCount > 0;
public bool CanAct => !IsStunned;
Switch Expressions
Prefer switch expressions for concise mapping:
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:
[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
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:
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
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
public class NetworkedComponent : NetworkBehaviour
{
private NetworkVariable<int> value = new NetworkVariable<int>();
public override void OnNetworkSpawn()
{
// Initialize networked state
}
public override void OnNetworkDespawn()
{
// Cleanup
}
}
Notes
- For Unity work, prefer Unity MCP for active scene inspection, runtime verification, prefab checks, and console review when it is available in the session.
- Never edit code, scenes, prefabs, components, or Unity asset settings while the Unity Editor is in play mode. Stop play mode first, then edit.
- After Unity-related edits, refresh or compile as needed and check the Unity console before proceeding.
- For networked play tests, prefer a temporary non-conflicting test port when needed and restore the default port after validation.
- The user has a strong project preference that play mode must be stopped before edits because network ports can remain occupied otherwise.
- 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(nom_or_prefix) - Prefer
IReadOnlyList<T>for exposing collections