noobtuts

uMMORPG - The #1 Unity MMORPG

uMMORPG

Content

Introduction

uMMORPG is a simple and powerful Unity MMORPG that contains all the Massive Multiplayer Online Role Playing Game core features, all built with Unity's own UNET Networking system.

uMMORPG is as simple as it gets when it comes to Unity MMORPG development because the Server and the Client are ONE, there is no more separation between them. Unity takes care of it all!

uMMORPG currently contains only about 4000 lines of clean, elegant and easy to understand source code. We designed it in a way that allows you to just run it and start hacking around in it immediately.

Download

You can Download uMMORPG on the Unity Asset Store!

Feel free to take a look at our uMMORPG WebGL Demo first!

Quick start guide


  1. Install and open Unity 5.5.0p3 or newer.
  2. Import the Project from Unity's Asset Store and open the World scene file.
  3. Build & Run it for your operating system via File->Build Settings
    Note: you can also press Ctrl+B to immediately build and run it afterwards.
  4. Select "Server & Play" in the Editor to start the Server and play on it (with the account entered in the Login Mask)
    Note: a Dedicated Server lets you start a Server without playing on it at the same time..
  5. Enter a different account (any one is accepted right now) and press "Login" in the build to see the first two players in your MMORPG.

Architecture Overview

uMMORPG was designed for you to modify. Here is a quick overview for the code and architecture:

General usage advice

If you are a developer then you can either use this project to build your own customized MMORPG on top of it, you can use it as a reference to learn the best way to implement specific MMORPG features or you can even take components out of it and add them to your own game.

We used lots of comments throughout the code, so if you want to learn more, simply take a look at the implementation of the function that you are interested in.

A Beginner's Exercise

Here is a simple exercise to get your feet wet without writing any code: try adding a new 'Universal Potion' item that restores health and mana. Give it a nice description, adjust all the properties and add an icon too. When you are done, give players a way to obtain it in the game world, e.g. by adding it to a monster's drops.

Note: the Tutorial section on items could be useful.

Tutorials

How to add or modify a Player/Monster/Npc Type

Adding or changing entities is not very difficult, but there are a few things to keep in mind. We will go through the process that we used to create the archer from our warrior, one step after another.

First of all, make sure that your 3D model is correctly imported with all the animations:
uMMORPG model change import settings

Drag the Warrior Prefab into the Hierarchy:
uMMORPG model change Prefab to Hierarchy

Then remove the 3D Model child object in the Hierarchy:
uMMORPG model change delete mesh and armature

Now drag the new mesh from your model file (FBX etc.) into it:
uMMORPG drag model into object

If the model is facing into a weird direction, then rotate the model part:
uMMORPG model change rotation

We also rename it to '3D Model' for consistency:
uMMORPG model change rename to 3D Model

Now it should look properly rotated in the Scene:
uMMORPG model change properly rotated

Every animated model needs an animation controller. So let's duplicate the Warrior's controller (CTRL+D) and then move it into the Archer model folder:
uMMORPG model change duplicate controller

Double click to open the Controller in the Animator:
uMMORPG model change controller in animator

Select the Idle state, then drag the archer model's idle animation (it's a child of the model file) into the Motion slot in the Inspector:
uMMORPG model change replace animation

Replace all other state's animations as well. Note that you may have to modify the Transition (the white arrows) Duration times later if your animations stop too abruptly or too slowly.

Now select our GameObject in the Hierarchy again and then drag the archer model's Controller and Avatar into the Animator component:
uMMORPG model change adjust animator component

Each entity also needs a Collider. We could add it to the main GameObject, but it's usually a better idea to add it to the Pelvis bone, so that it follows the animation. Imagine a standing monster and a dead monster that lays on the ground. If we would attach the Collider to the main GameObject, then it would be in the default standing position at all times. If we attach it to the pelvis then it moves around with the Animation and the Collider will stand while the monsters is standing and it will lay on the floor when the monster is laying on the floor. So let's find the pelvis in the model's armature (bone structure) in the Hierarchy:
uMMORPG model change find pelvis

