NoEditorEngine

Learning hub

Learn the engine by building a small 2D game.

Follow the path from setup to gameplay code, sprites, physics, tilemaps, audio, particles, debugging, and preview builds. No visual editor needed.

Code-first lessons C# gameplay examples v0.8 gameplay flow
01

Start

Install the SDK, open the Code Workspace, and create your first project.

02

Build

Write C# entities, add components, move the player, and draw sprites.

03

World

Load a tilemap, set camera bounds, use collision, triggers, audio, and particles.

04

Debug

Use console logs, diagnostics, profiler output, and temp Preview Play safely.

Step 1

Install NoEditorEngine

The installer gives users the Code Workspace, runtime, Engine.dll API, templates, and build tools.

Download

Use the current installer from the home page.

Download Setup

Open

Open the setup file. It installs the modern editor, runtime, SDK, templates, and helper scripts.

Launch

Open NoEditorEngine Code Workspace from Desktop or Start Menu.

%LOCALAPPDATA%\NoEditorEngine\NoEditorEngine-0.8\
  editor/
  runtime/
  sdk/
  templates/

Step 2

Use the Code Workspace

The workspace is not a scene editor. It is a code-focused place to edit scripts, build, preview, and read logs.

Project Explorer

Open scripts, assets, maps, sounds, and project.json without leaving the workspace.

Code Editor

Edit .cs files with line numbers, tabs, save support, search, and Engine API completion.

Build Panel

Run dotnet build, read compiler output, and jump to diagnostics by file and line.

Preview Play

Build into a temp folder, run the C++ runtime, capture logs, then clean temp files.

Step 3

Understand project files

A NoEditorEngine game is just a folder with config, C# scripts, and assets.

MyGame/
  project.json
  scripts/
    Game.csproj
    Game.cs
    Player.cs
  assets/
    maps/
      level1.json
    sprites/
    sounds/
{
  "name": "MyGame",
  "version": "0.8",
  "mainAssembly": "scripts/bin/Debug/net8.0/Game.dll",
  "mainClass": "Game",
  "startScene": "assets/maps/level1.json",
  "window": {
    "width": 1280,
    "height": 720,
    "title": "My Game"
  },
  "performance": {
    "targetFps": 240,
    "fixedPhysicsFps": 60,
    "maxDeltaTime": 0.05,
    "enableFrameLimiter": true
  }
}

Step 4

Create your first entity

Entities are the gameplay objects. Components add behavior like rendering, physics, audio, and particles.

using Engine;

public class Player : Entity
{
    public override void Awake()
    {
        Name = "Player";
    }

    public override void Start()
    {
        Log.Info("Player started");
    }

    public override void Update(float deltaTime)
    {
    }

    public override void OnDestroy()
    {
        Log.Info("Player destroyed");
    }
}
AwakeRuns when the entity is created.
StartRuns once before the first update.
UpdateRuns every render frame.
FixedUpdateRuns during fixed physics steps.
OnDestroyRuns before the entity is removed.

Step 5

Add WASD movement

Use Rigidbody2D velocity instead of directly pushing through walls with Transform changes.

using Engine;

public class Player : Entity
{
    Rigidbody2D rb;
    public float Speed = 300f;

    public override void Start()
    {
        rb = AddComponent<Rigidbody2D>();
        rb.UseGravity = false;
    }

    public override void Update(float dt)
    {
        Vector2 move = Vector2.Zero;

        if (Input.IsKeyDown(KeyCode.W)) move.Y += 1;
        if (Input.IsKeyDown(KeyCode.S)) move.Y -= 1;
        if (Input.IsKeyDown(KeyCode.A)) move.X -= 1;
        if (Input.IsKeyDown(KeyCode.D)) move.X += 1;

        if (move.Length() > 0)
            move = move.Normalized();

        rb.Velocity = move * Speed;
    }
}

Tip: Normalized movement keeps diagonal movement from becoming faster.

Step 6

Draw sprites and animations

SpriteRenderer draws one texture. AnimatedSpriteRenderer switches named clips over time.

var sprite = AddComponent<SpriteRenderer>();
sprite.TexturePath = "assets/sprites/player.png";
sprite.Size = new Vector2(64, 64);
var anim = AddComponent<AnimatedSpriteRenderer>();
anim.AddAnimation("Idle", new[]
{
    "assets/player_idle_1.png",
    "assets/player_idle_2.png"
}, fps: 4, loop: true);

