Code Monkey home page Code Monkey logo

ecsrx.unity's Introduction

EcsRx

EcsRx is a reactive take on the common ECS pattern with a well separated design using rx and adhering to IoC and other sensible design patterns.

Build Status Code Quality Status License Nuget Version Join Discord Chat Documentation

Features

  • Simple ECS interfaces to follow
  • Fully reactive architecture
  • Favours composition over inheritance
  • Adheres to inversion of control
  • Lightweight codebase
  • Built in support for events (raise your own and react to them)
  • Built in support for pooling (easy to add your own implementation or wrap 3rd party pooling tools)
  • Built in support for plugins (wrap up your own components/systems/events and share them with others)

The core framework is meant to be used primarily by .net applications/games, there is a unity specific version here which builds on top of this core version, as well as a monogame game version here.

It is also worth mentioning that this framework builds on top of SystemsRx, which can be used without EcsRx for when you want Systems and Events but dont need the Entity Component aspects.

Installation

The library was built to support .net standard 2.0, so you can just reference the assembly, and include a compatible rx implementation.

Quick Start

It is advised to look at the setup docs, this covers the 2 avenues to setup the application using it without the helper libraries, or with the helper libraries which offer you dependency injection and other benefits.

If you are using unity it is recommended you just ignore everything here and use the instructions on the ecsrx.unity repository as that has not been fully mapped over to use this core version yet so is its own eco system until that jump is made.

Simple components

public class HealthComponent : IComponent
{
    public int CurrentHealth { get; set; }
    public int MaxHealth { get; set; }
}

You implement the IComponent interface which marks the class as a component, and you can optionally implement IDisposable if you want to dispose stuff like so:

public class HealthComponent : IComponent, IDisposable
{
    public ReactiveProperty<int> CurrentHealth { get; set; }
    public int MaxHealth { get; set; }
    
    public HealthComponent() 
    { CurrentHealth = new ReactiveProperty<int>(); }
    
    public void Dispose() 
    { CurrentHealth.Dispose; }
}

Any component which is marked with IDisposable will be auto disposed of by entities.

Simple systems

public class CheckForDeathSystem : IReactToEntitySystem
{
    public IGroup TargetGroup => new Group(typeof(HealthComponent)); // Get any entities with health component

    public IObservable<IEntity> ReactToEntity(IEntity entity) // Explain when you want to execute
    {
        var healthComponent = entity.GetComponent<HealthComponent>();
        return healthComponent.CurrentHealth.Where(x => x <= 0).Select(x => entity);
    }
    
    public void Process(IEntity entity) // Logic run whenever the above reaction occurs
    {
        entity.RemoveComponent<HealthComponent>();
        entity.AddComponent<IsDeadComponent>();
    }
}

Systems are conventional, so there are many built in types like IReactToEntitySystem, IReactToGroupSystem, IManualSystem and many others, but you can read about them in the docs/systems, you can add your own conventional systems by extending ISystem and systems are handled for you by the ISystemExecutor.

Check the examples for more use cases, and the unity flavour of ecsrx which has more examples and demo projects, and drop into the discord channel to ask any questions.

Running Examples

If you want to run the examples then just clone it and open examples project in the src folder, then run the examples, I will try to add to as the library matures.

There are also a suite of tests which are being expanded as the project grows, it was written with testability in mind.

Architecture / Infrastructure

EcsRx

This is layered on top of SystemsRx and adds the ECS paradigm to the framework as well as adding a couple of systems specifically for entity handling. This also contains an EcsRx.Infrastructure layer which builds off the SystemsRx.Infrastructure layer to provide additional ECS related infrastructure.

EcsRx.Infrastructure

This builds on top of the SystemsRx.Infrastructure library to provide all the cool DI abstraction and plugin stuffs.

EcsRx.Plugins.*

These are plugins that can be used with EcsRx to add new functionality to the library, from entity persistance/rehydration to schedulable systems, these can optionally be added to your projects.

History

The library was originally developed for unity (way before they had their own ECS framework) and since then has moved to be a regular .net library that can run anywhere (Even in Blazor WASM).

Off the back of this there have been a few other libraries that were created for EcsRx but now live as their own standalone libraries:

  • LazyData - Was created as a serialization layer for EcsRx
  • Persistity - Was created as an ETL style pipeline for EcsRx
  • SystemsRx - Was the supporting system/data layer for EcsRx

Docs

There is a book available which covers the main parts which can be found here:

Documentation

This is basically just the docs folder in a fancy viewer

Community Plugins/Extensions

This can all be found within the docs here

Thanks

Thanks to Jetbrains for providing free liceneses via their Open Source Support program

Jetbrains

ecsrx.unity's People

Contributors

bezarius avatar corvoorc avatar gitter-badger avatar grofit avatar jaypavlina avatar lailore avatar phoenleo avatar timmeh4242 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ecsrx.unity's Issues

Move IBlueprint from Assets.EcsRx.Framework.Blueprints

Move IBlueprint from Assets.EcsRx.Framework.Blueprints to EcsRx.Blueprints namespace.

It stands out like a sore thumb.

Even better get rid of the namespaces leaving only EcsRx as there seems to be way to many compared to Zenject and UniRx.

Nits for GroupBuilder

Howdy there,

I had a couple nit picking comments for GroupBuilder()

  1. Add additional constructor that accepts a built IGroup. This would offer a straight forward method to modify an existing Group.
  2. GroupBuilder.Create() seems it should be a static factory.
  3. Renaming WithComponent() to AddComponent() helps self document its behavior.
  4. Renaming WithPredicate() to SetPredicate() helps self document it's behavior.

I didn't notice anything in the readme covering the contribution process (or how you feel about breaking changes :p ), but I would be happy to make a PR.

Cheers,
Dxslly

Example with Animator

Hi!

Could you add an example of using a simple animator(walk\attack\death)?

I would like to see an example of the correct use of ecsrx for such tasks.

IReactToGroupSystem much slower then IReactToEntitySystem and causing GC spikes

Contrary to what the docs state IReactToGroupSystem is a lot slower than IReactToEntitySystem and also allocates GC memory which is causing spikes easily noticeable in the profiler and practically stopping the game on a moderately fast tablet (galaxy note 2014).

Main culprit is Enumerable.ToArray() which I think is: var entities = accessor.Entities.ToArray(); called during system setup, but could be wrong. Leaking almost 1.0kb per frame is absolutely unacceptable.

Another problem is: IEnumerableExtensions.RunForEach() - it 'only' allocates 32B but obviously it'll quickly accumulate.

So there are a few separate things here.

Enumerable.ToArray() should be used sparingly and certainly not every frame which is what ReactToGroup is meant for.

Perhaps RunForEach() could be called on accessor.Entities directly?? Since it's effectively just an array converted to another array.

In any case it'll still cause some GC allocation as with the way entities are kept in the groupAccessor it's impossible to convert that foreach loop into a normal for loop. So maybe entities should be kept in a plain array[].

callstack1

I also came across Entity.HasComponents(params Type[] componentTypes) wasting lots of CPU time but I did't drill down into it as I had to find a work-around to get my project working. It is certainly worth looking into.

Vector3 in component editor doesn't work

For reproduction:

public class SomeComponent : IComponent
{
    public Vector3 SomeVec{ get; set; }
}

On go add RegisterAsEntity and add SomeComponent.

Now in editor we can see error:

NullReferenceException: Object reference not set to an instance of an object
EcsRx.Json.JSONNode.set_AsVector3 (Vector3 value) (at Assets/EcsRx/Unity/JSON.cs:949)
EcsRx.Json.JSONData..ctor (Vector3 value) (at Assets/EcsRx/Unity/JSON.cs:428)
Assets.EcsRx.Unity.Extensions.ComponentExtensions.SerializeComponent (System.Object component) (at Assets/EcsRx/Unity/Extensions/ComponentExtensions.cs:84)
EcsRx.Unity.Helpers.RegisterAsEntityInspector+c__AnonStorey0.<>m__0 () (at Assets/EcsRx/Unity/MonoBehaviours/Editor/RegisterAsEntityInspector.cs:86)
EcsRx.Unity.Helpers.Extensions.EditorExtensions.UseVerticalBoxLayout (UnityEditor.Editor editor, System.Action action) (at Assets/EcsRx/Unity/MonoBehaviours/Editor/Extensions/EditorExtensions.cs:17)
EcsRx.Unity.Helpers.RegisterAsEntityInspector.ComponentListings () (at Assets/EcsRx/Unity/MonoBehaviours/Editor/RegisterAsEntityInspector.cs:54)
EcsRx.Unity.Helpers.RegisterAsEntityInspector.OnInspectorGUI () (at Assets/EcsRx/Unity/MonoBehaviours/Editor/RegisterAsEntityInspector.cs:137)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor editor, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1236)
UnityEditor.DockArea:OnGUI()