And then add a Capsule Collider to it in the Inspector:
uMMORPG model change add capsule collider

Adjust the Collider properties in the Inspector until the Collider fits the model:
uMMORPG model change capsule collider fit

Players have the ability to equip and unequip items. If a player equips a weapon, then the item's 3D model should be shown in the player 3D model's hand. The code for this mechanic is already written, all we have to do is find the bone that should hold the weapon. 3D Artists usually include a "weaponMount" bone somewhere in the armature:
uMMORPG model change weapon mount bone

If there is no weapon mount yet, then find the left hand bone and add an empty "weaponMount" GameObject to it:
uMMORPG model change find hand bone

And then add the PlayerEquipmentLocation component to the weapon mount in the Inspector. We also set the accepted category to "EquipmentWeapon":
uMMORPG model change equipment location component

Our archer isn't allowed to equip a shield. But if it were, then we would have to add another PlayerEquipmentLocation with the accepted category "EquipmentShield" to the other hand as well.

Now we can adjust the Archer's Player component to our needs. We will keep it simple and only adjust the Equipment Types so that the archer is not allowed to use a shield, and is only allowed to use bow weapons. We will also drag the bow into the Default Equipment list:
uMMORPG model change equipment types

So far, all we did was modify the Warrior prefab in the Hierarchy. We can now either save our changes to the Warrior Prefab, or create a completely different Archer Prefab from it.

If we want to save our modifications to the Warrior prefab, then we can simply press the Apply button:
uMMORPG model change apply modifications
Afterwards we can remove it from the Hierarchy again.

If we want to save our modifications to a new Archer prefab, then we first rename our Warrior in the Hierarchy to "Archer":
uMMORPG model change renamed to archer

Then drag it into the Prefabs folder:
uMMORPG model change drag to prefabs

And then we drag that Prefab into the NetworkManager's Spawnable Prefabs list:
uMMORPG model change spawnable prefabs
Afterwards we can remove it from the Hierarchy again.

How to add a Skill

Adding a new Skill is very easy. At first we right click in the Project Area and select Create->Scriptable Object and press the SkillTemplate button. This creates a new ScriptableObject that we can now rename to something like "Strong Attack". Afterwards we can select it in the Project Area and the modify the skill's properties in the Inspector. It's usually a good idea to find a similar existing skill in the ScriptableObjects folder and then copy the category, cooldown, cast range etc.

Afterwards we select the player prefab and then drag our new skill into the Skill Templates list to make sure that the player can learn it.

How to add an Item

Adding a new Item is very easy. At first we right click in the Project Area and select Create->Scriptable Object and press the ItemTemplate button. This creates a new ScriptableObject that we can now rename to something like "Strong Potion". Afterwards we can select it in the Project Area and the modify the item's properties in the Inspector. It's usually a good idea to find a similar existing item in the ScriptableObjects folder and then copy the category, max stack, prices and other properties.

Afterwards we have to make sure that the item can be found in the game world somehow. There are several options, for example:

How to change the Start Position

The NetworkManager will always search for a GameObject with a NetworkStartPosition component attached to it and then use it as the start position.

uMMORPG has a startpos GameObject in the Hierarchy, which can be moved around in order to modify the character's start position.

How to add more Player levels

Each player Prefab has a Levels property in the Player component. If you want 4 levels, then set the Size to 4. Afterwards you can configure each level's stats, so that a player can have 100 health in level 1, 110 health in level 2, and so on.

How to change the ground or use a different Terrain

We can use just about any mesh or terrain as the ground element. In order to allow entities to move on it, we simply have to make it Static, enable the collider and then select Window->Navigation and press the Bake button in order to refresh the navigation mesh.

How to add Environment Models

Environment models like rocks, trees and buildings can simply be dragged into the Scene. They don't need a Collider, but they should be made Static so that the Navigation system recognizes them.

Afterwards we can select Window->Navigation and press the Bake button in order to refresh the navigation mesh. This makes sure that the player can't walk through those new environment objects.

How to change the Login Screen