anim.AddAnimation("Walk", new[]
{
    "assets/player_walk_1.png",
    "assets/player_walk_2.png"
}, fps: 8, loop: true);

anim.Play("Idle");
if (move.Length() > 0)
{
    anim.Play("Walk");
    if (move.X < 0) anim.FlipX = true;
    if (move.X > 0) anim.FlipX = false;
}
else
{
    anim.Play("Idle");
}

Step 7

Use physics and collision

BoxCollider2D creates an AABB collider. Trigger colliders send trigger events without physically pushing entities.

var collider = AddComponent<BoxCollider2D>();
collider.Size = new Vector2(48, 48);
collider.Layer = CollisionLayer.Player;

public override void OnCollisionEnter(Entity other)
{
    Log.Info("Hit " + other.Name);
}

public override void OnTriggerEnter(Entity other)
{
    Log.Info("Trigger touched " + other.Name);
}

Solid

Use for walls, enemies, and physical blockers.

Trigger

Use for coins, checkpoints, doors, and invisible sensors.

Static

Set wall Rigidbody2D as static so the player resolves against it.

Step 8

Load a tilemap

Tilemaps define walls, empty space, coins, and player spawn points through JSON.

{
  "tileSize": 64,
  "width": 16,
  "height": 10,
  "layers": [
    {
      "name": "Walls",
      "solid": true,
      "tiles": [
        "################",
        "#..............#",
        "#....P.....C...#",
        "#..............#",
        "################"
      ]
    }
  ],
  "legend": {
    "#": { "type": "wall", "sprite": "assets/wall.png", "solid": true },
    ".": { "type": "empty" },
    "P": { "type": "player_spawn" },
    "C": { "type": "coin" }
  }
}
public class Game : Entity
{
    public override void Start()
    {
        Tilemap map = Scene.LoadTilemap("assets/maps/level1.json");
        Player player = Scene.Spawn(new Player());
        player.Transform.Position = map.PlayerSpawn;

        Camera.Main.Follow(player, smooth: 8.0f);
        Camera.Main.SetBounds(0, 0, map.WorldWidth, map.WorldHeight);
    }
}

Step 9

Follow the player with Camera.Main

The camera affects rendering only. Entity Transform.Position always stays in world coordinates.

Camera.Main.Follow(player, smooth: 8.0f);
Camera.Main.DeadZone = new Vector2(120, 80);
Camera.Main.Zoom = 1.0f;
Camera.Main.SetBounds(0, 0, map.WorldWidth, map.WorldHeight);

Rule: Camera movement should never change the player's Transform.Position.

Step 10

Add audio and particles

Use AudioSource for short WAV sounds and ParticleEmitter for lightweight effects.

var audio = AddComponent<AudioSource>();
audio.Clip = "assets/sounds/coin.wav";
audio.Volume = 0.8f;
audio.Play();
var dust = AddComponent<ParticleEmitter>();
dust.MaxParticles = 256;
dust.EmitRate = 20;
dust.Lifetime = 0.5f;
dust.Speed = 120;
dust.Size = 6;
dust.Play();
public class Coin : Entity
{
    public override void OnTriggerEnter(Entity other)
    {
        Log.Info("Coin collected");
        Scene.Destroy(this);
    }
}

Step 11

Debug and profile

Use keyboard debug tools during preview to inspect runtime behavior without adding editor features.

F1Toggle collider debug rendering.
F2Print FPS, frame time, entity count, draw calls, and collision checks.
F3Toggle physics debug details.
ConsoleRead build, runtime, error, and profiler logs in the workspace.
[Profiler]
FPS: 238
Frame Time: 4.16 ms
Update: 0.30 ms
Physics: 0.45 ms
Render: 1.10 ms
Draw Calls: 8
Collision Checks: 145

Troubleshooting

Common errors

Most first-project issues are path, build, or class-name problems. These are the first things to check.

Game.dll was not found

Press Build first and check that project.json mainAssembly points to the built DLL.

Main class was not found

Make sure project.json mainClass matches the C# class name exactly, for example Game.

Sprite does not appear

Check asset path spelling. Paths are relative to the project folder, not the editor folder.

Player passes through walls

Use Rigidbody2D velocity and BoxCollider2D. Walls should have solid static colliders.

Next steps

Build the BasicGame loop

After these lessons, try making a small scene with a player, coins, walls, camera follow, sound, and particles.

Your first goal

Create a player that moves with WASD, cannot walk through walls, collects a coin trigger, plays a sound, and uses Camera.Main follow.

Get NoEditorEngine