As i understand it's incorrect implementation method for vec serialization.

View Resoler << yes Resoler

you have that typo in a few related files.

Side note: you react to the whole entity being removed, perhaps you should react similarly to the ViewComponent being removed from the entity.

Add basic view pooling support

Summary

One key benefit of having entities decoupled from views is that you can easily have entities in memory which is fairly cheap, but you can turn your views on and off. For certain scenarios you may want to have a pool of GameObjects which you can just re-use as entities require a view.

Add support for ITeardownSystem

This would be the opposite of ISetupSystem so this can be used to indicate when an entity no longer applies to a group and can do custom logic on the entity in question.

Scene-first setting up entities based on GOs present in the scene.

It's kind of related to Issue #8.

It would be nice to see some helper classes or extension methods allowing to attach existing GOs in the scene to entity's ViewComponent.View and subsequently running them through a SetupSystem.

All the above completely programmatically without having to add any Components to the GO manually in Unity Editor.

Also discussed on gitter on 01-Nov-2016.

Entity Ids have finite limit

As I am sure someone else will come out with this at some point, currently the Ids of entities were VERY basic in implementation and will not really track unused ids etc so if you were to instantiate over the period of a game int.MaxValue I believe currently it will blow up.

Ids were implemented but the use cases for them seem minimal, so it may be simpler to just remove the notion of Ids, but if there are some good use cases we can do some work around this area to make Ids more intelligent.

System question - access to entities in group

How i can get access to entity group in system like this:

    public class SenseSystem :  IReactToGroupSystem
    {

        public IGroup TargetGroup
        {
            get
            {
                return new GroupBuilder()
                    .WithComponent<SomeComponent>()
                    .Build();
            }
        }

        public IObservable<IGroupAccessor> ReactToGroup(IGroupAccessor @group)
        {
            return Observable.Interval(TimeSpan.FromSeconds(1)).Select(x => @group);
        }

        public void Execute(IEntity entity)
        {
            // now i want to get acccess to another  entities from targetGroup(find nearest enemy)
        }
    }

Or may be i have to use a IManualSystem?

NullReferenceException when trying to use Reactive Properties with generic types

NullReferenceException: Object reference not set to an instance of an object
EcsRx.Unity.JSONNode.set_AsVector3 (UnityEngine.Vector3 value) (at Assets/EcsRx/Unity/JSON.cs:949)
EcsRx.Unity.JSONData..ctor (UnityEngine.Vector3 value) (at Assets/EcsRx/Unity/JSON.cs:428)
EcsRx.Unity.Extensions.ComponentExtensions.SerializeComponent (System.Object component) (at Assets/EcsRx/Unity/Extensions/ComponentExtensions.cs:91)
EcsRx.Unity.RegisterAsEntityInspector+c__AnonStorey0.<>m__0 () (at Assets/EcsRx/Unity/Editor/RegisterAsEntityInspector.cs:83)
EcsRx.Unity.Extensions.EditorExtensions.UseVerticalBoxLayout (UnityEditor.Editor editor, System.Action action) (at Assets/EcsRx/Unity/Editor/Extensions/EditorExtensions.cs:17)
EcsRx.Unity.RegisterAsEntityInspector.ComponentListings () (at Assets/EcsRx/Unity/Editor/RegisterAsEntityInspector.cs:51)
EcsRx.Unity.RegisterAsEntityInspector.OnInspectorGUI () (at Assets/EcsRx/Unity/Editor/RegisterAsEntityInspector.cs:134)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor[] editors, System.Int32 editorIndex, System.Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1367)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

I added RegisterAsEntity script to a MonoBehavior, via the editor, and on this, I added a component with a Vector3ReactiveProperty in it. But I remark your rogue example have the same problem if you open the components with Vector3 as RamdomlyPlacedComponent.

Add support for blueprints when Setting Up View Entity

Summary

Currently when you are using a scene first setup mb on a game object (SetupView MonoBehaviour), it only lets you setup the components that the view should be using, which is great but it would be good to also allow you to choose a blueprint to use and configure that, allowing you to have an easier more standard way of setting up scene first entities.

Zenject Warning: It is bad practice to call Inject/Resolve/Instantiate before all the Installers have completed!

This happens to be from view-binding-scene example.

Yes, code still works but wouldn't it be nice to not have this warning?