uMMORPG uses Unity's new UI system, so everything can be modified easily. The Unity UI Manual has a lot of information on that topic.

If you want to modify the background, you can simply move the camera to another position, for example behind a tree or in front of a camp fire.

How to use another Database System

The Database.cs class is the the only place that has to be modified in order to use another database system like SQLITE or MYSQL.

We decided against using MYSQL for our database, simply because people shouldn't have to setup a whole MYSQL database just to run our Unity MMORPG.

The database currently uses XML files for several reasons, mainly because they are incredibly easy to work with and very fast to read and write. We also tried SQLITE a while ago, but it turned out that it's just far more complicated to deal with (transactions, locks, table initialization, SQL injection, DLL files for Unity, ...) and actually much slower than XML. Saving 1000 players took about 30 seconds with SQLITE and only 2 seconds with XML.

In the end, SQLITE and XML are both just files on our hard drive, so we might as well pick the easier solution.

Note: Item, Skill and Quest templates don't really need to be stored in a Database. Right now they are just ScriptableObjects that can be referenced in the game world, which makes development very easy.

How to modify Database Characters

uMMORPG uses the XML document format for its database. The database can be found in the Project's Database folder above the Assets folder or next to the executable in builds.

The database structure is very simple, it contains folders for accounts and each folder contains XML files for the account's characters. The files can be modified with any text editor.

Characters can be moved to a different account by simply moving them out of one folder and into another folder.

A character can be deleted by simply deleting the XML file.

How to add an Account Database

In a real MMORPG, we would most likely have a Content Management System that manages the Forum, News, Accounts and Item Shop. We could then modify the NetworkManagerCustom's IsValidAccount function to verify the login credentials. The function already contains some example code for HTTP-GET and MYSQL.

How to use another Scene

First of all, we have to understand that the game server can only handle one Scene right now, so our whole game world should be in that Scene. If you want to replace the current Scene, you can either just build on top of it or duplicate it and then modify what you want to modify. Unity doesn't have a Duplicate option for Scenes, but we can open the project folder with a file manager, duplicate the scene file and then rename it.

Note: having multiple Scenes at the same time and allowing players to teleport to them makes sense too. It's very likely that UNET will get a feature like that sooner or later, which would be the best solution. Right now we can't use UNET to connect from one UNET server to another UNET server, which makes transferring players impossible without some really weird workarounds, hence why we don't want to implement that feature just yet.

How to add another attribute like Dexterity

uMMORPG already has strength and intelligence attributes which can be upgraded after each level up. To add more attributes, simply take a look at the Player.cs script, find the Attributes section, duplicate one of the current attributes rename it.

You can then modify the Player's Health, Mana, Damage, Defense properties to include your attribute in the formula.

You can show your new attribute in the UI by first adding elements to the CharacterInfo panel in the Canvas and then updating them with the UIRefresh script where attributes can be found in the UpdateCharacterInfo function.

You will notice that the UI script uses Commands when the player asks the server to increase an attribute. The final step is to add one of those commands to the Player script. This is very easy again, since you can simply copy one of the existing attribute commands and modify it to your attribute.

How to make a 2D MMORPG with uMMORPG

uMMORPG is mostly networking code, it doesn't really matter if your game is 2D or 3D. For example, you could easily make your camera orthographic and make it look down on the player to have a 2D game already (which still uses 3D models).

If you want to make a real 2D MMORPG with sprites instead of 3D models, then you will have to keep a few things in mind:

Other than that, items, quests, skills etc. are all the same.

How to connect to the Server over the Local Network

If you want to connect to the game server from another computer in your local network, then all you have to do is select the NetworkManager in the Hierarchy and modify the Network Info -> Network Address property to the IP address of the server.

Note: you also have to configure both computers so that they can talk to each other without being blocked by firewalls.

How to host a Server on the Internet

You should run uMMORPG in headless mode on a Linux server (recommended) or in batchmode on a Windows server.

For a detailed step by step guide, check out our UNET Server Hosting Tutorial. It recommends a hoster and explains the whole process step-by-step.

