Skip to content

Generated Code

Yaroslav Sarchuk edited this page Aug 29, 2025 · 2 revisions

Generated Code Examples

This page shows exactly what C# code is generated from your .atomic files with the latest Atomic Framework.

Basic Generation

Input: Simple.atomic

namespace: Game
className: EntityExtensions
entityType: IEntity
aggressiveInlining: true

imports:
  - Atomic.Entities

tags:
  - Player

values:
  - Health: int

Output: EntityExtensions.cs

/**
* Code generation. Don't modify! 
**/

using Atomic.Entities;
using static Atomic.Entities.EntityNames;
using System.Runtime.CompilerServices;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace Game
{
#if UNITY_EDITOR
    [InitializeOnLoad]
#endif
    public static class EntityExtensions
    {
        ///Tags
        public static readonly int Player;

        ///Values
        public static readonly int Health; // int

        static EntityExtensions()
        {
            //Tags
            Player = NameToId(nameof(Player));

            //Values
            Health = NameToId(nameof(Health));
        }

        ///Tag Extensions

        #region Player

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasPlayerTag(this IEntity entity) => entity.HasTag(Player);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool AddPlayerTag(this IEntity entity) => entity.AddTag(Player);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool DelPlayerTag(this IEntity entity) => entity.DelTag(Player);

        #endregion

        ///Value Extensions

        #region Health

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int GetHealth(this IEntity entity) => entity.GetValue<int>(Health);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool TryGetHealth(this IEntity entity, out int value) => entity.TryGetValue(Health, out value);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void AddHealth(this IEntity entity, int value) => entity.AddValue(Health, value);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasHealth(this IEntity entity) => entity.HasValue(Health);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool DelHealth(this IEntity entity) => entity.DelValue(Health);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void SetHealth(this IEntity entity, int value) => entity.SetValue(Health, value);

        #endregion
    }
}

Advanced Generation

Input: Combat.atomic with Multiple Types

namespace: Game.Combat
className: CombatExtensions
entityType: IEntity
aggressiveInlining: true
unsafe: false

imports:
  - Atomic.Entities
  - UnityEngine
  - System.Collections.Generic

tags:
  - InCombat
  - Attacking
  - Defending
  - Dead

values:
  - Health: int
  - MaxHealth: int
  - Damage: float
  - Position: Vector3
  - Targets: List<Transform>

Output: CombatExtensions.cs

/**
* Code generation. Don't modify! 
**/

using Atomic.Entities;
using static Atomic.Entities.EntityNames;
using System.Runtime.CompilerServices;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System.Collections.Generic;

namespace Game.Combat
{
#if UNITY_EDITOR
    [InitializeOnLoad]
#endif
    public static class CombatExtensions
    {
        ///Tags
        public static readonly int InCombat;
        public static readonly int Attacking;
        public static readonly int Defending;
        public static readonly int Dead;

        ///Values
        public static readonly int Health; // int
        public static readonly int MaxHealth; // int
        public static readonly int Damage; // float
        public static readonly int Position; // Vector3
        public static readonly int Targets; // List<Transform>

        static CombatExtensions()
        {
            //Tags
            InCombat = NameToId(nameof(InCombat));
            Attacking = NameToId(nameof(Attacking));
            Defending = NameToId(nameof(Defending));
            Dead = NameToId(nameof(Dead));

            //Values
            Health = NameToId(nameof(Health));
            MaxHealth = NameToId(nameof(MaxHealth));
            Damage = NameToId(nameof(Damage));
            Position = NameToId(nameof(Position));
            Targets = NameToId(nameof(Targets));
        }

        ///Tag Extensions

        #region InCombat

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasInCombatTag(this IEntity entity) => entity.HasTag(InCombat);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool AddInCombatTag(this IEntity entity) => entity.AddTag(InCombat);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool DelInCombatTag(this IEntity entity) => entity.DelTag(InCombat);

        #endregion

        // ... other tags follow same pattern ...

        ///Value Extensions

        #region Health

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int GetHealth(this IEntity entity) => entity.GetValue<int>(Health);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool TryGetHealth(this IEntity entity, out int value) => entity.TryGetValue(Health, out value);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void AddHealth(this IEntity entity, int value) => entity.AddValue(Health, value);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool HasHealth(this IEntity entity) => entity.HasValue(Health);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool DelHealth(this IEntity entity) => entity.DelValue(Health);

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void SetHealth(this IEntity entity, int value) => entity.SetValue(Health, value);

        #endregion

        // ... other values follow same pattern ...
    }
}

Complex Types

Input with Complex Types

namespace: Game.Components
className: GameObjectExtensions
entityType: IEntity

