Giter VIP home page Giter VIP logo

morpeh.startup's Introduction

Morpeh Startup

Simple startup with DI integration for Morpeh ECS

Installation

Install via git URL

https://github.com/heymeepo/morpeh.startup.git

Usage

Attention: All your update systems should be inherited from the IUpdateSystem interface instead of ISystem.

public class Game : MonoBehaviour
{
    private EcsStartup startup;

    private void Awake()
    {
        startup = new EcsStartup();

        startup
            .AddSystemsGroup()
            .AddInitializer(new GameInitializer())
            .AddUpdateSystem(new InputSystem())
            .AddLateSystem(new GameOverSystem());

        startup
            .AddSystemsGroup()
            .AddCleanupSystem(new DestroyEntitySystem());

        startup.Initialize(updateByUnity: true);
    }

    private void OnDestroy()
    {
        startup?.Dispose();
    }
}

All added systems after AddSystemsGroup() are placed in one systems group. If you need to add systems to different systems groups, you should call startup.AddSystemsGroup() again, as in the example above.

You can manually update the startup by passing 'updateByUnity: false' and calling the methods startup.Update(), startup.FixedUpdate(), and startup.LateUpdate() as needed.

You can also pass an instance of the World into the constructor, otherwise, World.Default will be used.

Features

A feature is a wrapper around a set of systems responsible for some specific functionality. To create a feature, declare a new class and inherit it from the IEcsFeature interface. Inside the feature, all functionality for adding systems is available, except for AddSystemsGroup and AddFeature

public class Game : MonoBehaviour
{
    private EcsStartup startup;

    private void Awake()
    {
        startup = new EcsStartup();

        startup
            .AddSystemsGroup()
            .AddInitializer(new GameInitializer())
            .AddFeature(new AnimationFeature());

        startup.Initialize(updateByUnity: true);
    }
}

public sealed class AnimationFeature : IEcsFeature
{
    public void Configure(EcsStartup.FeatureBuilder builder)
    {
        builder
            .AddUpdateSystem(new AnimatorInitializeSystem())
            .AddUpdateSystem(new IdleAnimationSystem())
            .AddUpdateSystem(new MovementAnimationSystem())
            .AddUpdateSystem(new DieAnimationSystem())
            .AddUpdateSystem(new AnimatorSystem());
    }
}

VContainer

Ensure that you have imported the VContainer package and define VCONTAINER in Project Settings -> Player -> Scripting Define Symbols

Now, to create an EcsStartup, you need to pass VContainerResolver with the current LifetimeScope to its constructor. Specify all the necessary dependencies in the constructors of your systems and features.

You can use the methods with the 'Injected' postfix to add your systems using the container. However, you still have the option to add systems manually.

public class EcsModule : IStartable, IDisposable
{
    private readonly LifetimeScope scope;
    private EcsStartup startup;

    [Inject]
    public EcsModule(LifetimeScope scope)
    {
        this.scope = scope;
    }

    public void Start()
    {
        startup = new EcsStartup(new VContainerResolver(scope));

        startup
            .AddSystemsGroup()
            .AddInitializerInjected<GameInitializer>()
            .AddUpdateSystemInjected<InputSystem>();

        startup
            .AddSystemsGroup()
            .AddFeatureInjected<AnimationFeature>()
            .AddFeatureInjected<RenderFeature>();

        startup
            .AddSystemsGroup()
            .AddCleanupSystem(new DestroyEntitySystem());

        startup.Initialize(updateByUnity: true);
    }

    public void Dispose()
    {
        startup?.Dispose();
    }
}

public sealed class AnimationFeature : IEcsFeature
{
    private readonly IGameSettingsService gameSettings;

    [Inject]
    public AnimationFeature(IGameSettingsService gameSettings)
    {
        this.gameSettings = gameSettings;
    }

    public void Configure(EcsStartup.FeatureBuilder builder)
    {
        builder
            .AddUpdateSystemInjected<AnimatorInitializeSystem>()
            .AddUpdateSystemInjected<IdleAnimationSystem>()
            .AddUpdateSystemInjected<MovementAnimationSystem>()
            .AddUpdateSystemInjected<DieAnimationSystem>();

        if (gameSettings.Graphics.EnableExperimentalAnimations)
        {
            builder.AddUpdateSystem(new ExperimentalAnimatorSystem(...));
        }
        else
        { 
            builder.AddUpdateSystemInjected<AnimatorSystem>();
        }
    }
}

Clarification: You don't need to register your systems or features in the LifetimeScope, the startup does it automatically.

Custom DI container (Advanced)

To add support for another DI solution:

  • Define the STARTUP_DI directive.
  • Create a class that implements IStartupContainer.
  • Implement all necessary methods similar to how it's done in the VContainerResolver class.
  • Pass an instance of this class to the constructor of EcsStartup.

Here's a brief explanation:

Since we support injection both into features and systems, we need to use two different containers.

Why is that?

The issue arises because, besides directly added systems and features, we also have a Configure method inside features. These methods additionally want to register their systems in the container. Hence, we cannot build the systems' container until all systems are registered. However, to invoke the Configure method of features, we need to resolve them. Therefore, features cannot reside in the same container as systems.

Due to this, we first build the container with features. Afterward, we call the Configure methods. Only then can we build the container with systems and create systems groups.

License

MIT

morpeh.startup's People

Contributors

heymeepo avatar sttrox avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.