Skip to content

Heavenlode/Nebula

Repository files navigation

Nebula

Multiplayer netcode for Godot C#

Nebula is a tick-based, server-authoritative networking framework that makes building responsive online games in Godot straightforward. It handles the hard partsβ€”client-side prediction, rollback, interpolation, and state synchronizationβ€”so you can focus on your game.

Table of Contents

Why Nebula?

Building multiplayer games is hard. Building multiplayer games that feel good in Godot is even harder. Nebula solves the core challenges:

  • Instant responsiveness β€” Client-side prediction means players see immediate feedback, not 100ms of input lag
  • Cheat resistance β€” Server-authoritative model where the server is always the source of truth
  • Smooth visuals β€” Automatic interpolation for non-owned entities eliminates jitter
  • Simple API β€” Annotate properties with [NetProperty] and let the source generator handle the rest
  • Zero-allocation hot paths β€” Carefully optimized to avoid GC pressure; no lag spikes from garbage collection during gameplay

Quick Example

using Godot;
using Nebula;

public partial class Player : NetNode3D
{
    public Player()
    {
        Network.InitializeInput<PlayerInput>();
    }

    // Synced to all clients, with rollback and interpolation for smooth movement
    [NetProperty(Interpolate = true, Predicted = true, NotifyOnChange = true)]
    public Vector3 Position { get; set; }
    
    // Defines misprediction threshold for automagic rollback
    public float PositionPredictionTolerance { get; set; } = 2f;

    // Interest management - only visible to specific players
    [NetProperty(InterestMask = 0x02)]
    public int SecretScore { get; set; }

    // Called when Position changes on clients
    protected virtual void OnNetChangePosition(int tick, Vector3 oldVal, Vector3 newVal)
    {
        GD.Print($"Moved to {newVal}");
    }

    public override void _NetworkProcess(int tick)
    {
        // Both server AND owning client run this for prediction
        ref readonly var input = ref Network.GetInput<PlayerInput>();

        // Normalized inputs for easy cheat/hack prevention!
        Position += new Vector3(input.MoveX, 0, input.MoveY).Normalized() * Speed;
    }
}

Jump In

If you're eager to get started quickly, you can follow the Big Chungus tutorial to build your first game with Nebula + Godot right away.

completed-game

Features

Core Networking

  • Tick-based synchronization β€” Deterministic simulation at configurable tick rates (default 30Hz)
  • Server-authoritative β€” Single source of truth prevents cheating and ensures consistency
  • Input authority β€” Clients control specific entities; server validates and processes inputs
  • Interest management β€” Fine-grained control over what data each player receives

Client-Side Prediction

  • Instant feedback β€” Players see results immediately, not after round-trip latency
  • Automatic rollback β€” When predictions are wrong, Nebula corrects seamlessly
  • Configurable tolerance β€” Tune misprediction thresholds per-property

Visual Smoothing

  • Interpolation β€” Smooth movement for entities you don't control
  • Prediction + Interpolation β€” Owned entities predict, others interpolateβ€”same property, automatic switching

Developer Experience

  • Source generators β€” No boilerplate; annotate properties and methods
  • Compile-time validation β€” Errors like missing handlers caught at build time
  • Typed inputs β€” Zero-allocation input structs with full type safety
  • Virtual methods β€” Hook into network events with overridable virtual methods

Performance

  • GC-friendly design β€” Hot paths avoid allocations; no lag spikes from .NET garbage collection
  • Struct-based serialization β€” Inputs and state use unmanaged structs, not heap objects
  • Pooled buffers β€” Network buffers are reused, not allocated per-packet
  • No boxing β€” PropertyCache union type avoids boxing value types

Architecture

  • Multiple worlds β€” Run separate game instances (dungeons, lobbies, matches) in one server process
  • Flexible serialization β€” Built-in support for primitives, vectors, quaternions, and custom types
  • ENet transport β€” Reliable UDP with automatic connection management

Installation

Requirements

  • Godot 4.5+ with .NET support
  • .NET 10.0+

Setup

  1. Add Nebula to your project

    Copy the addons/Nebula folder into your project's addons directory.

  2. Import in your .csproj

    <Project Sdk="Godot.NET.Sdk/4.5.1">
      <PropertyGroup>
        <TargetFramework>net10.0</TargetFramework>
      </PropertyGroup>
      
      <Import Project="addons\Nebula\Nebula.props" />
    </Project>
  3. Build your project

    This compiles Nebula, allowing you to enable the plugin.

  4. Enable the plugin

    In Godot: Project β†’ Project Settings β†’ Plugins β†’ Enable "Nebula"

