A flexible ability system that allows creating, configuring, and executing abilities in games
Can be used in Unity 2020.1.4 or later (C# 8)
You can install it via NuGet:
Install-Package NuclearAbilitySystemThe solution is divided into several projects:
-
NuclearAbilitySystem - Core framework with interfaces and base implementations
- Defines core abstractions for units, abilities, and state management
- Provides event system and command queue implementations
- No game-specific logic or features
-
NuclearAbilitySystem.Implementation - Reference implementation with concrete features
- Example implementations of units, abilities, and status effects
- Can be used as-is or replaced with custom implementations
-
NuclearAbilitySystem.Tests - Unit and integration tests
- Flexible Architecture - Core framework is completely decoupled from specific game mechanics
- State Management - Copy-on-write pattern for safe state transitions
- Event System - Powerful event bus for game logic
- Extensible - Easy to add custom implementations of any component
The system is built on these key abstractions:
- IUnit - Base interface for game entities
- IUnitFeature - Extensible unit capabilities
- IAbility - Defines unit actions and their execution
- ICombatState - Manages game state with copy-on-write pattern
- ICombatEventBus - Handles event-based communication
- Define the feature interface:
public interface IMyFeature : IUnitFeature
{
void DoSomething();
}- Implement the mutable version:
public class MyFeature : IMyFeature, IUnitFeatureMutable
{
private ICombatStateMutable _combatState;
public void Connect(ICombatStateMutable combatState)
{
_combatState = combatState;
// Subscribe to events if needed
}
public void Disconnect()
{
// Clean up event subscriptions
_combatState = null;
}
public IUnitFeatureMutable DeepClone()
{
return new MyFeature();
}
public void DoSomething()
{
// Feature implementation
}
}- Add extension methods for easy usage:
public static class UnitExtensions
{
public static T WithMyFeature<T>(this T unit) where T : IUnitMutable
{
unit.AddFeature(new MyFeature());
return unit;
}
public static IMyFeature GetMyFeature(this IUnit unit)
{
return unit.GetUnitFeature<IMyFeature>();
}
}- Use your new feature:
// Adding the feature to a unit
var unit = new TestUnit("Hero").WithMyFeature();
// Using the feature
unit.GetMyFeature().DoSomething();- Keep features small and focused
- Use events for cross-feature communication
- Make features immutable when possible
- Document public APIs thoroughly
- Write unit tests for all features
// Create a unit with basic features
var unit = new TestUnit("Player1", health: 100, damage: 10, position: Vector2.Zero);
// Add abilities
unit.WithAbility(new FireballAbility());
// Add status effects
unit.WithBullyStatusEffect();
unit.WithDefenderStatusEffect();var state = new CombatStateBuilder()
.WithUnit(playerUnit)
.WithUnit(enemyUnit)
.WithAbilityContext(new AbilityContextHolder())
.Build();// Execute ability at index 0 from player to enemy
var result = state.ExecuteAbility(
sourceId: playerUnit.Id,
abilityIndex: 0,
targetId: enemyUnit.Id
);
// Process the result
foreach (var command in result.Commands)
{
// Visualize commands in your game
}// Subscribe to damage events
state.CombatEventBus.Connect<PreDamageEvent, DamageEventResult>((e, prev) =>
{
// Modify or cancel damage
return new DamageEventResult(shouldContinue: true);
});Issues are very valuable to this project.
- Ideas are a valuable source of contributions others can make
- Problems show where this project is lacking
- With a question you show where contributors can improve the user experience
Pull requests are, a great way to get your ideas into this repository.
- MIT