-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial
Yaroslav Sarchuk edited this page Aug 29, 2025
·
1 revision
This step-by-step tutorial will guide you through creating a complete game component system using the Atomic Plugin.
- Creating and configuring
.atomicfiles - Generating extension methods for entities
- Using generated code in your game
- Working with tags and values
- Optimizing with advanced features
We'll build a simple RPG character system with:
- Character entities with health, mana, and stats
- Inventory system with items
- Combat system with damage calculation
- Buff/debuff system
- Open Unity Hub
- Create new 3D project named "AtomicRPG"
- Install Atomic Framework:
# In Unity Package Manager, add from git URL: https://github.com/StarKRE22/Atomic.git
- Open the project in JetBrains Rider
- Verify Atomic Plugin is installed (see Installation)
- Create folder structure:
Assets/ โโโ Scripts/ โ โโโ Atomic/ # Your .atomic files โ โโโ Generated/ # Generated extension methods โ โโโ Game/ # Your game logic
- Right-click on
Scripts/Atomic/folder - Select
NewโAtomic File - Name it
Character.atomic
Edit Character.atomic:
entityType: "IEntity"
namespace: "RPG.Characters"
className: "CharacterExtensions"
directory: "Scripts/Generated/Characters"
aggressiveInlining: true
unsafe: false
imports:
System
UnityEngine
RPG.Core
RPG.Stats
tags:
Player
Enemy
NPC
Ally
Boss
Dead
Stunned
Invulnerable
values:
# Core Stats
Health: int
MaxHealth: int
Mana: float
MaxMana: float
Level: int
Experience: int
# Attributes
Strength: int
Agility: int
Intelligence: int
# Combat
Damage: float
Defense: float
CritChance: float
AttackSpeed: float
# References
Transform: Transform
Animator: Animator
CharacterModel: GameObject
- Open
Character.atomic - Press
Ctrl+Shift+Gto generate - Check
Scripts/Generated/Characters/forCharacterExtensions.cs
Create Inventory.atomic:
entityType: "IEntity"
namespace: "RPG.Inventory"
className: "InventoryExtensions"
directory: "Scripts/Generated/Inventory"
aggressiveInlining: true
imports:
System
System.Collections.Generic
UnityEngine
RPG.Items
tags:
HasInventory
InventoryFull
InventoryLocked
values:
# Inventory Data
Items: List<Item>
MaxSlots: int
Gold: int
# Equipment
Weapon: Item
Armor: Item
Accessory: Item
# Item Management
SelectedItem: Item
LastPickedItem: Item
ItemFilter: ItemType
- Press
Ctrl+Shift+GinInventory.atomic - Verify generation in
Scripts/Generated/Inventory/
Create Scripts/Game/CharacterController.cs:
using UnityEngine;
using RPG.Characters;
using Atomic.Entities;
public class CharacterController : MonoBehaviour
{
private IEntity characterEntity;
void Start()
{
// Create entity for this character
characterEntity = new Entity();
// Initialize character stats
characterEntity.SetMaxHealth(100);
characterEntity.SetHealth(100);
characterEntity.SetLevel(1);
characterEntity.SetStrength(10);
// Add player tag
characterEntity.AddPlayerTag();
// Set Unity references
characterEntity.SetTransform(transform);
characterEntity.SetAnimator(GetComponent<Animator>());
}
public void TakeDamage(int damage)
{
if (characterEntity.HasInvulnerableTag())
return;
int currentHealth = characterEntity.GetHealth();
int defense = (int)characterEntity.GetDefense();
// Calculate actual damage
int actualDamage = Mathf.Max(1, damage - defense);
int newHealth = Mathf.Max(0, currentHealth - actualDamage);
characterEntity.SetHealth(newHealth);
if (newHealth <= 0)
{
characterEntity.AddDeadTag();
OnDeath();
}
}
public void Heal(int amount)
{
if (characterEntity.HasDeadTag())
return;
int currentHealth = characterEntity.GetHealth();
int maxHealth = characterEntity.GetMaxHealth();
int newHealth = Mathf.Min(maxHealth, currentHealth + amount);
characterEntity.SetHealth(newHealth);
}
void OnDeath()
{
// Handle death logic
Debug.Log("Character died!");
characterEntity.GetAnimator()?.SetTrigger("Death");
}
}Create Scripts/Game/InventoryManager.cs:
using System.Collections.Generic;
using UnityEngine;
using RPG.Inventory;
using RPG.Items;
using Atomic.Entities;
public class InventoryManager : MonoBehaviour
{
private IEntity inventoryEntity;
void Start()
{
inventoryEntity = new Entity();
// Initialize inventory
inventoryEntity.SetItems(new List<Item>());
inventoryEntity.SetMaxSlots(20);
inventoryEntity.SetGold(100);
inventoryEntity.AddHasInventoryTag();
}
public bool AddItem(Item item)
{
if (!inventoryEntity.HasHasInventoryTag())
return false;
var items = inventoryEntity.GetItems();
int maxSlots = inventoryEntity.GetMaxSlots();
if (items.Count >= maxSlots)
{
inventoryEntity.AddInventoryFullTag();
return false;
}
items.Add(item);
inventoryEntity.SetLastPickedItem(item);
// Remove full tag if it was set
if (inventoryEntity.HasInventoryFullTag() && items.Count < maxSlots)
{
inventoryEntity.DelInventoryFullTag();
}
return true;
}
public void EquipWeapon(Item weapon)
{
if (weapon.Type != ItemType.Weapon)
return;
// Unequip current weapon
if (inventoryEntity.TryGetWeapon(out var currentWeapon))
{
AddItem(currentWeapon);
}
// Equip new weapon
inventoryEntity.SetWeapon(weapon);
// Remove from inventory
var items = inventoryEntity.GetItems();
items.Remove(weapon);
}
}Create Combat.atomic:
entityType: "IEntity"
namespace: "RPG.Combat"
className: "CombatExtensions"
directory: "Scripts/Generated/Combat"
aggressiveInlining: true
unsafe: true # Enable for performance-critical combat
imports:
System
System.Collections.Generic
UnityEngine
RPG.Skills
tags:
InCombat
Attacking
Defending
Casting
Channeling
Interrupted
values:
# Combat State
Target: IEntity
LastAttacker: IEntity
CombatStartTime: float
# Damage Tracking
DamageDealt: float
DamageTaken: float
LastDamageTime: float
CriticalHits: int
# Skills
ActiveSkills: List<Skill>
SkillCooldowns: Dictionary<int, float>
CurrentCast: Skill
CastProgress: float
Create Buffs.atomic:
entityType: "IEntity"
namespace: "RPG.Buffs"
className: "BuffExtensions"
directory: "Scripts/Generated/Buffs"
aggressiveInlining: true
imports:
System
System.Collections.Generic
UnityEngine
tags:
Buffed
Debuffed
Poisoned
Burning
Frozen
Blessed
Cursed
values:
ActiveBuffs: List<Buff>
ActiveDebuffs: List<Debuff>
BuffStacks: Dictionary<int, int>
DebuffResistance: float
StatusEffectDuration: Dictionary<string, float>
For performance-critical systems, enable aggressive inlining:
aggressiveInlining: true # Compiler optimization hint
Generated methods will include:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetHealth(this IEntity entity) { ... }For hot paths, enable unsafe code:
unsafe: true # Enables ref returns
This generates additional methods:
public static ref int RefHealth(this IEntity entity) { ... }Usage:
ref int health = ref entity.RefHealth();
health += 10; // Direct modification, no method call- Create new scene "TestArena"
- Add character GameObject with
CharacterController - Add UI for health/mana display
- Create enemy spawner
public class CombatTest : MonoBehaviour
{
public CharacterController player;
public CharacterController enemy;
void Start()
{
// Test damage calculation
player.TakeDamage(20);
// Test healing
player.Heal(10);
// Test death
enemy.TakeDamage(999);
}
}- Keep
.atomicfiles organized by system - Use consistent naming conventions
- Group related tags and values
- Enable
aggressiveInliningfor frequently called methods - Use
unsafeonly when necessary - Cache entity references
- Document complex values in comments
- Use meaningful tag names
- Keep atomic files focused (single responsibility)
Create a magic system with:
- Spell casting with mana cost
- Elemental damage types
- Spell combos
Implement quests with:
- Quest progress tracking
- Rewards system
- Quest dependencies
Extend for multiplayer:
- Network synchronization tags
- Player ownership values
- Server authority checks
- Explore Advanced Features
- Study Performance Optimization
- Learn about Custom Types
- Check Unity Integration specifics
- Review Troubleshooting for common issues
- Check FAQ for questions
- Report bugs on GitHub
Congratulations! You've completed the Atomic Plugin tutorial. You now know how to create entity systems using .atomic files and the generated extension methods.