jeffreylanters/unity-entity-component-system

Repository files navigation

readme splash

licenseopenupmbuilddeploymentstarsdownloadssizesponsorsdonateawesome

A better approach to game design that allows you to concentrate on the actual problems you are solving: the data and behavior that make up your game. By moving from object-oriented to data-oriented design it will be easier for you to reuse the code and easier for others to understand and work on it.

Installation · Documentation · License

Made with ♥ by Jeffrey Lanters

Install the latest stable release using the Unity Package Manager by adding the following line to your manifest.json file located within your project's Packages directory, or by adding the Git URL to the Package Manager Window inside of Unity.

"nl.elraccoone.entity-component-system": "git+https://.com/jeffreylanters/unity-entity-component-system"

The module is availble on the OpenUPM package registry, you can install the latest stable release using the OpenUPM Package manager's Command Line Tool using the following command.

openupm add nl.elraccoone.entity-component-system

It's recommended to get started by using the built-in File Generator. When it's your first time using the ECS, you might want to enable the Overwrite All Virtuals option to see all the available methods for each type of class.


It's recommended to build your entire project around these life cycle methods.


The Controller is the heart of your Application, each Application should consist of just one, commonly named the MainController. The Controller is the first entry point of the Entity Component System and is the place where all of your System and Services are registered. Your Controller should be attached to a GameObject in your scene and will automatically be marked to not be destroyed when switching scenes.

public class MainController: Controller { }

The Controller consists of a virtual OnInitialize method. This lifecycle method can be overwritten and will be invoked at the very start of your Application. During this cycle, properties with the Injected and Asset attributes are being assigned, and the OnInitialize method of each registered System and Service will be invoked as well.

public class MainController: Controller {
  public override void OnInitialize() { }
}

The Controller consists of a virtual OnInitialized method. This lifecycle method can be overwritten and will be invoked after the OnInitialize method has been invoked. During this cycle, the OnInitialized method of each registered System and Service will be invoked as well.

public class MainController: Controller {
  public override void OnInitialized() { }
}

The Controller consists of a virtual OnUpdate method. This lifecycle method can be overwritten and will be invoked every frame. During this cycle, the OnUpdate method of each registered System will be invoked as well.

public class MainController: Controller {
  public override void OnUpdate() { }
}

The Controller consists of a virtual OnWillDestroy method. This lifecycle method can be overwritten and will be invoked when the Application is about to quit. During this cycle, the OnWillDestroy method of each registered System and Service will be invoked as well.

public class MainController: Controller {
  public override void OnWillDestroy() { }
}

Use this method to Register the Systems and Services that are required for your Application to function. The Register method accepts a list of Type arguments, each of these types should be a System or Service type.

Registering a System or Service can only be done once during the Controller's OnInitialize life cycle method.

public class MainController: Controller {
  public override void OnInitialize() {
    Register(
      typeof(ExampleSystem),
      typeof(ExampleService)
    );
  }
}

To enable or disable the life cycle of a System or Service, use the SetSystemEnabled methods. This method accepts a Type generic, and a bool value to enable or disable the life cycle of the System or Service.

public class MainController: Controller {
  void SomeMethod() {
    SetSystemEnabled<ExampleSystem>(false);
  }
}

To check whether the life cycle of a System or Service is enabled, use the IsSystemEnabled methods. This method accepts a Type generic, and returns a bool value indicating whether the life cycle of the System or Service is enabled.

public class MainController: Controller {
  void SomeMethod() {
    if (IsSystemEnabled<ExampleSystem>()) { }
  }
}

Something you might want to get a reference to a System or Service from within something outside of the Entity Component System. To do this, use the GetSystem, GetService, HasSystem and HasService methods respectively. These methods accept a Type generic, or a Type parameter and return the System or Service instance.

public class MainController: Controller {
  void SomeMethod() {
    if (HasSystem<ExampleSystem>()) {
      var exampleSystem = GetSystem<ExampleSystem>();
      var exampleSystem = GetSystem(typeof(ExampleSystem));
    }
    if (HasService<ExampleService>()) {
      var exampleService = GetService<ExampleService>();
      var exampleService = GetService(typeof(ExampleService));
    }
  }
}

Something you might want to get a reference to an Asset from within something outside of the Entity Component System. To do this, use the GetAsset and HasAsset methods respectively. These methods accepts an optional Type generic and a name parameter and returns the Type or Object

public class MainController: Controller {
  void SomeMethod() {
    if (HasAsset<ExampleAsset>()) {
      var exampleAsset = GetAsset<ExampleAsset>("MyAssetName");
      var exampleAssetObject = GetAsset("MyAssetName");
    }
  }
}

The Controller allows the use of the Asset attribute on properties to automatically assign the values of referenced Assets. Assets can be assigned on the Controller instance in your Scene. When assigning using the empty contructor, the property's name will be used for searching the Asset, to find an Asset by its name, use the string overload. All types of UnityEngine's Object can be used in these fields. These properties are assigned during the OnInitialize cycle and are available for use at the OnInitialized cycle. When an asset is not found, an error is thrown.

public class MainController: Controller {
  [Asset] public ExampleAsset exampleAsset;
  [Asset("MyAssetName")] public ExampleAsset exampleAsset;
}

The Controller allows the use of the Injected attribute on properties to automatically assign the values of referenced Systems and Services, making all public methods and properties accessible. These properties are assigned during the OnInitialize cycle and are available for use at the OnInitialized cycle.

public class MainController: Controller {
  [Injected] public ExampleSystem exampleSystem;
  [Injected] public ExampleService exampleService;
}

Components are responsible for storing the data of your entities while Systems are responsible for manipulating that data. Components are added to your entities (GameObjects) in the Scene, an Entity is not limited to one Component and can hold as many as needed.

public class MovementComponent : EntityComponent<MovementComponent, MovementSystem> { }

To provide Systems entity data, we'll use properties to store this. All properties should be public and will be accessible to all Systems and Controllers since there is no need for privates.

public class MovementComponent : EntityComponent<MovementComponent, MovementSystem> {
  public float speed;
  public Vector3 targetPosition;
  public int[] ids;
  public NpcDialog dialog;
  [HideInInspector] public bool isMoving;
}

About

A better approach to game design that allows you to concentrate on the actual problems you are solving: the data and behavior that make up your game. By moving from object-oriented to data-oriented design it will be easier for you to reuse the code and easier for others to understand and work on it.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Sponsor this project

 

Contributors 2

  •  
  •  

Languages