C# and Variant API: methods, properties and signals
When to use direct C# calls or Call, Get and generated names.
Choose the call boundary
Prefer a direct call between known C# types: the compiler checks names, arguments and results. Call serves a dynamic engine boundary where method names and arguments use Variant. It does not make arbitrary .NET types engine-compatible.
CounterService.cs
using Reckfell;
public partial class CounterService : Entity
{
[Signal] public delegate void CountChangedEventHandler(int count);
private int _count;
public int Count => _count;
public bool TryAdd(int amount)
{
if (amount <= 0 || amount > 1000 - _count) return false;
_count += amount;
EmitSignal(SignalName.CountChanged, _count);
return true;
}
}The complete example uses counter.Call(CounterService.MethodName.TryAdd, 5).AsBool(). Count becomes 5 and a CountChanged subscriber receives 5. Get("Count") reads a supported property through the engine API; it does not expose every private C# field.
Names and types
The generator preserves the C# name TryAdd. try_add is not an alias. Use generated MethodName, PropertyName and SignalName values where available; do not edit generated code.
Dynamic arguments and results must match the signature. Check HasMethod for an unknown object and separately check native instance validity; finding a method does not validate a gameplay command.
CountChanged is the C# representation of an engine signal. IDamageable and ordinary .NET models remain C# contracts without automatic Variant marshalling. This page explains the C# engine boundary rather than promising arbitrary second-language support.