Seems like AutoRegisterSystemsInstaller.RegisterSystems() shouldn't be called from within InstallBindings(). It seems like a cheeky hack to register systems while bindings are installed. Certainly requires for the AutoRegisterSystemsInstaller to be dropped onto SceneContext -> Installers in the last position. Perhaps it's better to just use AutoBindSystemsInstaller and use a separate MonoBehaviour based class to run RegisterSystems() if it's possible to assure it'd be run after all bindings have been installed?

Zenject Warning: It is bad practice to call Inject/Resolve/Instantiate before all the Installers have completed! This is important to ensure that all bindings have properly been installed in case they are needed when injecting/instantiating/resolving. Detected when operating on type 'ISystem'
UnityEngine.Debug:LogWarning(Object)
ModestTree.Log:Warn(String, Object[]) (at Assets/Zenject/Source/Internal/Log.cs:47)
Zenject.DiContainer:CheckForInstallWarning(InjectContext) (at Assets/Zenject/Source/Main/DiContainer.cs:466)
Zenject.DiContainer:ResolveAll(InjectContext) (at Assets/Zenject/Source/Main/DiContainer.cs:407)
Zenject.DiContainer:ResolveAll(InjectContext) (at Assets/Zenject/Source/Main/DiContainer.cs:1803)
Zenject.DiContainer:ResolveAll(Object, Boolean) (at Assets/Zenject/Source/Main/DiContainer.cs:1795)
Zenject.DiContainer:ResolveAll(Object) (at Assets/Zenject/Source/Main/DiContainer.cs:1788)
Zenject.DiContainer:ResolveAll() (at Assets/Zenject/Source/Main/DiContainer.cs:1776)
EcsRx.Unity.Installers.AutoRegisterSystemsInstaller:RegisterSystems() (at Assets/EcsRx/Unity/Installers/AutoRegisterSystemsInstaller.cs:28)
EcsRx.Unity.Installers.AutoRegisterSystemsInstaller:InstallBindings() (at Assets/EcsRx/Unity/Installers/AutoRegisterSystemsInstaller.cs:23)
Zenject.DiContainer:InstallInstallerInternal(IInstaller) (at Assets/Zenject/Source/Main/DiContainer.cs:680)
Zenject.DiContainer:Install(IInstaller, IEnumerable1) (at Assets/Zenject/Source/Main/DiContainer.cs:535) Zenject.DiContainer:Install(IInstaller) (at Assets/Zenject/Source/Main/DiContainer.cs:516) Zenject.Context:InstallInstallers(Dictionary2) (at Assets/Zenject/Source/Install/Contexts/Context.cs:158)
Zenject.Context:InstallInstallers() (at Assets/Zenject/Source/Install/Contexts/Context.cs:117)
Zenject.SceneContext:InstallBindings(InitialComponentsInjecter) (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:232)
Zenject.SceneContext:RunInternal() (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:183)
Zenject.SceneContext:Run() (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:134)
Zenject.SceneContext:Awake() (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:103)

GetComponent throwing random KeyNotFoundException

  • Unity: 2017.3.1f1
  • EcsRx: 0.11.0 (release)
  • Zenject: 5.5.1
  • UniRx: 5.5.0

I am facing a weird issue where the name of a class seems to makes EcsRx throw KeyNotFoundExceptions whenever I use entity.GetComponent. I was not able to isolate a clear pattern, so I will try to be as precise as possible.

So, I have a really simple ISetupSystem...

public class RotationSetupSystem : ISetupSystem
{
    public RotationSetupSystem () {
        TargetGroup = new Group(typeof(RotationComponent), typeof(ViewComponent));
    }

    public IGroup TargetGroup { get; private set; }

    public void Setup (IEntity entity) {
        Quaternion value = entity.GetComponent<ViewComponent>().View.transform.localRotation;
        entity.GetComponent<RotationComponent>().Value = value.eulerAngles;
    }
}

... which throws this error whenever I hit Play in Unity:

KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[System.Type,EcsRx.Components.IComponent].get_Item (System.Type key) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:150)
EcsRx.Entities.Entity.GetComponent[ViewComponent] () (at Assets/Libraries/EcsRx/Framework/Entities/Entity.cs:75)
Sources.Systems.Core.RotationSetupSystem.Setup (IEntity entity) (at Assets/Sources/Systems/Core/RotationSetupSystem.cs:26)
...