Note: it's sometimes useful to also show the log messages in the console. Here is how to do it on Linux:

./uMMORPG.x86_64 -logfile /dev/stdout

And on Windows:

uMMORPG.exe -batchmode -nographics -logfile log.txt
powershell -noexit Get-Content log.txt -Wait

How to update your own modified MMORPG to the latest uMMORPG

uMMORPG's code is likely to change a bit every now and then, so upgrading your modified MMORPG to the latest uMMORPG version could always break something in your project. We recommend to pick the latest uMMORPG version and then develop your own MMORPG with it without updating to the latest uMMORPG version all the time.

If however uMMORPG has a new feature or bugfix that you desperately need, then we recommend the following steps:

Of course, you can always try to just update your current project and hope for the best / fix occurring errors. Just be warned that this might be stressful, because uMMORPG is a source code project. Conventional software can easily be made downwards compatible because the user never modifies the source code directly. But if you modify code that we change later on, then there can always be complications.

Note: we always try to fix all known bugs before releasing a new uMMORPG version, so you really won't have to update to the latest version all the time and can work with one version for a long time instead.

How to keep track of uMMORPG changes in detail

If you want to know every single line of code that was changed between versions, there are several ways to do that:

If you don't know how to use git, here is how you can see version changes with just a few mouse clicks:

Note: please don't put uMMORPG into a public repository on the internet. Git works perfectly fine on your local machine.

Development Info

A list of planned features, bugs and requests can be found in our Official uMMORPG Thread on the Unity forums.

Official Addons

There are several official uMMORPG addons. Some of them were created by us, some of them are services by other people that we found to be the perfect fit for uMMORPG. You can decide which ones to use, we simply share the ones that we will use for our own MMORPG some day.

A Distribution & Patching Solution

Distributing an MMORPG is challenging. There are serveral things necessary:

Taking care of all those things by ourselves would be a full time job already. What we need is some kind of tool or service so that we don't have to worry about any of it.

The Steam platform is a great solution, but it's very difficult to get into it, especially while your MMORPG is still in development.

A great alternative is itch.io. It's like an open source Steam clone that everyone can use. We highly recommend using it for your own MMORPG too.
itch.io

You can get started by registering at itch.io/developers. Upload your game and you will immediately get your custom itch.io URL like yourname.itch.io/yourgame, which you can share with your players already. People that don't want to redownload your game manually every time can simply use the itch.io client, which works just like Steam:
itch.io client

That's it, problem solved!

Community Addons

The uMMORPG community has created a few useful addons that you can implement to your own project.

PHP Account Registration

Kuroato create a simple PHP Account Registration script for uMMORPG:
GitHub.com uReg

XML Account Registration

tvirus06 create a simple XML Account Registration plugin for uMMORPG:
uMMORPG Thread XML Account Registration

Warehouse

ciao00 created a Warehouse for uMMORPG:
Youtube.com uMMORPG Warehouse

Technology Choices

Designing an MMORPG is difficult, there are a lot of technology choices to make. We will explain the most important ones for uMMORPG:

As usual, we chose the simplest solution and made uMMORPG a template for your own dream MMO.

Script Documentation

We will now explain each Script file in detail. Note that the documentation is parsed from the project's script files, so you might as well jump right into the project and learn even more.

AggroArea.cs

Catches the Aggro Sphere's OnTrigger functions and forwards them to the Entity. Make sure that the aggro area's layer is IgnoreRaycast, so that clicking on the area won't select the entity.

Note that a player's collider might be on the pelvis for animation reasons, so we need to use GetComponentInParent to find the Entity script.

BuggyQuest.cs

The Quest struct only contains the dynamic quest properties and a name, so that the static properties can be read from the scriptable object. The benefits are low bandwidth and easy Player database saving (saves always refer to the scriptable quest, so we can change that any time).

Quests have to be structs in order to work with SyncLists.

Note: the file can't be named "Quest.cs" because of the following UNET bug: http://forum.unity3d.com/threads/bug-syncliststruct-only-works-with-some-file-names.384582/