Core Concepts

Network Nodes

Inherit from NetNode, NetNode2D, or NetNode3D to create networked entities:

public partial class Enemy : NetNode3D
{
    [NetProperty]
    public int Health { get; set; } = 100;
}

Network Properties

Mark properties for synchronization with [NetProperty]:

[NetProperty]                          // Basic sync
[NetProperty(NotifyOnChange = true)]   // Triggers OnNetChange{Name}() on change
[NetProperty(Interpolate = true)]      // Smooth interpolation for non-owners
[NetProperty(Predicted = true)]        // Client-side prediction for owners
[NetProperty(InterestMask = 0x04)]     // Only sync to players with this interest layer

Input Handling

Define input structs and process them on both server and client:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PlayerInput
{
    public float MoveX;
    public float MoveY;
    public bool Jump;
}

// In your node:
public override void _PhysicsProcess(double delta)
{
    Network.SetInput(new PlayerInput
    {
        MoveX = Input.GetAxis("left", "right"),
        MoveY = Input.GetAxis("up", "down"),
        Jump = Input.IsActionPressed("jump")
    });
}

Spawning Entities

// Server-side spawning with input authority
var player = playerScene.Instantiate<Player>();
worldRunner.Spawn(player, inputAuthority: peer);

Net Functions

Nebula's version of an RPC.

[NetFunction(Source = NetFunction.NetworkSources.Client, ExecuteOnCaller = false)]
public void JoinGame()
{
    var player = playerScene.Instantiate<Player>();
    Network.CurrentWorld.Spawn(newPlayer, inputAuthority: Network.CurrentWorld.NetFunctionContext.Caller);
}

Comparison

Feature Nebula Godot Built-in Netfox
Language C# only GDScript & C# GDScript & C#
Architecture Server-authoritative Flexible (RPC-based) Server-authoritative
Client-side Prediction βœ… Built-in ❌ Manual βœ… Built-in
Rollback/Reconciliation βœ… Automatic ❌ Manual βœ… Automatic
Interpolation βœ… Per-property βœ… MultiplayerSynchronizer βœ… Built-in
Interest Management βœ… Fine-grained (property-level) ⚠️ Basic (visibility) ❌ Not built-in
Multiple Game Worlds βœ… Built-in ❌ Manual ❌ Not built-in
Tick-based Simulation βœ… Yes ❌ Frame-based βœ… Yes
Source Generation βœ… Zero boilerplate ❌ N/A ❌ N/A
Compile-time Validation βœ… Yes ❌ No ❌ No
Transport ENet (UDP) ENet, WebSocket, WebRTC Godot's built-in
Learning Curve Moderate Low Moderate

When to Choose Each

Choose Nebula if you:

  • Are building in C#, want maximum type safety, and performance optimization
  • Need fine-grained control over what data each player sees
  • Want prediction and interpolation to "just work" together
  • Are building a game with instances areas, lobbies, matches (multiple worlds)

Choose Godot's built-in multiplayer if you:

  • Want the simplest possible setup
  • Are building a casual/turn-based game where latency isn't critical
  • Prefer GDScript and minimal dependencies

Choose Netfox if you:

  • Prefer GDScript but still want prediction/rollback
  • Want the noray integration for easier connectivity
  • Are looking for a middle-ground solution

Documentation

Comprehensive documentation is available at: https://nebula.heavenlode.com

For implementation details and architecture overview, see NEBULA_OVERVIEW.mdc. This file is particularly useful for AI/vibe coding as well.

Roadmap

  • Client-side prediction and rollback
  • Property interpolation
  • Interest management
  • Multiple world support
  • Physics rollback (blocked by Godot #2821)
  • Lag compensation for projectiles/hitscan

Community

Contributing

Contributions are welcome! Whether it's bug reports, feature requests, documentation improvements, or code contributions.

  1. Questions or ideas? Drop by the Discord or open an issue
  2. Want to contribute code? Please open an issue first to discuss your proposal
  3. Found a bug? Bug reports with reproduction steps are incredibly helpful

Built with πŸ’œ for the Godot community

About

Godot C# Netcode from another galaxy 🌌

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors