Universal RPG facade. One component per character - player, NPC, mob, pet. Replaces the
legacy RpgCombatant + RpgStatsManager (removed in v8.4.0). Supports any number of resources
(HP / Mana / Stamina / DarkMana / Rage / any Custom), any number of stats
(Strength / Defense / FireResist / any Custom), buffs (SO + inline), status effects, two growth
modes (Dota-like and Dark-Souls-like), Save/Load and Mirror multiplayer.
File: Assets/Neoxider/Scripts/Rpg/Components/RpgCharacter.cs В· Menu: Neoxider/RPG/RpgCharacter.
Demo: Assets/Neoxider/Samples~/Demo/Scenes/RpgCharacterQuickDemo.unity - open the scene, press Play, and test Damage/Heal/Stamina/DarkMana/Upgrade with on-screen buttons.
RpgCharacter : NeoNetworkComponent, IRpgCombatReceiver
|-- RpgCharacterTemplate (SO, optional) - start resources / stats / buffs / progression
|-- RpgResourceDefinition[] _resources - HP / Mana / Stamina / Shield / any Custom
|-- RpgStatDefinition[] _stats - Strength / Defense / FireResist / any Custom
|-- BuffDefinition[] _knownBuffs - re-usable SO buffs
|-- InlineBuffEntry[] _inlineBuffs - one-off buffs without SOs
|-- StatusEffectDefinition[] _knownStatuses - DoT / Slow / Stun
|-- RpgEffectShelf (runtime) - single source of truth for buff/status lifetime
`-- RpgProgressionDefinition (SO, optional) - Dota | Souls | Hybrid + upgrade rules
No singleton. Multiple characters per scene is a first-class scenario (player + party + pets + enemies).
RpgStatId = RpgStatPreset + optional customId. The inspector shows a dropdown with common
values (Hp, Mana, Stamina, Shield, Strength, FireResist, ...) plus a custom-string field
that activates when you pick Custom. Same for buff target id.
// 1. Preset
new RpgStatId(RpgStatPreset.Hp) // value = "Hp"
// 2. Custom
new RpgStatId("DarkMana") // preset = Custom, value = "DarkMana"
// implicit conversions
RpgStatId id = RpgStatPreset.Stamina;
string key = id; // "Stamina"Every method takes 0-1 primitive / SO parameter - they appear in UnityEvent dropdowns and can be
called from NetworkContextActionRelay.InvokeComponentMethod, Button.onClick,
PhysicsEvents3D.onTriggerEnter, NeoCondition.OnTrue.
| Method | What it does |
|---|---|
Damage(float) |
HP using buff/status IncomingDamage% + Defense% modifiers |
DamageType(string, float) |
+ specific resist (FireResist, IceResist, ...) |
Heal(float) |
heal HP |
Spend(string id, float) |
spend a resource; returns false when not enough |
Refill(string, float) / Increase(string, float) |
top up a resource |
Restore() / RestoreResource(string) |
full restore |
SetMaxResource(string, float) / AddMaxResource(string, float) |
change Max (buffs / upgrades) |
SpendMana(float), RefillMana(float), SpendStamina(float), RefillStamina(float),
SpendShield(float) - explicit methods for the common pools, visible in UnityEvent dropdowns.
| Method | What it does |
|---|---|
GetStat(string) |
final value = base + level + upgrade + buffs |
AddStatBase(string, float) / SetStatBase(string, float) |
menu / inventory |
UpgradeStrength() / UpgradeDexterity() / UpgradeVitality() / UpgradeIntelligence() / UpgradeEndurance() |
Dark-Souls UI |
UpgradeStat(string) |
universal upgrade |
| Method | What it does |
|---|---|
ApplyBuff(BuffDefinition) |
SO buff (from library) |
ApplyBuffById(string) |
by id (looks up SO and inline) |
ApplyInlineBuff(int index) |
inline entry from _inlineBuffs[index] (pickup buffs) |
RemoveBuff(string) / ClearAllBuffs() |
|
ApplyStatus(StatusEffectDefinition) / ApplyStatusById(string) |
|
RemoveStatus(string) / ClearAllStatuses() |
|
HasBuff(string) / HasStatus(string) |
| Method | What it does |
|---|---|
SetLevel(int) / AddLevel(int) |
raises level. AllStatsEveryLevel auto-applies growth; ManualUpgradePoints grants upgrade points |
AddXp(float) |
|
AddUpgradePoints(int) |
|
CanUpgradeStat(string) / GetUpgradeLevel(string) |
| Method | What it does |
|---|---|
LockInvulnerable() / UnlockInvulnerable() |
stack (used by Evade controller) |
SetInvulnerable(bool) |
direct |
When isNetworked = true and the caller is a remote client, NetDamage, NetHeal, NetSpend,
NetRefill, NetApplyBuffById, NetApplyInlineBuff, NetApplyStatusById, NetAddLevel
dispatch a [Command] to the server. The server applies the change and pushes a snapshot
SyncVar; every client receives. If you use the plain Damage / Heal / etc., they apply
locally only.
SaveProfile() / LoadProfile() / ResetProfile() - writes to PlayerPrefs[_saveKey].
Persists every resource / stat / upgrade-points / active buff / active status by id (universal,
no hardcoded fields).
HpState, HpPercentState, MaxHpState, ManaState, ManaPercentState, StaminaState,
StaminaPercentState, LevelState, UpgradePointsState, XpState, IsDeadState,
InvulnerableState.
Generic: GetResourceCurrentState("DarkMana"), GetResourceMaxState(id),
GetResourcePercentState(id), GetStatState("Strength").
| Header | Contents |
|---|---|
| Template | RpgCharacterTemplate SO + applyTemplateOnAwake. Imports resources / stats / progression from the archetype. |
| Resources | RpgResourceDefinition list. Each: id (preset / Custom), start current / max, regen rules (Flat / Percent / FromStat / *PerTick + pause-after-spend / damage). |
| Stats | RpgStatDefinition list. Each: id, base, optional level growth. |
| Effects | _knownBuffs[] (SO), _inlineBuffs[] (no SO), _knownStatuses[] (SO). |
| Progression | RpgProgressionDefinition SO + optional LevelComponent. |
| Persistence | save key, load on awake, autosave. |
| Authority | None / OwnerOnly / ServerOnly - Command sender filter. |
| Events | OnDamaged / OnHealed / OnDeath / OnRevived / OnBuffApplied / OnBuffExpired / OnStatusApplied / OnStatusExpired / OnLevelChanged / OnResourceChanged(id, value) / OnStatChanged(id, value) / OnProfileSaved / OnProfileLoaded. |
Drop on a UI GameObject, drag the RpgCharacter, pick a resource id (e.g. Custom = "DarkMana").
UnityEvent OnCurrent(float) / OnMax(float) / OnPercent(float) go to Slider / TMP_Text without code.
For text that combines several values, use the generic NoCodeFormattedText instead of a RPG-only UI wrapper.
Same idea for stats. OnValue(float).
- On the player:
RpgCharacterwith oneInlineBuffEntry:id = "BigHpBoost",duration = 60Modifiers[0]:BuffStatType = AddResourceMaxFlat,TargetId = Hp,Value = 20
- On the pickup trigger:
NetworkContextActionRelay:Action = InvokeComponentMethod,Component = RpgCharacter,Method = ApplyInlineBuff,Argument = 0
Button.onClick -> RpgCharacter.RefillStamina(50).
NeoCondition:
Source = RpgCharacter,Property = HpPercentValue,op = <,threshold = 0.3OnTrue->GameOverPanel.SetActive(true)
Slider + RpgResourceBinding (Character = Player, ResourceId = Stamina) ->
OnPercent -> Slider.value.
PhysicsEvents3D.OnTriggerStay -> RpgCharacter.ApplyStatusByName("Poison").
RpgProgressionDefinition with growthMode = ManualUpgradePoints,
upgradeRules = [{ statId = Vitality, increasePerPoint = 1, derivedResourceModifiers = [{ Hp, AddMaxFlat, 15 }] }].
UI button -> RpgCharacter.UpgradeVitality().
RpgProgressionDefinition with growthMode = AllStatsEveryLevel. On level-up from
LevelComponent, every stat with affectedByLevel=true is recomputed.
In _resources[]: Mana (preset) + DarkMana (Custom string). Dark spell:
Button.onClick -> RpgCharacter.Spend("DarkMana", 25) or through NetworkContextActionRelay.
RpgCharacter : NeoNetworkComponent. Enable isNetworked in the inspector and the component
becomes server-authoritative:
- Server authority. Changes via
NetDamage/NetHeal/Net*ride a[Command]to the server. - Snapshot SyncVar. Server serializes every resource / stat / buff / status / level / xp /
upgradePoints / isDead / invulLocks into one snapshot string. Clients receive via
[SyncVar(hook)]and restore local state. - Authority Mode -
None/OwnerOnly(only the owning client) /ServerOnly. - Late join. When a new client connects,
ApplyNetworkState(inherited fromNeoNetworkComponent) applies the latest snapshot.
Multiplayer test:
- Host + remote via
NetworkManagerHUD/NeoNetworkManager. - Pickup trigger on the scene with
NetworkContextActionRelay.InvokeComponentMethod -> RpgCharacter.ApplyInlineBuff(0)- both players see the effect.
An NPC is the same RpgCharacter - no separate component.
- On the enemy prefab:
RpgCharacter+RpgCharacterTemplate(e.g. "Orc"):- resources: HP 80, Stamina 50
- stats: Strength 10, Defense 5
-
NpcRpgCombatBrain(_characterfield points to thisRpgCharacter)
-
RpgAttackController(_characterSource-> thisRpgCharacter)
-
RpgDeathHandler(auto-attaches, listens toOnDeath)
-
- UI through
RpgResourceBinding+SetProgressfor the HP bar andNoCodeFormattedTextforHP / MaxHPtext.
- UI through
RpgContactDamage(selfCharacter-> this character) +targetTag = "Enemy"- damage by proximity.- Alternative:
MeleeWeapon(MonoBehaviour subclass) + trigger collider ->target.GetComponentInParent<RpgCharacter>().Damage(amount).
RpgAttackControllerwithRpgAttackDefinition(deliveryType = Projectile).RpgProjectilespawns from_projectileSpawnPoint; on hit ->Damageon the target'sRpgCharacter.
AuraWeapon(extendsMeleeWeapon) - radius damage on a tick.
- RpgCharacterTemplate - SO archetype
- RpgProgressionDefinition - growth modes
- RpgResourceBinding - NoCode UI binding
- RpgStatBinding
- BuffDefinition, InlineBuffEntry
- Multiplayer_Guide