Expert guidance for developing 2D games in the All-Out Engine custom framework with networking, ECS architecture, and mobile-first design patterns.
Expert guidance for developing 2D games using the All-Out Engine, a custom 2D game framework with built-in networking and ECS (Entity Component System) architecture.
This skill provides comprehensive instructions for working with the All-Out Engine, a custom C# game framework that handles networking, movement, and basic game systems. The engine uses a component-based architecture similar to Unity but with significant differences in available APIs.
1. **No Unity APIs** - This is a custom engine; do not attempt to use Unity-specific APIs
2. **2D First** - Use Vector2 instead of Vector3 for all spatial operations
3. **Mobile First** - Design for touch input; avoid keyboard controls
4. **ECS Architecture** - Use Entity/Component patterns for all game objects
5. **Network Awareness** - Always consider client/server separation
**Creating Entities:**
```csharp
// Create entity locally
var entity = Entity.Create();
// Network spawn (server only)
if (Network.IsServer)
{
Network.Spawn(entity);
}
```
**Finding Entities:**
```csharp
// Find by name
var entity = Entity.FindByName("MyEntity");
// Check if entity exists
if (entity.Alive())
{
// Entity is valid
}
// Get all components of type
foreach (var player in Scene.Components<MyPlayer>())
{
// Process each player
}
```
```csharp
// Get component
var component = entity.GetComponent<MyComponent>();
// Add component
entity.AddComponent<MyComponent>();
// No HasComponent - use GetComponent and check for null
```
```csharp
// Use LocalScale, not Scale
entity.LocalScale = new Vector2(2f, 2f);
// Position (2D)
entity.Position = new Vector2(100f, 50f);
```
```csharp
// Use Time.TimeSinceStartup for timers
float startTime = Time.TimeSinceStartup;
// Later, check elapsed time
if (Time.TimeSinceStartup - startTime > 5f)
{
// 5 seconds have passed
}
```
**Do NOT use coroutines or other timing methods**
```csharp
// Initialize RNG
RNG.Seed(1337);
// Generate random integers
int randomInt = RNG.RangeInt(0, 10);
// Generate random floats
float randomFloat = RNG.RangeFloat(0f, 1f);
```
**Only use RangeInt and RangeFloat - no other RNG methods**
Prefer standard library math functions. If needed functionality doesn't exist, implement it using System.Math.
```csharp
// List available assets in /res directory first
// Do NOT prefix paths with /res
// Load texture
var texture = Assets.GetAsset<Texture>("sprites/player.png");
// Load audio
var audio = Assets.GetAsset<AudioAsset>("sounds/explosion.wav");
// Load Spine skeleton
var skeleton = Assets.GetAsset<SpineSkeletonAsset>("characters/hero.json");
```
Common asset types: `Texture`, `AudioAsset`, `SpineSkeletonAsset`
```csharp
// Get sprite renderer (type is Sprite_Renderer with underscore)
var renderer = entity.GetComponent<Sprite_Renderer>();
// Set tint using Vector4 (not Color)
renderer.Tint = new Vector4(1f, 0f, 0f, 1f); // Red
// Set texture
renderer.Texture = Assets.GetAsset<Texture>("sprites/player.png");
```
**Important:** UI and sprite rendering code must run on client only.
```csharp
// Check execution context
if (Network.IsClient)
{
// Client-only code
}
if (Network.IsServer)
{
// Server-only code
}
```
```csharp
// In Player classes, use IsLocal for local client
if (IsLocal)
{
// Only for local player (e.g., camera control)
entity.AddComponent<CameraControl>();
}
```
SyncVars automatically synchronize primitive values between server and clients.
**Supported Types:**
**Declaration:**
```csharp
public partial class BattlePlayer : Player
{
// Always call constructor with initial value
public SyncVar<int> Health = new(100);
public SyncVar<bool> IsAlive = new(true);
public SyncVar<string> PlayerName = new("");
public SyncVar<Vector2> TargetPosition = new(Vector2.Zero);
}
```
**Usage:**
```csharp
// Read value
if (Health.Value <= 0)
{
// Player died
}
// Set value (server only)
if (Network.IsServer)
{
Health.Set(80);
}
// React to changes
Health.OnSync((oldValue, newValue) =>
{
Debug.Log($"Health changed from {oldValue} to {newValue}");
});
```
**Only change SyncVar values on the server using .Set()**
**ClientRpc - Server calls function on clients:**
```csharp
public partial class MyComponent : Component
{
[ClientRpc]
public void PlaySuccessSound()
{
// This runs on clients
var audio = Assets.GetAsset<AudioAsset>("sounds/success.wav");
audio.Play();
}
public void ServerLogic()
{
if (Network.IsServer)
{
// Server triggers client function
CallClient_PlaySuccessSound();
}
}
}
```
**Key Rules:**
```csharp
using AO;
public partial class MyPlayer : Player
{
public SyncVar<int> Score = new(0);
public override void OnStart()
{
if (IsLocal && Network.IsClient)
{
// Local client setup
Entity.AddComponent<CameraControl>();
}
if (Network.IsServer)
{
// Server setup
Score.Set(0);
}
}
}
```
```csharp
if (Network.IsServer)
{
var projectile = Entity.Create();
projectile.Name = "Projectile";
projectile.AddComponent<ProjectileComponent>();
Network.Spawn(projectile); // Make visible to clients
}
```
```csharp
private float lastActionTime;
public void Update()
{
float cooldown = 2f;
if (Time.TimeSinceStartup - lastActionTime > cooldown)
{
PerformAction();
lastActionTime = Time.TimeSinceStartup;
}
}
```
1. **Always check Network.IsServer before spawning entities**
2. **Use IsLocal for player-specific client setup**
3. **Keep rendering/UI code on client side**
4. **Initialize SyncVars with constructors**
5. **Use .Alive() to check entity validity**
6. **Prefer Vector2 for all 2D operations**
7. **Design for mobile touch input**
8. **Use Time.TimeSinceStartup for all timing**
9. **Check /res directory for available assets**
10. **Mark RPC classes as partial**
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/all-out-engine-game-development/raw