- UNC 경로 처리 문제로 cmd/powershell/bash 대신 파일 도구 사용 규칙 명시 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
12 KiB
12 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: \\Truenas\smb\Obsidian Vault\Colosseum
- Always use the shared Obsidian Vault at
\\Truenas\smb\Obsidian Vault\Colosseumfor project documentation updates. - Obsidian Vault 파일은 반드시 파일 도구(read/write/edit)로만 접근한다. cmd, powershell, bash 등은 UNC 경로를 정상적으로 처리하지 못하므로 사용하지 않는다.
- Do not write Colosseum design notes to
C:\Users\dal4s\OneDrive\문서\Obsidian Vault\Colosseum; that path is not the active vault for this project. - Unless the user explicitly names another file,
체크리스트means\\Truenas\smb\Obsidian Vault\Colosseum\개발\프로토타입 체크리스트.md. - After completing work, always check whether the prototype checklist should be updated and reflect the new status when needed.
- If the work also changes a domain-specific checklist such as boss/player/combat, sync that checklist too.
- When editing user-authored Obsidian notes, preserve the user's original text structure as much as possible.
- If Codex adds interpretation, clarification, proposals, or implementation notes to a user-authored note, put them in a clearly labeled separate section such as
Codex 보완 메모orCodex 제안so the added content is visibly distinguishable from the user's original writing. - Avoid silently rewriting or blending Codex-authored guidance into the user's original bullet lists unless the user explicitly asks for a rewrite.
- Cross-session design agreements that should be checked before related work are summarized in
\\Truenas\smb\Obsidian Vault\Colosseum\개발\세션 공통 합의.md.
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.
- CRITICAL: After any code change (edit, create, delete), always perform a force refresh with compile request and wait for ready before entering play mode. Failing to do so causes mid-play compilation which can leave network ports occupied on the next run. Use
refresh_unity(mode="force", compile="request", wait_for_ready=true). - After Unity-related edits, check the Unity console for errors 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.
- Commit messages should follow the recent project history style: use a type prefix such as
feat:,fix:, orchore:and write the subject in Korean so the gameplay/UI/system change is clear from the log alone. - When the change is substantial, include a blank line after the subject and add Korean bullet points that summarize the work by feature/purpose, similar to commit
0889bb0(feat: 드로그 집행 개시 패턴 및 낙인 디버프 추가). - Prefer the format
type: 한글 요약for the subject, then- 변경 사항bullet lines for the body. Usefeat:for feature work,fix:for bug fixes, andchore:for non-feature maintenance such as scene/prefab cleanup, asset reorganization, or other miscellaneous upkeep. The body should mention key implementation scope, affected systems/assets, and validation or rollback notes when relevant. - 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 - 프로젝트 용어로는
필살기보다고위력 기술을 우선 사용한다. - 보호막은 단일 값이 아니라
타입별 독립 인스턴스로 취급한다. 같은 타입은 자기 자신만 갱신되고, 서로 다른 타입은 공존하며, 흡수 순서는 적용 순서를 따른다. - 보스 시그니처 전조는 가능한 한 정확한 진행 수치 UI보다 명확한 모션/VFX로 읽히게 한다. 차단 진행도나 정확한 누적 수치 노출은 명시 요청이 없으면 피한다.