Do the Game - Unity Tool Asset (In Developement)

Unity3D C#

This tool specializes on creating top-down games like RPGs, Zelda-likes, Tower-Defense-games or City-Builder.
It is inteneded to help Solo-Developers create a full fledged game and novices to get into unity game development.
It is heavily inspired by RPG Maker, comes in handy for gamejams, but it is also very useful for easily creating game prototypes or as starting point for any professional top-down game project.
It comes with a powerful architecture and some useful thought-concepts and principles to prevent your project to blow up in scope, configurations or work-steps for the Game Designer.
With this tool you can really create your favorite game in a short amount of time with little effort.


Features:

Prevent your project to be messy or grow exponential complexity with configs.
No hidden configs in prefabs.
Every feature has a category in the database and should be edited there.




You can create multiple Databases.
You can change the categories and GUI-drawer / entry-types for each category


When selecting a model you can choose your own model type with its own setup and either a 2D or 3D representation (or both).

You can also select from existing model assets in your project.


When using the PixelArtEditor to create the model-graphics you can also click on the pen-button to jump right into editing your model-sprites.
Models implement the IModelConfig interface.
This flexability also allows the GameDesigner to create quick prototypes with rough pixel art and exchange the models to 3D at a later point in development.

                      public interface IModelConfig : IIconAsset
                      {
                          Sprite PreviewSprite();
                          Object PreviewAsset();
                      }                  
                      

Create your own types for energy and stats, etc. without the need to go into code.
ID Configs are Project assets and can be linked in the project/ the database.

An enum can be generated out of the ID Configs to be able to use it in the code without linking the asset in a serialized field.
Most ID Configs have icons to quickly visually identify it in the database.

Example icons in database:

Example implementation:

                      /// <summary>
                      /// Can be used to group skill, make skills available for specific classes etc.
                      /// </summary>
                      [EditorIcon("icon-id")]
                      [Serializable]
                      public class SkillType : IDAsset, IIconAsset
                      {
                          public Sprite Icon;
                          public Sprite AssetIcon => Icon;
                      }
                    

Many RPG-systems hardcode things like life, stamina, attack and defense. But this approach has the huge advantage of being quite flexible with energies, stats and other various types.

Create flows of actions for game events and dialogue.
Actions are configs. You can click on the Action to configure it in an inspector window.

Actions use a factory-pattern implementing the IActionConfig and IBaseAction interface.

                      public interface IActionConfig : IScriptableObject
                      {
                          IEnumerable<string> Format { get; }
                          IBaseAction CreateAction();
                      }
                      public interface IBaseAction { }
                      public interface IDefaultAction : IBaseAction
                      {
                          void Invoke();
                      }
                      public interface IUpdatingAction : IBaseAction
                      {
                          bool IsFinished { get; }
                          void Init();
                          void Update(float dt);
                      }
                    
Setting up the Actions:
(Similar to Tasks)

I have also experimented with Node-Graphs (like UE Blueprint, Shadergraph) the past,
but concluded that the vertical nested-config approach is more readable
and easy to work with when using readable Format outputs for the IActionConfig implementation. (Highlighted texts, inspired by RPG Maker)

Create AI with task flows.
Tasks are configs. You can click on the Task to configure it in an inspector window.
In the Game the first task, that is applicable is chosen.

Taks use a factory-pattern implementing the ITaskConfig and ITask interface.

                      public interface ITaskConfig : IScriptableObject
                      {
                          // provides a readable highlighted text output for this config 
                          IEnumerable<string> Format { get; }
                          ITask GetAction(GameObject actor);
                      }
                      public interface ITask
                      {
                          void UpdateTarget();
                          TaskState CanExecute();
                          ICommand GetCommand();
                      }
                      public enum TaskState
                      {
                          CannotExecute,
                          Evaluating,
                          ReadyToExecute
                      }
                    

A task (fe.: Gather Items) will first update its potential targets (entities or interactions for interactable entities),
pick the best one and get a path on how to reach it.
This can take some time, so TaskState.Evaluating is returned. For execution the task itself will return a command. Commands are small executable actions like moving or interacting (picking something up).

Setting up the AI:
If you don't want to use the task-system you can also use other configs for AI, inheriting IAIBehaviourConfig.


Using the task-system: (Similar to Actions)

Commands are small executable actions like moving or interacting with something.
They are used in Task-flows (AI) or by ICommandControls (player input driven)