BuggySkill.cs

The Skill struct only contains the dynamic skill properties and a name, so that the static properties can be read from the scriptable object. The benefits are low bandwidth and easy Player database saving (saves always refer to the scriptable skill, so we can change that any time).

Skills have to be structs in order to work with SyncLists.

We implemented the cooldowns in a non-traditional way. Instead of counting and increasing the elapsed time since the last cast, we simply set the 'end' Time variable to Time.time + cooldown after casting each time. This way we don't need an extra Update method that increases the elapsed time for each skill all the time.

Note: the file can't be named "Skill.cs" because of the following UNET bug: http://forum.unity3d.com/threads/bug-syncliststruct-only-works-with-some-file-names.384582/

CameraMMO.cs

We developed a simple but useful MMORPG style camera. The player can zoom in and out with the mouse wheel and rotate the camera around the hero by holding down the right mouse button.

Note: we turned off the linecast obstacle detection because it would require colliders on all environment models, which means additional physics complexity (which is not needed due to navmesh movement) and additional components on many gameobjects. Even if performance is not a problem, there is still the weird case where if a tent would have a collider, the inside would still be part of the navmesh, but it's not clickable because of to the collider. Clicking on top of that collider would move the agent into the tent though, which is not very good. Not worrying about all those things and having a fast server is a better tradeoff.

ConsoleGUI.cs

People should be able to see and report errors to the developer very easily.

Unity's Developer Console only works in development builds and it only shows errors. This class provides a console that works in all builds and also shows log and warnings in development builds.

Note: we don't include the stack trace, because that can also be grabbed from the log files if needed.

Note: there is no 'hide' button because we DO want people to see those errors and report them back to us.

CopyPosition.cs

This component copies a Transform's position to automatically follow it, which is useful for the camera.

Database.cs

Saves Character Data in XML files. The design is very simple, we store chars in a "Database/Account/Character" file. This way we can get all characters for a certain account very easily without parsing ALL the characters.

benchmarks: saving 10 chars: 0.03s saving 100 chars: 0.45s saving 1000 chars: 1.7s

DefaultVelocity.cs

Sets the Rigidbody's velocity in Start().

DestroyAfter.cs

Destroys the GameObject after a certain time.

Entity.cs

The Entity class is rather simple. It contains a few basic entity properties like health, mana and level (which are not public) and then offers several public functions to read and modify them.

Entities also have a target Entity that can't be synchronized with a SyncVar. Instead we created a EntityTargetSync component that takes care of that for us.

Entities use a deterministic finite state machine to handle IDLE/MOVING/DEAD/ CASTING etc. states and events. Using a deterministic FSM means that we react to every single event that can happen in every state (as opposed to just taking care of the ones that we care about right now). This means a bit more code, but it also means that we avoid all kinds of weird situations like 'the monster doesn't react to a dead target when casting' etc. The next state is always set with the return value of the UpdateServer function. It can never be set outside of it, to make sure that all events are truly handled in the state machine and not outside of it. Otherwise we may be tempted to set a state in CmdBeingTrading etc., but would likely forget of special things to do depending on the current state.

Each entity needs two colliders. First of all, the proximity checks don't work if there is no collider on that same GameObject, hence why all Entities have a very small trigger BoxCollider on them. They also need a real trigger that always matches their position, so that Raycast selection works. The real trigger is always attached to the pelvis in the bone structure, so that it automatically follows the animation. Otherwise we wouldn't be able to select dead entities because their death animation often throws them far behind.

Entities also need a kinematic Rigidbody so that OnTrigger functions can be called. Note that there is currently a Unity bug that slows down the agent when having lots of FPS(300+) if the Rigidbody's Interpolate option is enabled. So for now it's important to disable Interpolation - which is a good idea in general to increase performance.

EntityTargetSync.cs

[SyncVar] GameObject doesn't work, [SyncVar] NetworkIdentity works but can't be set to null without UNET bugs, so this class is used to serialize an Entity's target. We can't use Serialization in classes that already use SyncVars, hence why we need an extra class.