I double checked that all target entities had a View, and a RotationComponent, and everything looked fine. So I started messing around, and renaming the system's class to FooRotationSetupSystem makes it work as expected.

I first thought that RotationSetupSystem might have been a reserved name by EcsRx but found no trace of it. I renamed the class again to ViewRotationSetupSystem and, bad luck, the exception was back!

I tried a bunch of names for that system, and some are working, some are throwing a KeyNotFoundException. And as I said, I was not able to isolate some kind of pattern, or rule, it seems completely random but specific to that system (I never had this issue before, with any other system I wrote).

Magic extension method BindAllSystemsWithinApplicationScope

The extension method BindAllSystemsWithinApplicationScope do some undocumented magic. But, one major issue, it forces you to put Application classes at the parent root of the Systems and ViewResolvers folders and thus, you can't put your Application classes in their own folder.

How about refactoring out all the 'new' statements which make it hard to replace functionalities through plugins?

Pool has a hardcoded 'new Entity()', PoolManager has a hardcoded 'new Pool()'.
If instead those classes used the simplest injectable zenject factories it would be easier to provide different implementations of IEntity, IPool without having to replace the whole chain PoolManager->Pool->Entity.

Heck, maybe CashableGroupAccessor or even GroupAccessors implementations in general should be easliy pluggable?

Zenject factories are practically one line classes (really more like typedefs in c++ speak) so should be easy enough.

Pool.RemoveEntity should call Entity.RemoveAllComponents().

Pool.RemoveEntity should call Entity.RemoveAllComponents().

Not only it's a little code cleanup but the real reason is it would fire component removed event. That way I can still find out if a given instance of a component was removed even if it's because of removing the whole entity. Would simplify disposing of some subscriptions to component property changes.

Also, this would add functionality through removing code.

Errors on build of example scene

I am trying to run view-binding-scene. I have done the following:

  1. cloned repo
  2. tried running
  3. imported zenject and unirx
  4. tried running

I get this error:

UNetWeaver error: Exception :System.MissingMethodException: Method not found: 'Mono.Cecil.ModuleDefinition.ImportReference'.
  at Unity.UNetWeaver.Weaver.Weave (System.String assName, IEnumerable`1 dependencies, IAssemblyResolver assemblyResolver, System.String unityEngineDLLPath, System.String unityUNetDLLPath, System.String outputDir) [0x0004b] in C:\buildslave\unity\build\Extensions\Networking\Weaver\UNetWeaver.cs:1713 
  at Unity.UNetWeaver.Weaver.WeaveAssemblies (IEnumerable`1 assemblies, IEnumerable`1 dependencies, IAssemblyResolver assemblyResolver, System.String outputDir, System.String unityEngineDLLPath, System.String unityUNetDLLPath) [0x0006e] in C:\buildslave\unity\build\Extensions\Networking\Weaver\UNetWeaver.cs:1837 
UnityEngine.Debug:LogError(Object)
Unity.UNetWeaver.Log:Error(String) (at C:/buildslave/unity/build/Extensions/Networking/Weaver/Program.cs:20)
Unity.UNetWeaver.Weaver:WeaveAssemblies(IEnumerable`1, IEnumerable`1, IAssemblyResolver, String, String, String) (at C:/buildslave/unity/build/Extensions/Networking/Weaver/UNetWeaver.cs:1844)
Unity.UNetWeaver.Program:Process(String, String, String, String[], String[], IAssemblyResolver, Action`1, Action`1) (at C:/buildslave/unity/build/Extensions/Networking/Weaver/Program.cs:34)
UnityEditor.Scripting.Serialization.Weaver:WeaveUnetFromEditor(String, String, String, String, Boolean)

and

Failure generating network code.
UnityEditor.Scripting.Serialization.Weaver:WeaveUnetFromEditor(String, String, String, String, Boolean)

and


Unhandled Exception:
System.IO.IOException: Sharing violation on path C:\Users\austi\Apps\ecsrx\ecsrx\src\Temp\Assembly-CSharp-firstpass.dll.mdb

  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) <0x2c774c0 + 0x006af> in <filename unknown>:0 

  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean isAsync, Boolean anonymous) <0x5982da8 + 0x0004f> in <filename unknown>:0 

  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access) <0x5982d48 + 0x0004f> in <filename unknown>:0 

  at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess)

  at Mono.CSharp.AssemblyDefinition.Save () <0x5967140 + 0x0036f> in <filename unknown>:0 

  at Mono.CSharp.Driver.Compile () <0x2c86620 + 0x00707> in <filename unknown>:0 

  at Mono.CSharp.Driver.Main (System.String[] args) <0x2c40f30 + 0x00147> in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.IO.IOException: Sharing violation on path C:\Users\austi\Apps\ecsrx\ecsrx\src\Temp\Assembly-CSharp-firstpass.dll.mdb

  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) <0x2c774c0 + 0x006af> in <filename unknown>:0 

  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean isAsync, Boolean anonymous) <0x5982da8 + 0x0004f> in <filename unknown>:0 

  at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access) <0x5982d48 + 0x0004f> in <filename unknown>:0 

  at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess)

  at Mono.CSharp.AssemblyDefinition.Save () <0x5967140 + 0x0036f> in <filename unknown>:0 

  at Mono.CSharp.Driver.Compile () <0x2c86620 + 0x00707> in <filename unknown>:0 

  at Mono.CSharp.Driver.Main (System.String[] args) <0x2c40f30 + 0x00147> in <filename unknown>:0 

Running 5.5.0f3

System priority documentation

Please provide some documentation for System priority and how the order of system execution can be determined.

Also please document how to correctly setup system auto binding and registration mentioning if order of namespaces in the list matters

GetUnityComponent does not work with Rigidbody

The extension method GetUnityComponent does not work with the Rigidbody component because it does not inherit of Behavior. The where T of the GetUnityComponent and AddUnityComponent should be changed or removed.

Create filterable groups

Based off another conversation it seems like it could be useful to have a way which automatically filter entities so you always have a way to get entities you care about rather than having to scan the list every cycle.

An example of this would be if you wanted a group which represented the entities with the top 5 score, you could then have some filter applied to the group to make sure it orders by the score and only takes the top 5, this way you can make re-useable groups which can do some level of filtering for you, or take in arguments which allow you to customize the filtration.

I am unsure currently as to where the logic for this should sit as ideally you want to be isolated somewhere but also you want it to be useable within systems, so it needs some thought.

String tags instead of empty "tag" components?

Would you consider adding a possibility to add tags to entities ?

Sometimes you just want to mark an entity as having a certain feature and then target those entities in systems. As it stands currently you have to create an empty pseudo-component just to slap it on an entity as a form of marker or a tag. If such tags could be implemented as a list of strings (or even constant integers) it could possibly save some compile time, some unnecessary files, and would be a wee bit more data-driven friendly. Targeting would possibly resolve quicker as well.

Subscribint to EntityAdded event from SystemExecutor will never serve any purpose.

Subscribint to EntityAdded event from SystemExecutor will never serve any purpose as those entities are always empty at the time this event is received.

If they weren't empty ( for example if Pool.CreateEntiity() published this event AFTER applying the blueprint) it would be even worse as systems would be applied to entities twice. Once after all required components are added and the second time in response to entity added event.

License?

This project is missing a license statement. People may be reluctant to use it without it.

Add collision detection for every entity created by pool

I have one scenario, and don't know what is the better form on acomplish the task.
Tha case is , I have a bullet view resolver, that inherit from the DefaultPooledViewResolverSystem, I need to add an collision observer to every bullet, to detect collision with enemy (and have the access to the collided object in the executor). Basicaly I made this system. But I don't know if there are better ways, if someone have made it differently, I will be very thankful

	public class BulletInteractionSystem : IReactToEntitySystem
	{
		private GameObject colliderGO; 

		public BulletInteractionSystem ()
		{
		}

		public IGroup TargetGroup { get { return new Group (typeof(BulletComponent), typeof(ViewComponent)); } }

		public IObservable<IEntity> ReactToEntity(IEntity entity)
		{
			var viewComponent = entity.GetComponent<ViewComponent>();
			return viewComponent.View.OnTriggerEnterAsObservable ()
				.Where(collider => collider.gameObject.tag == "Enemy")
				.Select(collider => {
					colliderGO = collider.gameObject;
					return entity;
				});
		}

		public void Execute(IEntity entity)
		{
			Debug.Log (colliderGO);
			Debug.Log ("trigged");
		}
	}

Request for a new example project

The current rogue example project has particular things making hard to grasp some concepts of the EcsRx library.

One of the things is the nature of the one-infinite-autogenerated-level scene. Almost all are set up and generated by code, but I want to see a menu scene loading a game scene. The game scene can use pool to spawn enemy, but other objects are already in the scene and probably come from prefab drag & dropped on the scene. Would be nice to see additive/multiple scenes to see how the objects talk to each other.

One of the other things, the WASD inputs do not control directly the player but some kind of turn-based/differed. I would like to see more standard movement, jump and fire bullets inputs to see how to implement them.

I'm a beginner at Unity, ECS, Rx and for me, the rogue example does not show off the essentials from the point of view of a more traditional game and workflow with the editor, composed of many scenes and in-place objects.

Is it possible for you to create another example more toward static scenes with RegisterAsEntity?

SystemExecutor doesn't pass Zenject Scene Validation

SystemExecutor doesn't pass Zenject Scene Validation.

Yes, I know it doesn't prevent EcsRx from running but why not have a Zenject compliant code.

InvalidCastException: Cannot cast from source type to destination type.
Zenject.DiContainer.Resolve[ISystemExecutor] (Zenject.InjectContext context) (at Assets/Zenject/Source/Main/DiContainer.cs:1770)
Zenject.DiContainer.Resolve[ISystemExecutor] (System.Object identifier) (at Assets/Zenject/Source/Main/DiContainer.cs:1723)
Zenject.DiContainer.Resolve[ISystemExecutor] () (at Assets/Zenject/Source/Main/DiContainer.cs:1717)
EcsRx.Unity.Installers.AutoRegisterSystemsInstaller.RegisterSystems () (at Assets/EcsRx/Unity/Installers/AutoRegisterSystemsInstaller.cs:29)
EcsRx.Unity.Installers.AutoRegisterSystemsInstaller.InstallBindings () (at Assets/EcsRx/Unity/Installers/AutoRegisterSystemsInstaller.cs:23)
Zenject.DiContainer.InstallInstallerInternal (IInstaller installer) (at Assets/Zenject/Source/Main/DiContainer.cs:680)
Rethrow as Exception: Error occurred while running installer 'AutoRegisterSystemsInstaller'
Zenject.DiContainer.InstallInstallerInternal (IInstaller installer) (at Assets/Zenject/Source/Main/DiContainer.cs:686)
Zenject.DiContainer.Install (IInstaller installer, IEnumerable1 extraArgs) (at Assets/Zenject/Source/Main/DiContainer.cs:535) Zenject.DiContainer.Install (IInstaller installer) (at Assets/Zenject/Source/Main/DiContainer.cs:516) Zenject.Context.InstallInstallers (System.Collections.Generic.Dictionary2 extraArgsMap) (at Assets/Zenject/Source/Install/Contexts/Context.cs:158)
Zenject.Context.InstallInstallers () (at Assets/Zenject/Source/Install/Contexts/Context.cs:117)
Zenject.SceneContext.InstallBindings (Zenject.InitialComponentsInjecter componentInjecter) (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:232)
Zenject.SceneContext.RunInternal () (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:183)
Zenject.SceneContext.Run () (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:119)
UnityEngine.Debug:LogException(Exception)
ModestTree.Log:ErrorException(String, Exception) (at Assets/Zenject/Source/Internal/Log.cs:79)
Zenject.SceneContext:Run() (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:129)
Zenject.SceneContext:Awake() (at Assets/Zenject/Source/Install/Contexts/SceneContext.cs:103)

Event raising/handling Issues

To keep the other issues clean and focused I have made this one to discuss changes to event propogation and handling (as mentioned in #17).

The events are mainly there for other things to hook into, as you can make a plugin and put anything into the DI/ECS eco system so some plugins (which track entities or whatever) may want to subscribe to events we would think fairly useless.

Also the issue around components being registered in certain orders shouldnt be an issue, as groups are inclusive, so if you make an entity and add components A, B, C or B ,C A it doesnt really matter, any systems listening to A,B and B,C would still trigger. The only thing that may be a hiccup for you would be if you wanted the B,C group to be triggered AFTER the A,B had been setup, but this is the reason the predicates exist on groups so you can enforce that you not only want Components but also want some state to be true within the entity.

Currently I do not see any problem with the implementation for events but if you can provide specific problem scenarios (and we can then potentially add them to the unit tests), we can see if changes would be needed but currently I don't think you are safe to just assume components will be loaded in a given order, if you do require an order you can use the predicate. The other point about events not being used/needed cause little overhead and make the system more pluggable.

Anyway have a think and if you get together some examples we can look into it further.

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.