groupsCommunity

Project Structure Recommendations

calendar_today May 3, 2026 schedule ~1 min read person patrickjr verified 50

Project Structure Recommendations

Community guide for organizing s&box projects based on Facepunch examples and successful community projects.

CODE
my_game/
├── code/
│   ├── GameManager.cs          # Main game logic
│   ├── Player/
│   │   ├── PlayerController.cs
│   │   ├── PlayerState.cs      # Health, inventory, etc.
│   │   └── PlayerInput.cs      # Input handling
│   ├── Weapons/
│   │   ├── Weapon.cs           # Base weapon class
│   │   ├── WeaponRifle.cs
│   │   └── WeaponShotgun.cs
│   ├── UI/
│   │   ├── Hud.razor
│   │   ├── MainMenu.razor
│   │   └── Scoreboard.razor
│   └── Utils/
│       ├── Extensions.cs
│       └── Constants.cs
├── assets/
│   ├── weapons/
│   │   ├── rifle.vmdl
│   │   └── rifle.fire.sound
│   ├── ui/
│   │   └── hud.scss
│   └── materials/
│       └── bullet_hole.vmat
├── scenes/
│   ├── main_menu.scene
│   └── level_01.scene
└── my_game.sbproj

Namespace Organization

CSHARP
// Keep namespaces consistent with folder structure
namespace MyGame.Player;
namespace MyGame.Weapons;
namespace MyGame.UI;

// Avoid generic namespaces
// ❌ namespace MyGame; (too broad)
// ✅ namespace MyGame.Weapons; (specific)

Component Naming

CSHARP
// ✅ Good: Clear, specific names
public class PlayerHealth : Component
public class WeaponManager : Component
public class GameTimer : Component

// ❌ Bad: Vague or generic
public class Manager : Component  // Which manager?
public class Script : Component   // Too generic
public class MyComponent : Component // Meaningless

Asset Naming Conventions

TypeConventionExample
ScenesPascalCaseMainMenu.scene
Materialssnake_casemetal_rusty.vmat
Soundssnake_caseweapon_rifle.fire.sound
ModelsPascalCasePlayerRig.vmdl
PrefabsPascalCaseEnemyZombie.prefab

Scene Organization

Use empty GameObjects as "folders" in scenes:

CODE
Level_01 (scene root)
├── [Environment] (empty, groups terrain/props)
│   ├── Terrain
│   └── Buildings
├── [Gameplay] (empty, groups game logic)
│   ├── Spawners
│   └── Triggers
├── [Lighting] (empty, groups lights)
└── [Players] (empty, spawn points)

Tags Strategy

Establish a consistent tagging system:

CSHARP
// Core gameplay tags
public static class Tags
{
    public const string Player = "player";
    public const string Enemy = "enemy";
    public const string Weapon = "weapon";
    public const string Solid = "solid";
    public const string Trigger = "trigger";
    public const string Interactable = "interactable";
    
    // Team tags for multiplayer
    public const string TeamRed = "team_red";
    public const string TeamBlue = "team_blue";
}

Resource Loading Strategy

CSHARP
public class AssetManager : Component
{
    // Cache loaded resources
    private static Dictionary<string, Material> _materials = new();
    private static Dictionary<string, SoundEvent> _sounds = new();
    
    public static Material GetMaterial(string path)
    {
        if (!_materials.TryGetValue(path, out var mat))
        {
            mat = Material.Load(path);
            _materials[path] = mat;
        }
        return mat;
    }
}

Settings Organization

CSHARP
// Game settings in one place
public static class GameSettings
{
    // Player
    public const float PlayerWalkSpeed = 200f;
    public const float PlayerRunSpeed = 400f;
    public const float PlayerJumpForce = 400f;
    
    // Weapons
    public const float WeaponFireRate = 0.1f;
    public const int WeaponMaxAmmo = 30;
    
    // Game
    public const float MatchDuration = 300f;
    public const int MaxPlayers = 16;
}

Version Control Best Practices

GITIGNORE
# Add to .gitignore
*.los              # Compiled assets
*.vpk              # Packaged files
bin/
obj/
.vs/
*.user

Source

  • Facepunch example projects
  • Official asset pipeline docs: https://sbox.game/dev/doc/assets
  • Community best practices from s&box Discord
Was this helpful?