The probably most common commands are
  • MoveCommand for moving a step,
  • InteractCommand for executing an IInteraction.
  • and SkillItemCommand, which is used to execute skills and using items.

There are also a lot of other commands like JumpCommand, PushCommand or Item-Commands like dropping items on the ground, exchanging some item with inventory or destroying it...

Implement your own commands according to your game needs.

                      /// <summary>
                      /// commands are small actions that can be executed by agents,
                      /// AI-evaluation picks best command via tasks, 
                      /// agent only has one command at a time and picks the next command
                      /// once it is done
                      /// </summary>
                      public interface ICommand
                      {
                          bool Done { get; }
                          void Execute(float delta);
                      }
                    

                      public interface ICommandControls : IInputActionReceiver
                      {
                          /// <summary>
                          /// retrieve command, take over responsibility
                          /// </summary>
                          public ICommand GetCommand();
                  
                          void UpdateControl(float delta);
                          void Clear();
                      }
                    

Create interaction possibilities with objects.
Interactions can be used for player-interactions and/or NPC-interactions.

For example you can use interaction-configs for Buildings to define what you can do when interacting with it.
This way we can have all interactions nicely decoupled and avoid monolythic classes.

Interactions use a factory-pattern implementing the IInteractionConfig and IInteraction interface.

                      public interface IInteractionConfig : IScriptableObject
                      {
                          IInteraction CreateTaskTarget(IInteractiveEntity entity);
                      }
                      /// <summary>
                      /// Interface for specific actions on targets.
                      /// Used for player-interaction to check if possible or 
                      /// for AI to also figure out the priority
                      /// </summary>
                      public interface IInteraction : IPositioned
                      {
                          IInteractiveEntity Entity { get; }
                          
                          bool IsTask(IEntity actor);
                          int TaskPriority(IEntity actor);
                          bool CanInteract(IEntity actor);
                      }
                    
Setting up the Interactions:


When there are multiple interactions on the same target location,
the player can choose his intention.

FeatureTraits are features or traits that are activated by default for specific actors, plants, creatures or buildings.

Or they get activated during the course of the game by
  • changing the job or equipment,
  • or by aquiring an ability ,
  • or being affected by a state, monument or shrine.

So you find FeatureTraits to be configured in a lot of categories in the RPG-database.


                      public interface IFeatureTrait : IScriptableObject
                      {
                          public string Name { get; }
                      }
                      public interface IActivatingFeatureTrait : IFeatureTrait
                      {
                          void Activate(GameObject actor);
                          void Deactivate(GameObject actor);
                      }
                      public interface ITickingFeatureTrait : IFeatureTrait
                      {
                          void Tick(GameObject actor);
                      }
                      // You can also implement a feature trait as Stat-Modifier
                      public interface IStatModifier
                      {
                          void GetStatModifications(List<StatBuffData> stats, 
                                                    List<EnergyBuffData> energies);
                      }
                    
Some examples for features are changing skills, abilities, allow or restrict equipment, changing stats and energies.

Adding a skill via Job or equipment:

Example features for poison-state

Example features for resist-state


(inspired by RPG Maker)

Effects get applied when executing a skill or using an item.


                      public interface IEffect : IScriptableObject
                      {
                      }
                      // An effect that applies to the excecution of the skill 
                      public interface ISkillModEffect : IEffect
                      {
                          // custom data will contain excecution data for the skill
                          void Apply(object customData);
                      }
                      // An effect that applies to the target positions, independent of target-entities
                      public interface IPositionEffect : IEffect
                      {
                          void Apply(Vector3Int position, object customData);
                      }
                      // An effect that applies to entities on the target-positions
                      public interface ITargetEffect : IEffect
                      {
                          void Apply(IEntity actor, IEntity target, object customData);
                      }
                    

When using Form-system you can define target-areas for secondary damage and effects. These get only applied on perfect invocations (similar to ForTheKing)

Some examples for effects are
  • adding buffs or states to the targets,
  • modifying the attack by guaranteeing a crit,
  • ignoring armor / resistance,
  • or adding splash damage/ recover to the attack (similar to ForTheKing)

Some example effects:


(inspired by RPG Maker)