imports:
  - System.Collections.Generic
  - UnityEngine
  - Atomic.Entities

values:
  - Inventory: List<Item>
  - Attributes: Dictionary<string, float>
  - Path: Vector3[]

Generated Methods for Complex Types

#region Inventory

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static List<Item> GetInventory(this IEntity entity) => entity.GetValue<List<Item>>(Inventory);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryGetInventory(this IEntity entity, out List<Item> value) => entity.TryGetValue(Inventory, out value);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddInventory(this IEntity entity, List<Item> value) => entity.AddValue(Inventory, value);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasInventory(this IEntity entity) => entity.HasValue(Inventory);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool DelInventory(this IEntity entity) => entity.DelValue(Inventory);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetInventory(this IEntity entity, List<Item> value) => entity.SetValue(Inventory, value);

#endregion

With Unsafe Code

Input with Unsafe Enabled

namespace: Game.Performance
className: FastExtensions
entityType: IEntity
aggressiveInlining: true
unsafe: true

imports:
  - Atomic.Entities
  - UnityEngine

values:
  - Position: Vector3
  - Health: int

Generated with Unsafe (Additional Ref Methods)

// When unsafe: true, additional ref methods are generated:

#region Health

// Standard methods...

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref int RefHealth(this IEntity entity) => ref entity.GetRef<int>(Health);

#endregion

#region Position

// Standard methods...

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Vector3 RefPosition(this IEntity entity) => ref entity.GetRef<Vector3>(Position);

#endregion

Key Changes in New Format

Static Field Initialization

  • Tags and values are now public static readonly int fields
  • Initialized in static constructor using NameToId()
  • No more hardcoded hash values

Method Signatures

  • All methods use integer IDs instead of strings
  • Tag methods return bool for add/delete operations
  • Value methods use generic GetValue<T>() and SetValue()

Unity Editor Support

  • Automatic [InitializeOnLoad] attribute for Unity Editor
  • Conditional compilation with #if UNITY_EDITOR
  • Always includes using static Atomic.Entities.EntityNames

Code Organization

  • Clear regions for each tag and value
  • Consistent comment markers (///Tags, ///Values)
  • Expression-bodied methods for conciseness

Complete Generated Methods

For each tag, the following methods are generated:

Method Return Type Description
Has{Tag}Tag() bool Check if entity has the tag
Add{Tag}Tag() bool Add tag to entity (returns success)
Del{Tag}Tag() bool Remove tag from entity (returns success)

For each value, the following methods are generated:

Method Return Type Description
Get{Value}() T Get the value
Set{Value}(T value) void Set the value
Has{Value}() bool Check if value exists
Add{Value}(T value) void Add value component with initial value
Del{Value}() bool Remove value component
TryGet{Value}(out T value) bool Try get value safely
Ref{Value}() ref T Get ref to value (only if unsafe: true)

Performance Optimizations

Aggressive Inlining

When aggressiveInlining: true:

  • All methods are decorated with [MethodImpl(MethodImplOptions.AggressiveInlining)]
  • Compiler attempts to inline method calls for better performance

Unsafe Code

When unsafe: true:

  • Additional Ref{Value}() methods are generated
  • Allows direct memory access without copying
  • Use with caution in performance-critical code

Usage Example

using Game.Combat;
using Atomic.Entities;

public class CombatSystem
{
    public void ProcessDamage(IEntity attacker, IEntity target)
    {
        // Check combat state
        if (!attacker.HasAttackingTag() || target.HasDeadTag())
            return;
        
        // Get damage value
        float damage = attacker.GetDamage();
        
        // Apply damage
        int currentHealth = target.GetHealth();
        target.SetHealth(currentHealth - (int)damage);
        
        // Check for death
        if (target.GetHealth() <= 0)
        {
            target.AddDeadTag();
            target.DelInCombatTag();
        }
    }
    
    public void QuickHeal(IEntity entity, int amount)
    {
        // Using ref for direct modification (if unsafe: true)
        ref int health = ref entity.RefHealth();
        health = Math.Min(health + amount, entity.GetMaxHealth());
    }
}

Best Practices

  1. Use meaningful names for tags and values
  2. Enable aggressive inlining for performance-critical code
  3. Use unsafe sparingly - only when performance profiling shows it's needed
  4. Organize imports - only include what you need
  5. Keep atomic files focused - one system per file
  6. Document complex values with comments in the atomic file

Note: The generated code format is optimized for the latest Atomic Framework with integer-based IDs for maximum performance.

Navigation

πŸ“š Documentation

πŸ“– Reference

❓ Help

πŸ”— Links

Clone this wiki locally