read manual online at
for support please contact
permalink: /manual title: “Overview” sidebar: title: “Manual” nav: manual —
This is the manual for Action Adventure Kit by SoftLeitner. Action Adventure Kit is quite the mouthful so I will be referring to it using the shorthand AAK.
Action Adventures are a very wide, loose genre with all kinds of different games and sub genres. There are some things that many of them have in common though. Lots of them have characters that perform actions. These might have items that change hands and attributes that define their capabilities.
AAK was made to provide a solid foundation for these common ideas within the genre so you can focus on what makes your game special.
Since AAK goes for a broad base of functionality rather than something more specialized it generally tries to do anything in the most default, unity-built-in way possible. For example the movement in the souls demo uses the default unity character controller and the intro is done using timeline. To accommodate for the fact that more special systems may be required for movement, inventory, actions, … AAK was made from the ground up with expandability in mind.
AAK is separated into multiple projects.
The Core Framework of AAK, always import this one.
Contains the soulslike demo, import if you want to start by adapting this demo.
Start up Scenes/Title/SoulsTitle to start the game from the title screen just like the demo does.
To jump directly into the game open Scenes/Dungeon/SoulsDungeon for the level itself, add Scenes/Dungeon/SoulsDungeonTemp for the temporary parts like enemies and crates.
Scenes/Debugging/SoulsDebuggingGeneral is a useful scene for testing out all the actions and Scenes/Debugging/Enemies/SoulsDebuggingEnemies can be used to debug combat.
Scenes/Debugging/Interaction/SoulsDebuggingInteraction can be useful to synchronize the character with some object they are interacting with, this is done using timelines.
The models in this demo were made using blender and then exported to fbx for unity. You can find the original blend files and the used export settings in AdventureSouls/AdventureSoulsBlender.zip.
- Input System allows binding character actions directly to inputs
- Timeline used to provide a character action that waits for a timeline to finish
- Cinemachine used in a helper that performs camera locking using two virtual cameras
- Input System for all the player inputs
- Timeline for the intro and bonfire actions
- Cinemachine for the main camera
- Universal RP
- ProBuilder used to build the environments
This manual is meant to explain the concepts and ideas of AAK rather then any specific detailed API. For more detailed explanations of every class in the core framework and most of the demo please consult the code itself. I try to give a detailed explanation for the purpose of the class in the xml-doc of the class itself and explain every field of the behaviors in the tooltip.
The manual pages for the core systems of AAK are always split into a Core part that explains the idea behind the system and a Souls part that covers how the system was used in that demo.
The Souls section of the manual contains some additional information about how the AdventureSouls demo is set up and how it may be extended.
At least the first update will focus on rounding out and polishing the current core functionality and the souls demo. After that I will most likely start on a second demo game(OoT?, 2d?). Feel free to let me know if you have some features or game types that you’d like to see in the future.
The quickest channels to reach me are mail and discord. Please feel free to reach out with any problems and questions. Feedback regarding the general direction of AAK and particular future features are also always welcome. Though I might not immediately be able to incorporate your requests I very much take them into consideration when planning out future updates.
If you can spare the time please consider leaving a review in the asset store.
permalink: /manual/releases title: “Release Notes” sidebar: title: “Manual” nav: manual —
- manual page for SoulsPlayer(includes step by step guide for replacing the model)
- Animator is now part of CharacterBase, AnimatedCharacterBase is therefore obsolete
- simplified model replacement for SoulsPlayer
- colliders moved to separate GameObject ‘Body’
- TimelineAction and SoulsBonfireAction can pass character animator to the PlayableDirector which lets us remove the dependency between environment and player model
- translation and rotation of model can be suppressed independently
- SoulsAttackAction no longer locks rotation until damage is activated
- MovementSaver can be overridden from outside
- BossArena uses this to properly reset the player if the game is quit during a fight
- intro sequence can now be skipped
- 2021 LTS compatibility
- usable items not being hidden if action is interrupted
- potential initialization order errors
- AttributePool value/stat dictionaries
- CharacterActionArea Bindings
- armor no longer vanishes at certain camera angles
permalink: /manual/character title: “Character” sidebar: title: “Manual” nav: manual —
Characters are the brains of the operation for any entity in the world be it player or NPC. They tie all the other concepts together and implement any logic the belongs to a specific character but does not fit any of the other concepts.(input for players, AI for enemies)
CharacterBase has explicit fields for AttributePool and ResourcePool since these probably wont be inherited from. The actor, movement and inventory implementation can be freely defined when inheriting. CharacterBaseTyped/AnimatedCharacterBase define the fields for theses in a generic manner which makes them convenient to inherit from.
The character base implements a very simple messaging channel that can be used for events that may be used by every other system on the character. Typically messages are received from things like animators or timelines and then used by the current action(animation end>action end) or something like the AudioManager(play sound on animation foot down).
A CharacterInstruction defines some type of state change for a character in a way that can be set and reset. This is done to deal with situation where multiple systems modify the same properties without knowing about each other. For example modifications to the movement speed or the visibility of an item slot. AdventureCore defines some useful general instructions like multipliers for attributes or stats and suspending damages, collisions or movement. See the header of the different instructions for a more detailed explanation of each one.
CharacterInstruction(or CharacterInstruction) can be used as an inspector field despite being abstract because AdventureCore comes with a PropertyDrawer that allows choosing the actual implementation in the inspector.
- SoulsCharacterBase provides some common stagger, guard and parry logic
- SoulsPlayerCharacter manages input(movement, lock-on, menu, …), XP recovery and character reset(bonfire)
- SoulsEnemyCharacter is a very simple enemy that approaches the player and attacks
- SoulsMorningstar character is a specific boss enemy that chooses its attacks based on the position of the player.
permalink: /manual/acting title: “Acting” sidebar: title: “Manual” nav: manual —
An action is basically anything a character can do that may occupy it for a while.
Where the action behavior is defined depends on its use. It could be defined directly on a character so it can be triggered by AI or input(attacks, moves, …). Alternatively it may also sit on some object in the environment and become available to the character by colliding with a CharacterActionArea(Door, Levers, Dialog, …).
The most important methods to override when implementing a new action are:
CanStart returns if all requirements to start are met(key for door, stamina for move).
OnStart is called by the actor when the action is actually started so this is the main point where things are kicked of.
CanEnd defines if an action can be ended by the outside even though it has not ended itself yet.
OnEnd is called by the actor when the action is ended. This is where things are reset for reusable actions or when actions are destroyed if they are one time.
OnMessage is where messages from the character will be directed when the action is active. For example events from the animator that are needed so the action knows when it has ended.
A character actors manages a stream of actions for a character. That means taking care of how and when they are started and ended as well as forwarding the appropriate messages to them.
CharacterActorBase can technically accommodate more than one active action at a time but the most common scenario is that actions are performed one after the other rather than parallel. SerialCharacterActor serves as a good base class for these scenarios. Both the MinimalCharacterActor(ai) and BufferedCharacterActor(player) inherit from it.
Attacks in AdventureSouls have a custom implementation called SoulsAttackAction.
Attacks CanStart when the character has enough stamina and either the action has not started or when it has and it CanCombo. OnStart it triggers an animation and adds an instruction that suspends the characters regular movement so that only the root motion from the animation is used. It also removes the used stamina from the character.
It responds to the following in OnMessage
START confirms that the animation has actually started, this makes sure we are not responding to messages from the wrong animation.
DMG_ON/DMG_OFF control whether the damage on the weapon is turned on. COMBO is sent when the animation is ready to transition to the next swing.
END means the animation has ended and the action should end.
CanEnd is true when the attack CanCombo and the next action is that same attack. OnEnd the attack reset some things including the combo counter if the next action is not itself.
The roll in AdventureSouls uses an action from AdventureCore called MotionAction. This action is useful for rolls, jumps and any other moves that are based on a character animation.
CanStart returns true when is has no cost or when the character has any of the demanded resources left. OnStart removes the cost from the character and sets the animation trigger. If AlignCharacter is checked(which is the case for a roll) the motion calls AlignToInput on the characters movement. Without this the player would not be able to change direction when rolling multiple times in a row because movement is always suspended.
CanEnd is true when RELEASE has been received by OnMessage so we can transition into the next roll before it has ended. OnEnd just resets things.
The gate in AdventureSouls uses an action from AdventureCore called ObjectAction. This is a good action for interacting with objects in the world. It supports one animation on an object you’re interacting with and another(optional) one on an object that should move in the end. It is useful for doors, levers and chests.
An ObjectAction CanStart always unless there is a cost item defined the character does not have. OnStart it moves the character into place and triggers its animation. When ACT is received in OnMessage it starts the animation on the lever and in OnEnd it starts the one on the gate.
permalink: /manual/item title: “Item” sidebar: title: “Manual” nav: manual —
Items are a type of ScriptableObject that defines whether an item can be equipped or used and how it acts when it is. Derive from ItemBase and override the appropriate methods to do so and declare fields for relevant for items of that type(for example visuals). For items that do not have any behavior of their own(key items, currency) the GenericItem can be used. ItemBase also defines some basic common properties that most item systems will use like name, image and categories.
An Inventory is where items are stored, mostly in combination with a character. InventoryBase defines some common ways an Inventory may be interacted with like adding, removing or using. AdventureCore comes with a simple implementation called ListedInventory which just stores items in a list without any limitations to item quantity or stack size. To implement a more specialized inventory, for example a re4 style case, just inherit from InventoryBase and implement the needed methods.
One important distinction to make when working with Inventory is between an ItemQuantity and an InventoryItem. While both of these have an Item and a Quantity they are used very differently. An InventoryItem represents an entry in an Inventory and can be used to react to the quantity of an item a character has and whether it is equipped. An ItemQuantity is not bound to any Inventory or Character and can be used to configure amounts of items that are gained or used when performing some action like picking up items or using a key.
The Inventory of a Character also acts as the access point for its ItemSlots.
ItemSlots enable Items to be equipped to and interact with a character. Deriving from ItemSlot and overriding equip and unequip is the recommended way to create a new kind of ItemSlot. Since they are in scene and exist by character ItemSlots can take care of any runtime data the item may produce when equipped(visuals, effects, …).
The SoulsArmorItem defines a prefab for the visual of the armor when it is equipped. The instancing of that prefab is done by the SoulsArmorSlot which also makes sure the bones on the renderer are set and manages the instance(as in destroys it when unequipped).
When armor is equipped it can also modify some stats, adding the modifier is done in the slot but could also be done in the item since it has no side effects. Lastly the armor defines attribute requirements which are checked by the item itself in its CanEquip.
In addition to the slot-item combination that armor uses, a weapon also has a SoulsWeapon behavior which serves as the access point for a weapons actions and damages in the weapons prefab. It can be used to check the damage through the prefab when the item is stored in the inventory and for the actions when it has been instanced by the slot.
The SoulsWeaponSlot allows binding input to its weapons light and heavy actions. It then rebinds these whenever the equipped weapon changes.
permalink: /manual/attribute title: “Attribute” sidebar: title: “Manual” nav: manual —
Attributes are whole number metrics that, roughly speaking, define a characters capabilities(strength, vitality, ….) but can also be used for any other number that should be persisted and does not fit any other concept(xp). Attributes do not define any behavior of their own, instead other things that depend on them will check them when needed. To add an attribute simply create an Adventure/AttributeType from the context menu in your assets.
In contrast to attributes an AttributeStat does not have a value of its own. Is is usually calculated based on one or multiple attributes or even just a constant value that just gets changed by modifiers. How a stat is calculated is defined by in its GetValue method, derive from AttributeStat to define your own calculations. Check the stats already defined in AdventureCore for examples.(MultipliedStat, TieredStat, …)
The AttributePool manages the available attributes and stats and their value in the scene. It is usually attached and assigned to a character. This is also where modifiers can register to change exposed values and where observers can register to be notified of changes of attributes and stats.
The SoulsVitality attribute can be leveled up at bonfires and influences the SoulsHealthMaximum stat which defines how many hit points the player has. On enemies the hit point maximum is set directly without using a stat.
SoulsEndurance is pretty much the same but for SoulsStaminaMaximum.
SoulsStrength can be leveled at the bonfire and influences the SoulsPhysicalAttack which is used by weapons to calculate their damage.
SoulsLevel and SoulsExperience are counters that are used to check if the player can level up and how many times they have done so.
Lastly SoulsFlask defines how many flasks are restored to the player when they sit at a bonfire. There is no way to change it currently but it has been added so increasing it with a pickup or some other action can be implemented later.
The stats SoulsPhysicalDefense and SoulsPoiseMaximum are not influenced by any attribute, they just have some base value and are only increased by modifiers like armor.
permalink: /manual/resource title: “Resource” sidebar: title: “Manual” nav: manual —
Resources are floating point metrics that can change on a frame to frame basis. A resource has a resource type which is mostly used to identify it and a ResourceValue behavior which actually holds and changes the value. The default ResourceValue does not change on its own. For more specialized resource values that change their value over time or by some other means you can inherit from ResourceValue(look at ChangingResourceValue for an example)
Resources are managed by a ResourcePool which can be used to check, change and monitor resource values.
SoulsHealth is a simple ResourceValue that does no change on its own. It is checked after a character receives damage to see if they die.
SoulsEndurance is a custom behavior in AdventureSouls called SoulsStamina. This is similar to a ChangingResourceValue but also subtracts from its value when the player is sprinting.
SoulsPoise is a resource value that defines whether the character gets staggered by a hit. It gets damaged by attacks and then refills on its own.
permalink: /manual/movement title: “Movement” sidebar: title: “Manual” nav: manual —
The movement is where all the traversal logic for a character is located. Movements will probably vary quite a bit depending on if it is meant for the player or some NPC and also depending on the game. This is why MovementBase defines mostly ways for other components to interact and interfere with movement in some general ways. For example it gives other components a way to slow movement down, suspend it when some animation plays or force it to move somewhere. Any more specialized logic will have to lie in the implementation. Conveniently the generic base classes for characters(CharacterBaseTyped, AnimatedCharacterBase) allow us to declare the type in the class header which lets us use the implementation directly from inside the character or any other component that references the character implementation rather than CharacterBase.
AdventureSouls uses the CharacterControllerMovement for its player, the SoulsPlayerCharacter send all the necessary input to it. The zombie enemies use the NavMeshAgentMovement implementation in combination with NavApproachAction so that they can follow the player around the level. Lastly the Morningstar boss uses ManualMovement since it does not really do any traditional movement. Even if the Morningstar had more movement of its own a nav mesh would not really be necessary. The boss arena is a simple rectangle and there is no way for the boss to leave to as long as it aligns itself to the player and walks it will always get to them.
permalink: /manual/persistence title: “Persistence” sidebar: title: “Manual” nav: manual —
Persistence in AAK is built as simple as possible for the consuming components. Therefore we will start exploring persistence from this side and work our way towards the persistence management.
Most built in components of AAK simply reference a PersisterBase to keep their own persistence logic as slim as possible. That PersisterBase has methods for checking if a value has ever been set, retrieving it, setting it and clearing it out. For example the ObjectAction just calls Set(true) when it is triggered and whenever it is started in the future(scene/game reload) it calls Get
Persisters can come in different forms but there is one called ManualPersister that is meant specifically for the case above where some other component needs to save its state. The persister has a field for a key which is needed to identify its data and one for the area. A persister is convenient to keep persistence logic out of game logic but not necessarily needed, the PickupAction for example just deals with persistence itself without using a separate persister.
Another kind of persister is the DestructionPersister which simply sets a bool when it gets destroyed and destroys its GameObject if that bool has been set in the past. This means you can just add this persister to any destructible object to persist the destruction without any other scripting needed.
A PersistenceArea is a ScriptableObject found in Adventure/PersistenceArea that groups together data that will be saved together. This can be useful to separate smaller data that is saved frequently from larger data that is saved less frequently. The PersistenceArea also has the IsGlobal flag which is meant for data that is saved independent of save slot(settings for example).
The PersistenceContainer is the central singleton manager for persistence that is needed in every scene that uses any kind of persistence. This is where all the persistence data is managed and eventually sent to the saver that actually saves it to a storage medium. As you might have guessed from the above ObjectAction example state persistence in AAK is pushed rather than pulled. This means that state is not collected when a save game is created, instead state is sent to the container whenever it changes and the container decides when it actually saves the state. The container can be set to AutoSave so that is saves at the end of the frame whenever anything has changed, otherwise a Save() has to be called by some outside component like a save button.
In the inspector for PersistenceContainer you can find some useful helper buttons that can be used to deleted data when debugging or to check the keys of the persisters in the scene for duplicates. It can also generate random GUID keys for any persisters with an empty key field. So if you have objects that do not necessarily need a readable key just leave the key in their prefab empty and generate them all before you use the persistence.
As mentioned above the container does not save to disk itself, instead it references a PersistenceSaverBase for that purpose. This is done so that the ‘device-facing’ part of persistence is easily replaceable as I anticipate it might have to be customized depending on the built platform and other factors.
State in AdventureSouls is split into a couple different areas. SoulsSystemPersistence is a global area independent of the save slot that is used for settings like the sound effects volume but also to save a short info structure for every save index that is displayed in the title screen. SoulsPlayerPersistence is just used by the player character, the player gets its own area because it is saved quite frequently. The SoulsPermanentPersistence is used to save permanent world state like collected items or pulled levers. Lastly SoulsTemporaryPersistence is where any state resides that is discarded whenever the player changes the level or sits at a bonfire. It contains the state of the enemies and destructible environment objects.
The PersistenceContainer is part of the SoulsSetup prefab which contains all the necessary setup to run the game. Basically if you create a new scene and add the setup as well as a plane for the player to stand on you can start the game and it’ll work. If you check the container on the setups in the debugging scenes like Scenes/Debugging/SoulsDebuggingGeneral you may notice some overrides. For one the key is overridden so that data saved for that debug scene does not override data from the actual game scenes. Also the saver has been removed for most of them, this completely disables persistence because for most debug scenes a complete reset is more useful. If you want to debug the persistence logic you have to reassign or revert that saver.
permalink: /manual/damage title: “Damage” sidebar: title: “Manual” nav: manual —
Damage in AAK is a multi stage process that lets a sender, receiver and kind of damage interact. In PreDamage the sender and receiver are informed that a damage is about to occur between them, they both have the chance to completely cancel the damage here. During OnDamage each kind of damage that the sender has is packaged into a damage event that gets send to all the participants. This is where a senders and receivers can modify the damage value and where the DamageKind applies whatever effect the damage has. Finally in PostDamage the sender and receiver have a chance to react to the combined changes of the applied damages.
An IDamageSender is any component that causes damage occurences. It can be implemented by any class that sends damage. You can Use the static DamageEvent.Send to send your damages. AAK comes with a TriggerDamageSender that uses that regular Unity trigger messages(OnTriggerEnter, …). By default it only sends damage when a TriggerDamageRecevier first enters but it can also be configured to send damage in intervals or at the end.
AAK also comes with the DestructibleDamageReceiver which destroys(or replaces) its gameobject when it gets damaged. This is ideal for destructible environment object or any other object that needs to get damages but does not warrant a full character.
Both the TriggerDamageSender and the TriggerDamageReceiver forward all their damage calls to the character they are attached to(if any). Therefore if we want to react to any kind of damage done to a character we can conveniently do that in the character implementation. The SuspendSendDamage and SuspendReceiveDamage character instructions hook in here.
Damages can theoreticalls be anything, what exactly a damage does is decided by the DamageKind implementation. The most common kind of damage is removing a resource(HP) from a characters ResourcePool. AAK comes with the ResourceDamage damage kind which does exactly this.(ContextMenu>Aventure/ResourceDamage)
Somewhat more complicated than a lot of other games damage in the souls demo is split into physical and poise damage. Poise damage is generally used to signify the brunt of an attack rather then the pure health malus.
The base character defines a lot of the damage handling in the demo. Parries are checked in PreDamageReceive so that the damage can be cancelled if a parry succeeds. In OnDamageReceive the damage value is reduced by defense or set to 0 when a character is guarding. In PostDamageReceive it checks if the charcter dies or is staggered as a result of the damages applied.
One thing we need to make sure is that a player does not damage itself. We could theoretically just cancel any damage that a player weapon might do to the player in PreDamage but using Layers is far more convenient and performant.
The AdventureSouls demo has various Layers that control which objects can interact with each other. Check the Pyhsics settings to see how exactly they are configured.
The player has a general Player Layer that is used for any kind of logical interaction like entering areas or object interactions. The PlayerBody Layer is used to receive damage and interact with physics objects like derstroyed crates. In the current demo the body, just like the logic, uses a simple capsule collider. To get more exact hitboxes and more interesting phyiscs interactions the PlayerBody is the one that should be changed to have more detail. Lastly PlayerDamage is used on any weapons the player uses and interascts mostly with EnemyBody.
The Enemy has a very similar setup to the player with the Enemy, EnemyBody and EnemyDamage Layers. There is also a NeutralDamage Layer that is used by traps so they can send damage to either character. The Trigger Layer is used for logical area to make sure these do not interact with damages or physics at all.
permalink: /manual/souls-player title: “Souls Player” sidebar: title: “Manual” nav: manual —
The following is an overview of the SoulsPlayer prefab in the AdventureSouls demo.
The main transform contains the following components.
- ManualPersister used to save any state related to the player
- CharacterControllerMovement and the CharacterController it uses
- MovementSaver automatically saves the movement data
- Rigidbody and CapsuleCollider which are used by
- GenericTriggerItem with Key PLY which triggers GenericTriggerAreas in the environment(for example the traps in the dungeon)
- CharacterActionArea which is used by the character to detect and start actions in the environment(doors, chests, …)
This transform gets rotated by the movement to face the direction the player is moving.
Contains the TriggerDamageReceiver that receives damage. It also has a second CapsuleCollider with IsTrigger unchecked which pushes around decorators like smashed crates. The components of the Body GameObject were originally located on the Model but have been moved into a separate GameObject to make model replacement easier.
For the sake of simplicity and performance the collision model for the player only consists of a simple capsule. If a more detailed model is required do the following:
- Move TriggerDamageReceiver and Rigidbody to your Model they use any collider in the players model
- Delete the Body GameObject
- Change the Layer of Model to PlayerBody
- Create detailed colliders in the Armature of the model, skip if your model already comes with colliders
This is where the visuals of the player are located. It contains the Animator along with an AnimatorProxy that passes along events and root motion from the animator to the character.
Some other components of AdventureSouls depend on the players model and have to be reassigned if the model is replaced. The following steps show how the player model could be replaced by the zombie model that is usually used by the enemies.
- Open up the SoulsPlayer prefab
- Drag the Models/Characters/SoulsZombie into Pivot
- Add an Animator and an AnimatorProxy to it
- Assign the SoulsPlayer Controller and SoulsPlayerAvatar Avatar to the Animator
- Assign the SoulsPlayer as the Character for AnimatorProxy
- Completely expand the old and new models
- the original armature will contain Left/RightHand transforms under its Hand.L/R transform, drag those over to the new models Hand.L/R(these are used to instantiate items by the weapon and usable item slots)
- Delete the original Model
- In the ArmorTop/Bottom item slots assign CharacterBody to the now missing Template field, it is needed so the armor moves properly with the character model
- On the SoulsPlayerCharacter script reassign the missing Animator to the one you just created and set SoulsZombie as the Model that is replaced by the ragdoll
- At the bottom of SoulsPlayerCharacter you can empty out the HeadRenderer field, it is used for the character customization sliders but the zombie model does not have the needed blend shapes
When you now open up SoulsDebuggingGeneral you should be able to move around and perform actions with the Zombie. If you start the game through the title you’ll see that things there are mostly unchanged but when you start a game the model is in fact changed.
The process to replace the model may be different depending on the model used but generally, as we have seen above, the following dependencies have to be satisfied.
- animator and model on SoulsPlayerCharacter
- hand transforms and body renderer for the item slots
The Critical GameObject holds the actions and triggers necessary for ripostes and backstabs.
The SoulsCriticalAction is the one performed by the player, it uses a GenericTriggerArea to find potential enemies that may be critted. When it is started it forces the enemy to perform the SoulsCrittedAction which disrupts anything it was doing. This action moves the enemy to the Front(riposte) or Back(backstab) transform in order for the animations to line up.
All the actions a player can perform on its own as well as the actor are found here.
- Sit is not really in use currently but serves as an example of a gesture that is performed until some other input arrives
- Turn is started by the movement when the character makes a sharp turn
- Roll is started by the SoulsPlayerCharacter when dodge is pressed and the input direction is not neutral, in the Starting/Ending events in the inspector you can see that it activates a damage while it is active.(the damage has value 0 so it destroys boxes but does not hurt enemies)
- Dodge is started by the SoulsPlayerCharacter when dodge is pressed and the input direction is neutral
- Jump is directly bound to the Act.Jump input by SoulsPlayerCharacter
- Stagger is started by the SoulsCharacterBase base class that the player has in common with the enemies when the character runs out of poise from being hit
- GuardBreak is started by the SoulsCharacterBase when a character guards and runs out of stamina or it is parried while attacking
- Death is started by SoulsPlayerCharacter when it gets hit and health runs out, notice the SignalReceiver which calls the ResetDeath method
Holds items, item slots and inventory. You can add entries to the Items field on the ListedInventory to make the character start out with certain items which is quite useful for debugging.
- Usable is a special item slot that is just a placeholder for the three slots it has as its children. This lets us bind input and UI to that single item slot. Which one is currently active can be switched through using the F key.
- ArmorTop/Bottom are slots for SoulsArmorItem, they need a reference to the CharacterBody in order to copy the bones over to the armor they instantiate which makes the armor mesh move with the character
- WeaponLeft/Right are slots for SoulsWeaponItem, they have a target transform inside the character models armature which they parent their meshes to, the weapons then move because they are children of the characters hand bone. Also notice that the weapon slots have fists as their fallback item, otherwise the character would have no actions to perform when no weapons are equipped