We always serialize the entity's GameObject and then use GetComponent, because we can't directly serialize the Entity type.

Extensions.cs

This class adds functions to built-in types.

FaceCamera.cs

Useful for Text Meshes that should face the camera.

In some cases there seems to be a Unity bug where the text meshes end up in weird positions if it's not positioned at (0,0,0). In that case simply put it into an empty GameObject and use that empty GameObject for positioning.

Item.cs

The Item struct only contains the dynamic item properties and a name, so that the static properties can be read from the scriptable object.

Items have to be structs in order to work with SyncLists.

The player inventory actually needs Item slots that can sometimes be empty and sometimes contain an Item. The obvious way to do this would be a InventorySlot class that can store an Item, but SyncLists only work with structs - so the Item struct needs an option to be empty to act like a slot. The simple solution to it is the valid property in the Item struct. If valid is false then this Item is to be considered empty.

Note: the alternative is to have a list of Slots that can contain Items and to serialize them manually in OnSerialize and OnDeserialize, but that would be a whole lot of work and the workaround with the valid property is much simpler.

Items can be compared with their name property, two items are the same type if their names are equal.

ItemDropChance.cs

Defines the drop chance of an item for monster loot generation.

ItemTemplate.cs

Saves the item info in a ScriptableObject that can be used ingame by referencing it from a MonoBehaviour. It only stores an item's static data.

We also add each one to a dictionary automatically, so that all of them can be found by name without having to put them all in a database. Note that we have to put them all into the Resources folder and use Resources.LoadAll to load them. This is important because some items may not be referenced by any entity ingame (e.g. when a special event item isn't dropped anymore after the event). But all items should still be loadable from the database, even if they are not referenced by anyone anymore. So we have to use Resources.Load. (before we added them to the dict in OnEnable, but that's only called for those that are referenced in the game. All others will be ignored be Unity.)

A Item can be created by right clicking the Resources folder and selecting Create -> Scriptable Object -> ItemTemplate. Existing items can be found in the Resources folder.

Monster.cs

The Monster class has a few different features that all aim to make monsters behave as realistically as possible.

NavmeshPathGizmo.cs

Draws the agent's path as Gizmo.

NetworkManagerMMO.cs

We use a custom NetworkManager that also takes care of login, character selection, character creation and more.

We don't use the playerPrefab, instead all available player classes should be dragged into the spawnable objects property.

NetworkManagerMMOUI.cs

Updates the UI to the current NetworkManager state.

NetworkMessages.cs

Contains all the network messages that we need.

NetworkName.cs

Synchronizing an entity's name is crucial for components that need the proper name in the Start function (e.g. to load the skillbar by name).

Simply using OnSerialize and OnDeserialize is the easiest way to do it. Using a SyncVar would require Start, Hooks etc.

NetworkNavMeshAgent.cs

UNET's current NetworkTransform is really laggy, so we make it smooth by simply synchronizing the agent's destination. We could also lerp between the transform positions, but this is much easier and saves lots of bandwidth.

Using a NavMeshAgent also has the benefit that no rotation has to be synced while moving.

Notes:

NetworkProximityCheckerCustom.cs

The default NetworkProximityChecker requires a collider on the same object, but in some cases we want to put the collider onto a child object (e.g. for animations).

We modify the NetworkProximityChecker source from BitBucket to support colliders on child objects by searching the NetworkIdentity in parents.

Note: requires at least Unity 5.3.5, otherwise there is IL2CPP bug #786499.

NetworkTime.cs

Clients need to know the server time for cooldown calculations etc. Synchronizing the server time every second or so wouldn't be very precise, so we calculate an offset that can be added to the client's time in order to calculate the server time.

The component should be attached to a NetworkTime GameObject that is always in the scene and that has no duplicates.

Npc.cs

The Npc class is rather simple. It contains state Update functions that do nothing at the moment, because Npcs are supposed to stand around all day.

Npcs first show the welcome text and then have options for item trading and quests.

Player.cs

All player logic was put into this class. We could also split it into several smaller components, but this would result in many GetComponent calls and a more complex syntax.

