Skip to content

NyuEntities System

Mariusz edited this page May 21, 2020 · 4 revisions

NyuEntities is the newest version of WarWolfWorks Library's Entity system, and the successor of the now deprecated EntitySystem. It is located in the WarWolfWorks.NyuEntities namespace.

Usage & Purpose

(If you know what an entity system is, you can skip this part)

An entity system is one of the best and most reusable way of coding a game with a lot of interactions between the Player, NPC's and other similar entities in a game; This approach is also very performant and consistent across the board, and is almost required by larger projects; But you might be asking "Why is it not used so often then?" or "Why have I never heard of it before?" Well, the answer is simple: It's a pain in the ass to set up. The overwhelmingly negative aspect of an entity system is the unfathomable amount of boilerplate it takes to code even the foundation of such system, let alone a functioning one.

And as you might have guessed, this library contains such system, not only that, it contains dozens of premade components to remove boilerplate even further!

How it works

The core script of every entity is the Nyu class, with all of it's components deriving from either NyuComponent or INyuComponent. All NyuComponent and INyuComponent components have a reference to their respective parent named NyuMain which is assigned automatically by the parent. (for INyuComponent, the NyuMain property must have a setter for it to be assigned)

To call unity methods inside either the parent or it's components, instead of doing so like you would usually on a MonoBehaviour script, simply implement the interface of the according method that's located in the WarWolfWorks.Interfaces.NyuEntities namespace.

Example

Instead of doing this:

public class KujoJotaro : MonoBehaviour
{
    void Awake()
    {
        Debug.Log("This is the awake method!");
    }
}

You would do this:

using WarWolfWorks.Interfaces.NyuEntities;

public class KujoJotaro : NyuComponent, INyuAwake
{
    void INyuAwake.NyuAwake()
    {
        Debug.Log("This is the awake method, Ora!");
    }
}

Important note: Calling normal unity methods (like in the first example instead of the second one) will result in bad execution order, which will result in exceptions, which will likely break your game.

You can also make any of these methods overridable through deeper inheritance by simply making the method public instead of explicit for it's interface:

using WarWolfWorks.Interfaces.NyuEntities;

public class KujoJotaro : NyuComponent, INyuAwake
{
    public virtual void NyuAwake()
    {
        Debug.Log("This is the awake method, Ora!");
    }
}

If in doubt, you can always check a NyuComponent or a Nyu's supported interfaces by simply hovering your cursor over them in your favorite script editor, as ALL of them have an XML comment stating their compatibility: If a Nyu method alternative is not displayed or indicated to be compatible, you can safely use the unity method instead.

Instantiation and Destruction

To instantiate or destroy a Nyu entity, you cannot use the standard UnityEngine Instantiate and Destroy methods. Instead, you need to use NyuManager.New or NyuManager.Destroy located in the same namespace as the Nyu class.

Inspector and Custom Editors

Once you make a class that derives from Nyu, say, a Player class, add it to a game object, you will notice something:

This is a fancy-pants editor! Oh no! What are you gonna do?!?!?!

First, calm down, second, simply click on the "Add" button, which will show a menu of all possible NyuComponents you can add to this Nyu entity:

In here you simply click on the component you wish to add, then click on confirm.

The important part to note is that all component scripts' inspectors are removed:

And will be placed inside the parent class' components window:

(Which can of course be expanded)

But what if you want to make a custom editor?

You can simply create a new script inside a "Editor" folder in your project, then either:

  1. Make that script implement the INyuComponentEditor.
  2. Make that script implement the INyuSerializedEditor.

(for more info, click on the script classes to check out their individual functionalities)

Handling the Parent and it's Components

To retrieve a NyuComponent or a INyuComponent from the parent, simply use GetNyuComponent<T>(), or it's shorter version, GNC<T>() (Also has a non-generic type search overload method). If you wish to retrieve the parent from any INyuComponent or NyuComponent, simply access their NyuMain property.

As an example, let's say you want to make any entity that enters an area float upwards, then access the entity to ping it with an interface (this is only an example, please don't do that, it's here just to make the explanation above easier to understand)

public sealed class AirborneZone : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
        if(other.TryGetComponent(out NyuMovement entityMovement)) //Retrieves the entity's movement script
        {
            entityMovement.AddVelocity(new Velocity(Vector3.up)); //Adds an upwards velocity so it actually goes upwards
            if(entityMovement.NyuMain is IAirbornePingable airtity) //Checks if the movement script's parent entity implements a IAirbornePingable
                airtity.PingAirborne(); //Pings it
            if(entityMovement.NyuMain.TGNC(out NyuState stateHandler)) //TGNC is the shorter version of it's TryGetNyuComponent<T>(out T) method
            {
                stateHandler.OnStateChange?.Invoke(State.Airborne);
            }
        }
    }
}