Special Abilities can trigger during combat or at other times when conditions are met.
similar to ForTheKing


                      public interface ISpecialAbility : IScriptableObject
                      {
                          public void Apply(IEntity actor, object customData);
                      }
                      // actors have special abilities
                      public interface IHaveSpecialAbilities
                      {
                          IEnumerable<SpecialAbility> SpecialAbilities { get; }
                          
                          void Add(SpecialAbility ability);
                          void Remove(SpecialAbility ability);
                          
                          bool HasAbility(SpecialAbility ability);
                      }

                      // hook-evaluations are used to test whether to trigger an ability 
                      public interface IHookEvaluation : IScriptableObject
                      {
                          bool Activate( // the actor for which the hook is evaluated (can be actor or target in eventData or neither)
                              IEntity actor, 
                              // the event that has been triggered
                              HookTriggered eventData, 
                              // custom Data, that is not specific to the hook (like custom data in eventData),
                              // but bound to the actor and component for which the hook is evaluated
                              // f.e. for states it can be how many ticks the state has been active,
                              // for abilities the last tick it was triggered, etc.
                              // can be null
                              object customHookEvaluationData);
                      }
                      public struct HookTriggered
                      {
                          public TriggerHookID Hook;
                          // can be null if global hook
                          public IEntity Actor;
                          // for TargetEffects
                          public List<IEntity> Targets;
                          // custom data to evaluate hook (specific to the hook, like combat data in case of combat-hook)
                          public object CustomData;
                      }
                    
(Hooks are also used to remove affliction-states)
Abilities are quite unique and trigger randomly at specific points (using TriggerHook).
They make the combat feel alive, dyncamic and provide some surprise
Some examples for Special Abilities
  • receiving a buff in form of an inspiration,
  • directly countering an attack,
  • negating all party-damage,
  • finishing an enemy, ignoring its HP
  • supporting/ encouraging another character who attacks or defends

You could also use special abilities to implement something like darkest-dungeons random act-outs of afflictions or virtues.
This is how you could setup the Black-Hole ability from For the King


A Quest can have multiple quest-objectives and failure conditions.

                    public interface IQuestConfig : IScriptableObject
                    {
                        IQuestObjective CreateQuest();
                    }
                    public interface IQuestFailConfig : IScriptableObject
                    {
                        IQuestFailCondition CreateFailCondition();
                    }
                    public interface IQuestObjective
                    {
                        bool Locked { get; }
                        string ShortText { get; }
                        bool IsFinished { get; }
                        void Start();
                        void End();
                    }
                    public interface IProgressQuest : IQuestObjective
                    {
                        // QuestObjective can be used as ProgressQuest or not
                        // depending f.e. on amount of items to collect or creatures to kill
                        bool IsProgressQuest { get; }
                        float MissionProgress { get; }
                    }
                    public interface ITimedQuest : IProgressQuest
                    {
                    }
                    //...
                    
Some example quest-objectives are
  • retrieving or gathering items,
  • delivering items,
  • building a construction,
  • crafting an item,
  • killing creatures,
Failure conditions could be a timer or death of an NPCs.

Some example quest-setup:

The tool brings along its own Tile Editor. (using my learnings from an earlier approach)
It builds upon the Unity 2D Tilemap Package and improves its usability.

  • by automatically selecting correct layers when painting specific tiles
  • by enabling you to use similar AutoTiling-Rules as the RPG Maker does (using an underlying Grid with 2x resolution)
    You can use the Tool "Spritesheet-Slicer" to automatically create a Tilemap-Palette with according Tile-Types (RuleTiles, Animated etc.)
    from a Spritesheet with a specific layout. Spritesheet-Settings define which areas use which Rule-Template.
    Set it up once and update your Tilemap-Palettes with one click.
  • by adding Tile-Build-Rules, which can modify the surroundings and Event-Objects when painting specific Tiles.
    With those Builders you can automatically connect staircases and drag items into containers etc. (similar to what Super Dungeon Maker does)
  • add Event-Objects for Story-/ Gameplay-Progress-related events or dialogue. (inspired by RPG-Maker)

Use UI Styles to unify and easily update all your UI elements. Prefabs cannot be used for this purpose.
Also sometimes Unity native solutions for buttons or other elements are insufficient.
The UI Style system works similar to css styling. You can add or remove a StyleID to change the styling.
Add style-definitions for specific StyleIDs or a combination of StyleIDs to set the properties for your UI elements.


Progress:

TODO:
  • A feature wizzard for setting up your game. Here you can choose whether you want an RPG or city builder or hybrid of all those gameplay features.
    The database is then setup according to your favored design.
  • Game-Examples: A variety of example games (at least 2) with different combat systems.
  • More Content: 2D Pixelart and pre-made Database configurations.
  • Bugfixes and Polish