The default Player class takes care of the basic player logic like the state machine and some properties like damage and defense.

The Player class stores the maximum experience for each level in a simple array. So the maximum experience for level 1 can be found in expMax[0] and the maximum experience for level 2 can be found in expMax[1] and so on. The player's health and mana are also level dependent in most MMORPGs, hence why there are hpMax and mpMax arrays too. We can find out a players's max health in level 1 by using hpMax[0] and so on.

The class also takes care of selection handling, which detects 3D world clicks and then targets/navigates somewhere/interacts with someone.

Animations are not handled by the NetworkAnimator because it's still very buggy and because it can't really react to movement stops fast enough, which results in moonwalking. Not synchronizing animations over the network will also save us bandwidth.

PlayerChat.cs

We implemented a chat system that works directly with UNET. The chat supports different channels that can be used to communicate with other players:

Note: the channel names, colors and commands can be edited in the Inspector by selecting the Player prefab and taking a look at the PlayerChat component.

A player can also click on a chat message in order to reply to it.

PlayerDndHandling.cs

Takes care of Drag and Drop events for the player.

PlayerEquipmentLocation.cs

Used to find out where an equipped item should be shown in the 3D world. This component can be attached to the shoes, hands, shoulders or head of the player in the Hierarchy. The acceptedCategory defines the item category that is accepted in this slot.

Note: modify the equipment location's transform to mirror it if necessary.

PlayerNameColor.cs

Colors the name overlay in case of offender/murderer status.

Projectile.cs

This class is for bullets, arrows, fireballs and so on.

QuestTemplate.cs

Saves the quest info in a ScriptableObject that can be used ingame by referencing it from a MonoBehaviour. It only stores an quest's static data.

We also add each one to a dictionary automatically, so that all of them can be found by name without having to put them all in a database. Note that we have to put them all into the Resources folder and use Resources.LoadAll to load them. This is important because some quests may not be referenced by any entity ingame (e.g. after a special event). But all quests should still be loadable from the database, even if they are not referenced by anyone anymore. So we have to use Resources.Load. (before we added them to the dict in OnEnable, but that's only called for those that are referenced in the game. All others will be ignored be Unity.)

A Quest can be created by right clicking the Resources folder and selecting Create -> Scriptable Object -> QuestTemplate. Existing quests can be found in the Resources folder.

SkillTemplate.cs

Saves the skill info in a ScriptableObject that can be used ingame by referencing it from a MonoBehaviour. It only stores an skill's static data.

We also add each one to a dictionary automatically, so that all of them can be found by name without having to put them all in a database. Note that we have to put them all into the Resources folder and use Resources.LoadAll to load them. This is important because some skills may not be referenced by any entity ingame (e.g. after a special event). But all skills should still be loadable from the database, even if they are not referenced by anyone anymore. So we have to use Resources.Load. (before we added them to the dict in OnEnable, but that's only called for those that are referenced in the game. All others will be ignored be Unity.)

Skills can have different stats for each skill level. This is what the 'levels' list is for. If you only need one level, then only add one entry to it in the Inspector.

A Skill can be created by right clicking the Resources folder and selecting Create -> Scriptable Object -> SkillTemplate. Existing skills can be found in the Resources folder.

UIDragAndDropable.cs

Drag and Drop support for UI elements. Drag and Drop actions will be sent to the GameObject with the 'handlerTag' tag.

UIKeepInScreen.cs

This component can be attached to moveable windows, so that they are only moveable within the Screen boundaries.

UIRefresh.cs

All Player UI logic in one place. We can't attach this component to the player prefab, because prefabs can't refer to Scene objects. So we could either use GameObject.Find to find the UI elements dynamically, or we can have this component attached to the canvas and find the local Player from it.

UIShowToolTip.cs

Instantiates a tooltip while the cursor is over this UI element.

UITextCopyName.cs

UIWindow.cs

Adds window like behaviour to UI panels, so that they can be moved and closed by the user.

Utils.cs

This class contains some helper functions.