Git Product home page Git Product logo

entitas's People

Contributors

arielschoch avatar cconstable avatar chrischu avatar dethrail avatar idnoise avatar jamesmcmahon avatar kaladrius2trip avatar kalinon avatar kolesnick avatar kumokairo avatar marczaku avatar movrajr avatar mrobaczyk avatar mzaks avatar npruehs avatar readmecritic avatar robert-wallis avatar roygear avatar sbeca avatar sdarkwell avatar sschmid avatar thematthopkins avatar trumpets avatar vkuskov 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  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

entitas's Issues

Pool attribute name is not very descriptive

In my opinion the generated attributes that associate a component with a pool is not very descriptive. Imagine I have a pool called "Core", then the attribute will also be called "Core".

I think it would be better to have a PoolAttribute that takes an enum value and those enum values are generated by the code generator.

i.e. instead of having an attribute [Core] it would be an attribute [Pool(Pools.Core)].

Conflict when IComponents from different pools assigned to a single entity

Let's say I have 2 pools named A and B, with 1 component each.

using Entitas;
[A]
public class AComponent : IComponent {}
[B]
public class BComponent : IComponent {}

Code generation creates two arrays, one for each Pool. AComponent will be assigned at index 0 of his pool, BComponent will also be assigned to index 0 in his own pool's array:

    public const int A = 0;
    public const int TotalComponents = 1;

    static readonly string[] components = { "A" };
    public const int B = 0;

    public const int TotalComponents = 1;

    static readonly string[] components = { "B"};

Therefore, it results in conflicts when we want to group by AComponent and BComponent.

        var entity = Pools.a.CreateEntity ();
        entity.isA = true;
        Debug.Log ("Entity isA?: "+entity.isA);
        Debug.Log ("Entity isB?: "+entity.isB);

entity is incorrectly considered as both A and B.

Handling component properties, not only fields

Hello,

First I want to say I really enjoy Entitas, and the efforts you put in easing coding in Unity :)

I noticed that the CodeGen isn't handling component properties actually, only fields. Could this case be handled? It would be very convenient, I'm using NoesisGUI and the XAML bindings require properties.

Destroyed Entity will be passed to Reactive Systems

Entities that are marked as _isEnabled = false should not be passed into an IReactiveSystem anymore.
You should be able to reproduce this behaviour with the following steps:

  • Create 'Systems' with the 2 following systems:
  • CreateEntitySystem : IInitializeSystem
  • ListenToAnyComponentSystem : IReactiveSystem
  • In CreateEntitySystem.Initialize(): Add a AnyComponent to that Entity
  • In CreateEntitySystem.Initialize(): Destroy that entity immediately
  • In 'ListenToAnyComponentSystem' listen to Matcher.AnyComponent.OnEntityAdded()
  • Notice that the destroyed Entity is still passed in
  • Any call to entity.AddComponent(...) will lead to: new EntityIsNotEnabledException("Cannot add component!")

Expected behaviour: Destroyed entities shouldn't be passed into IReactiveSystems anymore

ReactiveSystem gets wrong entities

Hi,

When GroupEventType.OnEntityRemoved is used with IReactiveSystem, List<Entity> entities parameter on method public void Execute(List<Entity> entities) doesn't correspond to the removed entities (seems to match random entities within the pool)

It would be useful to get the removed components

Regards

System Configuration

Proposing a new feature for configuring Entitas game systems.

Some systems might need some configuration at initialization time - think difficulty level, game speed, mouse sensitivity. A good example is the GameBoardSystem of Match-One:

https://github.com/sschmid/Match-One/blob/master/Assets/Sources/Features/GameBoard/GameBoardSystem.cs

Here, the probability of creating a piece over a blocker (91%) is hard-coded. While in some cases this is quite fine, because these values don't change too often, in other cases designers are forced to tweak these values on an hour-to-hour basis.

Passing systems an initial configuration would allow the game to read this configuration from a text data file (much like blueprints for entities), and reduce turn-around time.

Entitas/Generate: 'Path contains invalid chars' on Windows

Windows 8.1
Unity 5.1.0f3
Entitas version 0.17.0 from bin/Entitas.zip

Entitas/Generate from menu throw an exception:

ArgumentException: Path contains invalid chars
System.IO.Directory.CreateDirectory (System.String path) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.IO/Directory.cs:81)
Entitas.CodeGenerator.CodeGenerator.CleanDir (System.String dir) (at Assets/Libraries/Entitas.CodeGenerator/CodeGenerator.cs:57)
Entitas.CodeGenerator.CodeGenerator.Generate (System.Type[] types, System.String[] poolNames, System.String dir, Entitas.CodeGenerator.IComponentCodeGenerator[] componentCodeGenerators, Entitas.CodeGenerator.ISystemCodeGenerator[] systemCodeGenerators, Entitas.CodeGenerator.IPoolCodeGenerator[] poolCodeGenerators) (at Assets/Libraries/Entitas.CodeGenerator/CodeGenerator.cs:15)
Entitas.Unity.CodeGenerator.CodeGeneratorEditor.Generate () (at Assets/Libraries/Entitas.Unity.CodeGenerator/Editor/CodeGeneratorEditor.cs:29)

Properties.cs

string[] getLinesWithProperties(string properties) {
            var delimiter = new[] { Environment.NewLine };         
            return properties
                .Split(delimiter, StringSplitOptions.RemoveEmptyEntries)
                .Select(line => line.TrimStart(' '))
                .Where(line => !line.StartsWith("#", StringComparison.Ordinal))
                .ToArray();
        }

properties comes in this format:

    properties  "Entitas.Unity.CodeGenerator.GeneratedFolderPath = Assets/Generated/\\nEntitas.Unity.CodeGenerator.Pools = \\nEntitas.Unity.VisualDebugging.DefaultInstanceCreatorFolderPath = Assets/Editor/DefaultInstanceCreator/\\nEntitas.Unity.VisualDebugging.TypeDrawerFolderPath = Assets/Editor/TypeDrawer/\\n\\nEntitas.Unity.CodeGenerator.Pools = PoolName\\nEntitas.Unity.VisualDebugging.DefaultInstanceCreatorFolderPath = Assets/Editor/DefaultInstanceCreator/\\nEntitas.Unity.VisualDebugging.TypeDrawerFolderPath = Assets/Editor/TypeDrawer/\\n\nEntitas.Unity.CodeGenerator.Pools = PoolName\nEntitas.Unity.VisualDebugging.DefaultInstanceCreatorFolderPath = Assets/Editor/DefaultInstanceCreator/\nEntitas.Unity.VisualDebugging.TypeDrawerFolderPath = Assets/Editor/TypeDrawer/\n"   System.String

where delimiters "\n" and "\n", but expected "\r\n" (from Environment.NewLine )

dirty fix that helped
replace
var delimiter = new[] { Environment.NewLine };
to
var delimiter = new[] {"\n", "\\n"};

With default setup
image

Add Namespace to Code Generator

When using the Code Generator outside of unity, it would help to be able to specify the namespace of each generated file. Otherwise each time I regenerate the files, i will have to fix my code manually.

Matcher OnEntityRemoved does not allow accessing components

Usually, I'd try to use IReactiveSystemsas much as possible to enforce an event-driven game architecture. However, some systems might require to react to the removal of entities, much like the ScoreSystemin Match One:

https://github.com/sschmid/Match-One/blob/master/Assets/Sources/Features/Score/ScoreSystem.cs

However, the OnEntityRemovedmatcher is triggered after some required components might already have been removed. In another version of the system, I was forced to attach the system to the OnEntityWillBeDestroyedevent of the pool directly, in order to access relevant component data before it's too late.

https://github.com/npruehs/Match-One-Blueprints/blob/develop/Source/Assets/Sources/Features/Score/ScoreSystem.cs

Is this the recommended way to design this behaviour? If not, I'd request new matchers for this scenario.

Return removed components to the component pool

As a performance optimization the Code Generator creates component pool for each generated component type (https://github.com/sschmid/Entitas-CSharp/blob/develop/Tests/Tests/Entitas.CodeGenerator/Fixtures/PersonComponent.cs#L15)

When you replace or remove components, the old component gets pushed to the component pool.

However, neither e.RemoveAllComponents() nor pool.DestroyEntity() will make use of the component pool and won't push them back.

That should be fixed...

[Question] Example Entitas Scene demonstrating subsystem and UnityEngine data types/objects

Hey y'all,

Can I get a pointer to an example scene that demonstrates how subsystems are setup. As well as array of example interaction with all UnityEngine datatypes (GameObject, Vector3...etc). I stumbled on it an existing example scene in one of the projects available here a week ago, but for the life of my are unable to locate that scene again. Thanks for your attention and consideration.

How to get started with components and systems

Hi,
I am studying Entitas-CSharp via Match-One example. I can understand almost class but i can not understand how to create classes, step by step.
For now i just understand that components class should be create and generated first, but can not understand how to create system and then link them together with game controller?
Could you please take some notes to describe process to create classes, step by step? I mean how to create a skeleton of project.
Thank so much for awesome framework! (Sorry for my bad of english)

Extract Code Generator Utility Methods

Many of the methods of the class Entitas.CodeGenerator.ComponentsGenerator are incredibly useful for writing own code generators. Following methods could be extracted to be accessible from other generators:

  • shouldGenerate
  • getFieldInfos
  • isSingletonComponent

Why close pull requests and recreate the commits instead of merging?

I just watched your presentation and what you guys have built seems extremely impressive. One project related question I had is why are you closing pull requests and recreating the commits instead of merging them directly in from contributors?

Few examples:

I don't want to be to be too critical of your workflow if it works for you but it seems like this approach has a few drawbacks:

  1. It makes this project look less active then it is because the contributor count remains at 1 instead of reflecting the accurate # of contributors.
  2. It doesn't give people proper credit in the git commit history.
  3. It makes thing harder to track, because an unaccepted PR looks the same as an accepted PR.

There was a post about this on the programmer stack exchange that covered some alternative ways to avoid merge commits (assuming that is what you are avoiding).

Again, I don't want to over step my bounds, this is an attempt at some constructive cristism. Please ignore if I am misunderstanding something about the project or your workflow.

Undo/Redo

Hi,
I know this is a little bit off topic. But maybe you can help me. Let's say I want to write a strategy based game where you can create and place new "entities" (e.g. a warrior) on a battle field. This warrior can move, attack and so on. I I like to provide a Undo/Redo functionality for the game. Would it be possible have an separate layer for Undo/Redo or should Undo/Redo be integrated into the core of Entitas?
Undo/Redo should be capable of following use cases:

  1. Create entity <-> Delete entity
  2. Add component to entity <-> Remove component from entity
  3. Set new value of property on component -> Restore old value on component

Any hint would be greatly appreciated.
Thanks,
Sven

[Question] What is the point of OnEntityUpdated?

Hello again,

I have another question about the design of Entitas. What is the intended use of OnEntityUpdated? I understand what it is actually can be used for but I am unclear about its intended purpose, given that Entitas use a faux immutable paradigm that fires on Add or Remove on any entity change.

Here is the implementation that I am refering to in Group.cs:

public void UpdateEntity(Entity entity, int index, IComponent previousComponent, IComponent newComponent) {
    if (_entities.Contains(entity)) {
        if (OnEntityRemoved != null) {
            OnEntityRemoved(this, entity, index, previousComponent);
        }
        if (OnEntityAdded != null) {
            OnEntityAdded(this, entity, index, newComponent);
        }
        if (OnEntityUpdated != null) {
            OnEntityUpdated(this, entity, index, previousComponent, newComponent);
        }
    }
}

So I get that if you want to cover your bases and have a catch all method for both adds and removes you could use update. But the CreateGameBoardCacheSystem class in the MatchOne example makes me think I may be missing something.

snip:

    var gameBoardElements = pool.GetGroup(Matcher.AllOf(Matcher.GameBoardElement, Matcher.Position));
    gameBoardElements.OnEntityAdded += onGameBoardElementAdded;
    gameBoardElements.OnEntityUpdated += onGameBoardElementUpdated;
    gameBoardElements.OnEntityRemoved += onGameBoardElementRemoved;
}

void onGameBoardElementAdded(Group group, Entity entity, int index, IComponent component) {
    var grid = _pool.gameBoardCache.grid;
    var pos = entity.position;
    grid[pos.x, pos.y] = entity;
    _pool.ReplaceGameBoardCache(grid);
}

void onGameBoardElementUpdated(Group group, Entity entity, int index, IComponent previousComponent, IComponent newComponent) {
    var prevPos = previousComponent as PositionComponent;
    var newPos = (PositionComponent)newComponent;
    var grid = _pool.gameBoardCache.grid;
    grid[prevPos.x, prevPos.y] = null;
    grid[newPos.x, newPos.y] = entity;
    _pool.ReplaceGameBoardCache(grid);
}

void onGameBoardElementRemoved(Group group, Entity entity, int index, IComponent component) {
    var pos = component as PositionComponent;
    if (pos == null) {
        pos = entity.position;
    }
    var grid = _pool.gameBoardCache.grid;
    grid[pos.x, pos.y] = null;
    _pool.ReplaceGameBoardCache(grid);
}

Maybe this is just a poor usage choice in the example project but it looks like it would be redundant to use OnEntityUpdated here as both OnEntityRemoved and OnEntityAdded have already been called at this point.

I was using this example as a basis for some of my own systems and I saw this oddity and wanted to make sure I wasn't missing behavior.

Generate EntityIndex

Generate Indexer class for fast lookups for fields in components tagged with [IndexKey]

public class NameComponent {
  [IndexKey]
  public string value;
}

var entity = pool.GetEntityWithNameValue("Player1");

Method name of IStartSystem could lead to conflicts when used on a MonoBehaviour

In my application it makes sense to manifest some systems in form of a MonoBehaviour on a GameObject (for example when I want to configure them through the editor, like giving them a reference to another GameObject that is relevant to them).

However since the method in IStartSystem is called Start, Unity thinks this method is actually the MonoBehaviour Start method that is used by Unity to initialize stuff.

Maybe it would be better to rename IStartSystem.Start to IInitializeSystem.Initialize.

Beside from fixing the problem described I also think it would nicely illustrate the distinguish between the Unity Start/Update concepts and the Entitas Initialize/Execute concepts.

[Wiki] New Example Project!

Hey guys,

I just recently got finished converting the Unity 2d roguelike example over to Entitas.

screenshot

The game is fairly simple but more involved than any of the current example projects. I've open sourced it at https://github.com/JamesMcMahon/entitas-2d-roguelike.

I'd love to get feedback on my implementation as this is the first time using both Entitas and the Entity Component System style of design. Please don't hesitate to open issues to point out anything that can be improved.

If the project looks good to you guys it would be great to get it added to the Wiki so that there is another example project for people to look at.

Does Entitas will support Unity 4.x in future?

For history reason,my unity version is 4.5.5f1, when I building Match-One example scene,there have some errors as follow:

  1. The unity(version < 4.6) doesn't has the NewUi (UnityEngine.UI);
  2. In Entitas.Unity.VisualDebugging and demo script there using Transform.SetParent function which doesn't exist in older unity version.
    thanks!

Designing levels in the editor and Entitas

I saw you guy's UNITE talk and I'm so hyped for the framework. But I'm during the Q&A (48:27 into the talk) one person made a very valid point and that is the framework leaves the editor powerless. I saw your example project of cars and in the hierarchy there was game controller a camera and nothing else. One can't even change the position of the goal without changing code.

Since components are just data, isn't it possible to read data from anywhere? My idea is that maybe the code generator can generate placeholder MonoBehaviours. MonoBehaviours can be used by the designer to design. Then when the scene is run, add the placeholder entities to the pool with a start system that reads the data from the placeholder MonoBehaviour?

Thank you for making Entitas open source.

Suggestion: Allow multiple components of the same type

Hey,

I've been looking into Entity Systems for a while and I've recently played around with Entitas.
One scenario I came across where Entitas is inappropriate is in any Application/Game that might play with multiple components of the same type on an Entity.

Let me give you an example:
Any kind of RPG or MOBA or other game that involves buffs or similar things.
For example you have a character and you give him multiple HealOverTime/HealthRegeneration components. The data they hold is just time between "ticks", time of last "tick", amount of "ticks" and how much they heal. They might vary in their data like the ticks left, the interval, the next time they will tick etc. so you can't combine them to just one component. They could all play together well with the same system and the same component structure. As far as I can tell Entitas does not support this thus far as it only allows one component of a given type to be present on any Entity. Even two Component of the same type with just varying start time and therefore just an offset in tick time and amounts left would require its own Component class and to be added to the group to be handled.

I've been starting to try to add this to Entitas myself but I've not yet had that much time to get it done in a way that works well with the code generation and just adding component list storages and adding methods for it is a big hacky. I think it would be based to adapt the system to this functionality from the core.

Is there already a way to solve this with Entitas that I might have missed? If not, do you plan to add this kind of functionality?
I do believe this would be a good feature that could apply to many possible game scenarios.

Add Testing Examples

While I love Entitas and I am thinking of using it for a commercial product but I'm struggling a bit with the best way to write tests against an Entitas project.

It would be great if we had some examples of testing an Entitas based project, either by updating the existing examples with test code or adding new examples.

Unity: Windows Store build doesn't work

I really like the Entitas system for Unity (I use version 5.2.0f3), but when I try to build a project with Entitas for Windows Store (I tried 8.1 and 10), I get a lot of compiler errors caused by the code generator. I am sure this is caused by .NET for Windows Store apps (https://msdn.microsoft.com/en-US/library/windows/apps/br230232.aspx) that is missing some types that are present in the full .NET framework. As all issues are in the code generation part I wonder if it is possible to exlude this part of the project from the build, because it seems to be needed in the editor only.
To reproduce the problems just build the Match-One example project with the Windows Store build target.

Thanks in advance,

Jannis

Here is the editor log, I'm sorry that I can only provide it in German, but maybe it's still useful.

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(43,17): error CS0246: Der Typ- oder Namespacename 'FileInfo' konnte nicht gefunden werden. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 43)

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(43,59): error CS1061: 'System.IO.DirectoryInfo' enth�lt keine Definition f�r 'GetFiles', und es konnte keine Erweiterungsmethode 'GetFiles' gefunden werden, die ein erstes Argument vom Typ 'System.IO.DirectoryInfo' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 43)

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(43,76): error CS0103: Der Name 'SearchOption' ist im aktuellen Kontext nicht vorhanden.

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 43)

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(48,25): error CS0103: Der Name 'Console' ist im aktuellen Kontext nicht vorhanden.

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 48)

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(58,37): error CS1061: 'System.Type' enth�lt keine Definition f�r 'GetInterfaces', und es konnte keine Erweiterungsmethode 'GetInterfaces' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 58)

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(64,38): error CS1061: 'System.Type' enth�lt keine Definition f�r 'IsInterface', und es konnte keine Erweiterungsmethode 'IsInterface' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 64)

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(67,29): error CS1061: 'System.Type' enth�lt keine Definition f�r 'GetInterfaces', und es konnte keine Erweiterungsmethode 'GetInterfaces' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 67)

Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs(92,30): error CS0117: 'System.Attribute' enth�lt keine Definition f�r 'GetCustomAttributes'.

(Filename: Assets\Libraries\Entitas.CodeGenerator\CodeGenerator.cs Line: 92)

Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs(24,31): error CS0117: 'System.Attribute' enth�lt keine Definition f�r 'GetCustomAttributes'.

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs Line: 24)

Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs(305,30): error CS0117: 'System.Attribute' enth�lt keine Definition f�r 'GetCustomAttributes'.

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs Line: 305)

Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs(311,25): error CS1061: 'System.Type' enth�lt keine Definition f�r 'GetFields', und es konnte keine Erweiterungsmethode 'GetFields' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs Line: 311)

Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs(333,25): error CS1061: 'System.Type' enth�lt keine Definition f�r 'GetFields', und es konnte keine Erweiterungsmethode 'GetFields' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\ComponentExtensionsGenerator.cs Line: 333)

Assets\Libraries\Entitas.CodeGenerator\Generators\IndicesLookupGenerator.cs(77,30): error CS0117: 'System.Attribute' enth�lt keine Definition f�r 'GetCustomAttributes'.

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\IndicesLookupGenerator.cs Line: 77)

Assets\Libraries\Entitas.CodeGenerator\Generators\SystemExtensionsGenerator.cs(21,41): error CS1061: 'System.Type' enth�lt keine Definition f�r 'GetConstructor', und es konnte keine Erweiterungsmethode 'GetConstructor' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\SystemExtensionsGenerator.cs Line: 21)

Assets\Libraries\Entitas.CodeGenerator\Generators\TypeGenerator.cs(30,22): error CS1061: 'System.Type' enth�lt keine Definition f�r 'IsGenericType', und es konnte keine Erweiterungsmethode 'IsGenericType' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\TypeGenerator.cs Line: 30)

Assets\Libraries\Entitas.CodeGenerator\Generators\TypeGenerator.cs(45,41): error CS1061: 'System.Type' enth�lt keine Definition f�r 'GetGenericArguments', und es konnte keine Erweiterungsmethode 'GetGenericArguments' gefunden werden, die ein erstes Argument vom Typ 'System.Type' akzeptiert (Fehlt eine Using-Direktive oder ein Assemblyverweis?).

(Filename: Assets\Libraries\Entitas.CodeGenerator\Generators\TypeGenerator.cs Line: 45)

Proposal for logging infrastructure in Entitas

Motivation:

There are two main reasons why one would consider introducing logging in a game.

  1. Finding and fixing bugs
  2. Gathering data for analytic purposes

Logging for Bug finding and fixing

It is fairly easy to unit test a system and therefore write robust code which transforms state in a expected manner. This however doesn't mean that one will not run into bugs. There are always a possibility for a behaviour which we do not expect. The unknown unknowns. For this type of situations it is crucial to have a logging infrastructure which can provide us with context and historical development of the state which lead to the bug. It helps us to understand and reproduce unexpected behaviours.

Gathering User Data

There are multiple reasons for gathering user data:

  • Understanding how many people play your game and how often
  • Understanding which parts of the game logic are executed
  • Analyse User input

This data than can be used for refining game design decisions, UI decisions and even for a creation of interactive agents and NPCs.

Hoover this kind of logic is very game specific and can already be achieved with smart use of reactive systems.

Therefore this proposal will concentrate on the Logging for Bug finding and fixing starting from here.

General Context

In order to analyse the logging data every logging statement has to be provided with context.

Time and order related context

  • Time (time stamp), it is the local time of device running the game. It reflects the time when the logging statement was created.
  • Current tick. As Entitas systems are executed on every tick. This can be considered as an additional information to time. Giving us an FPS agnostic view on execution.
  • Log Statement Index. This provides an additional information if we chose to select a time stamp format which is not fine granular enough. (e.g. multiple log statement have the same time stamp)

Time seems to be the important data point for this context. Two other data points can be seen as optional.

Identification context

  • GameId. This can be a static id for the game but it could also contain the game version and device information, because a game compiled for a different platform is technically not the same game.
  • UserId. Can be left blank or set to placeholder value if you want to protect the privacy of your users. However it can be helpful for contacting a user who happened to get all this bugs and crashes.
  • SessionId. If you have a logical concept of a game session.

Entitas specific events

I see two types of events which can help developers in finding and fixing Bugs

  1. State Events:
    • Entity Created
    • Entity Destroyed
    • Component Added
    • Component Removed
    • Component Replaced
    • Pool Cleared
  2. Logical events
    • Initialise System Executed
    • System Executed
    • Reactive SubSystem Executed
    • Event Listener executed (On Entity or on Group)
    • System crashed

This events also need context which is Entitas specific:

Entitas state context

  • Pool Type. Reflects pool the pool which manages the entities which were involved in state events and event listener / reactive sub system execution
  • Pool instance ID. We could potentially have multiple instances of the same pool type. In this case logging the instance id would be very helpful.
  • Entity Creation Index. Gives us a possibility to aggregate all changes happening to an entity during it's life cycle.
  • Entity instance ID. As an entity is pooled and reincarnated after destruction. This gives us a possibility for spotting bugs happening because of bad memory management. (Usage of Retain Release methods)

For component related events it would be nice to see the data the component was storing.
Something like:

  • PositionComponent x:45, y:13 was added
  • PositionComponent x:45, y:13 was replaced with x:45, y:12
  • Position component x:45, y:12 was removed

This would be hard to achieve automatically because a component can store any kind of data. Therefore I suggest to introduce a ILoggableInterface:

interface ILoggable {
   public string LogString {get;}
}

Which when implemented by a component class will lead to a more verbose log statement.

Examples of Log Statements:

2015-12-26T09:56:21Z game1 user1 session1 CorePool 34526 45673 1 e_created
2015-12-26T09:56:21Z game1 user1 session1 CorePool 34526 45673 1 c_added PositionComponent(5,4)
2015-12-26T09:56:21Z game1 user1 session1 CorePool 34526 45673 1 c_replaced PositionComponent(5,4) PositionComponent(5,5)
2015-12-26T09:56:21Z game1 user1 session1 CorePool 34526 45673 1 e_destroyed

Which can be decode as following

Time | GameId | UserId | SessionID | PoolType | PoolInstanceID | EntityInstanceID | EntityCreationIndex | EventName | ComponentRelatedData

Now by searching for game1 user1 session1 CorePool 34526 45673 1 we can find out the whole history of entity with creation index 1.
By excluding the creation index game1 user1 session1 CorePool 34526 45673 we can see how and when this entity instance was reused during the whole session1.

Logging BackEnd infrastructure

Logging all the events that I have described in Entitas specific events means that every instance of the game will generate a massive amount of data. This is why I would suggest using such high level logging only during development and maybe internal beta releases. However even for this controlled scenarios we would need to have a Log receiving part which can handle so much data.

Without trying it out my self, I would suggest to use Papertrail and see how much load it can handle. Papertrail provides a nice infrastructure for storing and querying Log statements.

Code Generation in a non-Unity project

I saw at the Wiki where there's two releases, one just for C# and one for with unity stuff. I was wondering if the C# stuff could be used outside of Unity, so I was trying to integrate it into MonoGame. Although I ran into a problem where it seemed intuitive in Unity, the code generation is triggered by clicking on generate. How would i be able to do something similar in say Mono Game?

Conflicting types: 'Entitas.Matcher' conflicts with the imported type 'Entitas.Matcher'

First of all, I'd like to start off saying I really like this ECS framework you built.
The auto-generator tool got me hooked when I saw it. 👍

On to the problem I've been wrestling with back and forth now for 2 days.

After I've created a couple of components and ran the generator, I'm adding the Generated components into my project. In doing so, when I go to create an Entity or Pool, I get an error of type conflicts due to there being a declaration in the Entitas.dll and the public partial class Entity generated in each component file.

The type 'Entitas.Matcher' in 'G:\Test\TestProject\Components\Generated\ComponentIds.cs' conflicts with the imported type 'Entitas.Matcher' in 'G:\Test\Entitas\bin\Debug\Entitas.dll'. Using the type defined in 'G:\Test\TestProjectComponents\Generated\ComponentIds.cs'. G:\Test\TestProject\Components\Generated\TestProject.Components.InputComponentGeneratedExtension.cs 25

I'm pretty sure I could be doing this all wrong, but it thought I went through the steps as described in the wiki,

Any thoughts?

image

[Feature] Entity Blueprints

Following up our previous discussion about allowing Entitas to be more data-driven, here's what I'd love to do, similar to what we are doing in our CBES:

  1. Create a Blueprint class with two properties:
    1. List of component types to add to the entity
    2. Dictionary mapping component property names to component property values.
  2. Adapt the code generator to provide an overload Pool.CreateEntity(Blueprint) that basically does three things:
    1. Create a new entity.
    2. Iterate over the component types of the blueprint.
    3. Add all components with their respective initial values taken from the dictionary.

This allows for easy serialization of entity data while preserving the flexibility and performance of the generated code.

What do you think? Would this be the correct way to go with Entitas?

Also, am I right that you are currently building a new code generator? Should I wait until you're finished?

CodeGenerator generated folder adds unnecessary "Generated/" suffix

If one changes the generated folder setting in the properties to a folder that does not end with "Generated/", that suffix is added.

I think that is unnecessary. For example when I only want to have one folder with all generated code, but I want to distinguish between the files generated by Entitas and by other frameworks/own code by putting them in different folders (e.g. "Assets/Generated/Entitas" for entitas and "Assets/Generated/OtherFramework" for another framework).

This is currently not possible (at least not without an necessary folder level ("Assets/Generated/Entitas/Generated").

ReactiveSystem will trigger itself when replacing components in execute

Hi,

Below is the project configuration :

  • NextTurnComponent
  • ComputeNextTurnSystem, RenderNextTurnSystem and InitSystem
  • GameController

NextTurnComponent

public class NextTurnComponent : IComponent {
    public int timeBeforeNextTurn;
}

ComputeNextTurnSystem

public class ComputeNextTurnSystem : IReactiveSystem {

    private readonly int nextTurnTimeToDecrease = 10;

    public IMatcher trigger { get { return Matcher.NextTurn; } }

    public GroupEventType eventType { get { return GroupEventType.OnEntityAdded; } }

    public void Execute(List<Entity> entities) {
        foreach (Entity entity in entities) {
            if(entity.hasNextTurn){
                entity.ReplaceNextTurn(entity.nextTurn.timeBeforeNextTurn - nextTurnTimeToDecrease);
                if( entity.nextTurn.timeBeforeNextTurn < 0){
                    entity.RemoveNextTurn();
                }
            } else {
                Debug.Log ("ComputeNextTurnSystem : Entity Match NextTurn but doesn't have nextTurnComponent");
            }
        }       
    }
}

RenderNextTurnSystem

public class RenderNextTurnSystem : IReactiveSystem, IStartSystem {

    Text nextTurn;

    public void Start() {
        nextTurn = GameObject.Find ("NextTurn").GetComponent<Text>();
    }       

    public IMatcher trigger { get { return Matcher.NextTurn; } }

    public GroupEventType eventType { get { return GroupEventType.OnEntityAdded; } }

    public void Execute(List<Entity> entities) {

        Entity entity = entities.SingleEntity ();
        if (entity.hasNextTurn) {
            nextTurn.text = "Next turn  : " + entity.nextTurn.timeBeforeNextTurn;
        } else {
            Debug.Log("RenderNextTurnSystem : Entity match but doesn't have component NextTurn");
        }
    }
}

InitSystem

public class InitSystem : IStartSystem, ISetPool {
    Pool _pool;

    public void SetPool(Pool pool) {
        _pool = pool;
    }

    public void Start () {
        _pool.CreateEntity ().AddNextTurn (1000);           
    }
}

GameController

public class GameController : MonoBehaviour {

    Systems _systems;

    void Start() {
        Random.seed = 42;

        _systems = createSystems (Pools.pool);
        _systems.Start();

    }

    void Update() {
        _systems.Execute();
    }

    Systems createSystems(Pool pool) {
        #if (UNITY_EDITOR)
        return new DebugSystems ()
            #else
            return new Systems()
                #endif
                .Add (pool.CreateInitSystem ())
                .Add (pool.CreateRenderNextTurnSystem ())
                .Add (pool.CreateComputeNextTurnSystem ())

                ;

    }
}

Expected behaviours

  1. RenderNextTurnSystem shows NextTurnComponent.timeBeforeNextTurn value
  2. ComputeNextTurnSystem decreases NextTurnComponent.timeBeforeNextTurn value
  3. When NextTurnComponent.timeBeforeNextTurn reaches 0 => call RemoveNextTurn() from Entity
  4. There is no more Entity with NextTurn component and RenderNextTurnSystem and ComputeNextTurnSystem won't be executed

Console Log

RenderNextTurnSystem : Entity match but doesn't have component NextTurn
ComputeNextTurnSystem : Entity Match NextTurn but doesn't have nextTurnComponent

IReactiveSystem must not be executed when there is no more matched component.

Solution works

I've replaced IReactiveSystem by IExecuteSystem and it works as expected

public class ComputeNextTurnExecuteSystem : IExecuteSystem, ISetPool {
    Group group;

    public void SetPool(Pool pool) {
        group = pool.GetGroup (Matcher.NextTurn);
    }

    private readonly int nextTurnTimeToDecrease = 10;


    public void Execute() {
        Entity[] entities = group.GetEntities();
        if (entities.Length > 0) {
            Entity entity =  entities[0];
                entity.ReplaceNextTurn (entity.nextTurn.timeBeforeNextTurn - nextTurnTimeToDecrease);
                if (entity.nextTurn.timeBeforeNextTurn < 0) {
                    entity.RemoveNextTurn ();
                }
        }

    }
}
public class RenderNextTurnExecuteSystem : IExecuteSystem, IStartSystem ,ISetPool {
    Group group;

    public void SetPool(Pool pool) {
        group = pool.GetGroup (Matcher.NextTurn);
    }

    Text nextTurn;

    public void Start() {
        nextTurn = GameObject.Find ("NextTurn").GetComponent<Text>();
    }       

    public IMatcher trigger { get { return Matcher.NextTurn; } }

    public GroupEventType eventType { get { return GroupEventType.OnEntityAdded; } }

    public void Execute() {

        Entity[] entities = group.GetEntities();
        if (entities.Length > 0) {
            Entity entity = entities[0];
                nextTurn.text = "Next turn  : " + entity.nextTurn.timeBeforeNextTurn;
        }
    }
}

Regards

Entity doesn't clean suscribed event delegates on entity destroy

If some class (on custom code) suscribes to OnComponentAdded, OnComponentReplaced or OnComponentRemoved events in Entity class, that entity could be reused after destroyed but will still trigger the events to old suscribed delegates.

I think Entity class should force to clean suscribed delegates of those event dispatchers on entity destroy.

Create Nuget Package for Entitas

I really like your tool, I just wish it was a nuget package that I could consume rather than download the src and add files to my project.

Generate non-public pool access method

In generated Entity extension methods for all components, there's a duplicate for retrieving a component from the pool.

Example:

var component = _positionComponentPool.Count > 0 ? _positionComponentPool.Pop() : new PositionComponent();

This line is used from Add and Replace extension methods (e.g. AddPosition and ReplacePosition), and might be useful for other generated extension methods as well. It could be extracted to a non-public method (e.g. AllocPosition).

[Enhancement] Code Generator as DLL

I'd like to request that the Code Generator aspect of Entitas be packaged as a binary for consumption.

The reasoning behind this is to avoid cases where any automated tooling might break code within the Code Generator, as any crash during the code generation results in an uncompilable project.
I personally had this happen due to a careless mistake where Resharper wanted to refactor "Tag" into "EntityTag" and included one of the string matchers used in the Code Generator library.

Packaging the Code Generator as a binary should not be an issue as it's the part of the project that does not need to be altered during generation. The common consumers of the package don't need to alter the Code Generator, as they depend on its robustness.

Generator does not work if Entitas is not in Assets folder root

Reproduced in a new Unity Project:

  1. Create a folder "Plugins" in Assets

  2. Add the Entitas package into Plugins. So the structure looks like:

    Assets/Plugins/Entitas/Enitas
    Assets/Plugins/Entitas/Enitas.CodeGenerator
    Assets/Plugins/Entitas/Enitas.*

  3. Create a simple PositionComponent

  4. Configure Entitas generated folder as: Assets/Source/Generated/

  5. Click Generate

Actual: ComponentIds and Pool are Generated, PositionComponent is not. Moving Entitas into Assets fixes the problem.

Component value change in Inspector doesn't use entity componentPool

I found out when change a component's value when game running in Unity Inspector, the event OnEntityRemoved and OnEntityUpdated doesn't work. The first one get call with Component's value already changed. The last one get call with previousComponent equals to newComponent. I wonder if it is an issue.

Repository does not contain VS projects for Entitas.Unity.* projects

This is particularly problematic if someone wants to contribute to the project and does use Visual Studio instead of MonoDevelop (because then the projects cannot be generated by Unity).

In general I feel it would be better if anyone that forks/checks out the repository could immediately start working with ALL the projects in any given development environment.

Maybe I am just not thinking about all the cases, but I don't think there would even be a big negative side effect with including the VS projects in the repository, right?

GroupEventType.OnEntityRemoved is also triggered when replacing a component

Hi,

Below is the project configuration :

  • 2 components Position and PlayerSelectActionAttack
  • MonoBehaviour script AttackPointerController with 2 observers on Matcher.AllOf(Matcher.PlayerSelectActionAttack, Matcher.Position)
  • MonoBehaviour script AttackController to create / destroy the entity with the 2 components
  • Entitas System PlayerSelectActionAttackSystem with a group on Matcher.AllOf(Matcher.PlayerSelectActionAttack, Matcher.Position)

Position

public class PositionComponent : IComponent {
      public float x;
      public float y;
}

PlayerSelectActionAttack

public class PlayerSelectActionAttackComponent : IComponent {
}

AttackPointerController

public class AttackPointerController : MonoBehaviour {
    Vector3 position;
    GroupObserver onAdded;
    GroupObserver onRemoved;

    void Awake () {
        Pool pool = Pools.pool;
        Group group = pool.GetGroup(Matcher.AllOf(Matcher.PlayerSelectActionAttack, Matcher.Position));

        onAdded = group.CreateObserver (GroupEventType.OnEntityAdded);
        onRemoved = group.CreateObserver (GroupEventType.OnEntityRemoved);

        position = transform.position;
    }

    void Update(){
        foreach (Entity entity in onAdded.collectedEntities) {

            position.x = entity.position.x;
            position.y = entity.position.y;
            Debug.Log ("Show Attack Pointer Position To " + position);
            transform.position = position;
        }

        foreach (Entity entity in onRemoved.collectedEntities) {
            Debug.Log ("Hide Attack Pointer");
        }

    }
}

AttackController

public class AttackController : MonoBehaviour {
    Pool pool;
    Entity attackSelectedEntity;
    Toggle toggleView;


    void Awake () {
        toggleView = GetComponent<Toggle> ();
        pool = Pools.pool;      
    }

    public void onAttackCheckedValueChanged(){
        if (toggleView.isOn && attackSelectedEntity == null) {      
                attackSelectedEntity = pool.CreateEntity().IsPlayerSelectActionAttack(true).AddPosition(0,0);       
        } else if(attackSelectedEntity != null){
            Debug.Log("Destroy entity");
            pool.DestroyEntity(attackSelectedEntity);
            attackSelectedEntity = null;
        }
    }
}

PlayerSelectActionAttackSystem

public class PlayerSelectActionAttackSystem : IExecuteSystem , ISetPool {
    Group _group;

    public void SetPool(Pool pool) {
        _group = pool.GetGroup(Matcher.AllOf(Matcher.PlayerSelectActionAttack, Matcher.Position));
    }

    public void Execute() {
        foreach (Entity entity in _group.GetEntities()) {               
            Vector3 point = Camera.main.ScreenToWorldPoint (Input.mousePosition);
            entity.ReplacePosition (point.x, point.y);      
        }
    }
}

Expected behaviours

  1. User clicks on Attack button, AttackController is called ONCE and creates new Entity pool.CreateEntity().IsPlayerSelectActionAttack(true).AddPosition(0,0);
  2. AttackPointerController onAdded observer is updated with the created Entity and Console shows Show Attack Pointer Position To [Entity.position]
  3. PlayerSelectActionAttackSystem _group field is updated with the created Entity and entity position's is replace on each frame

Console Log

AttackPointerController onRemoved.collectedEntities must be empty but the console log shows :

Show Attack Pointer Position To (-1.3, -4.3, -4.1)
Hide Attack Pointer
Show Attack Pointer Position To (-1.3, -4.3, -4.1)
Hide Attack Pointer
Show Attack Pointer Position To (-1.3, -4.3, -4.1)
Hide Attack Pointer
Show Attack Pointer Position To (-1.3, -4.3, -4.1)
Hide Attack Pointer
...

It seems like observers ignores the GroupEventType and populate onRemoved = group.CreateObserver (GroupEventType.OnEntityRemoved); with the newly created entity

Another issue

When the Entity created in AttackController is destroyed (pool.DestroyEntity(attackSelectedEntity)), there are an Exception on AttackPointerController

EntityDoesNotHaveComponentException: Cannot get component at index 11 from Entity_2()
Entity does not have a component at index 11
Entitas.Entity.GetComponent (Int32 index) (at Assets/Lib/Entitas/Entity.cs:87)
Entitas.Entity.get_position () (at Assets/Sources/Generated/PositionComponentGeneratedExtension.cs:5)
AttackPointerController.Update () (at Assets/Scripts/AttackPointerController.cs:25)

Regards

Fast but no exceptions

Add a compiler flag ENTITAS_FAST_BUT_NO_EXCEPTIONS

Potential code to exclude:
Checks on entity

  • Add
  • Remove
  • Replace
  • Get
  • Retain
  • Release

Checks on Pool

  • onEntityReleased

and maybe more...

[Enhancement] Code Generator failure checks

AFAIK, at the moment the (Unity) code generation first deletes the generated code folder as it assumes that execution of the code generation will happen without faults or errors.

I suggest that we first write to a temporary folder and not replace/remove the code generated folder without confirmation of a successful execution of the Code Generator. (Exceptions / errors)

Check for updates: TlsException: Invalid certificate received from server

Can't check for updates because Mono doesn't trust the connection.

TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a
Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.validateCertificates (Mono.Security.X509.X509CertificateCollection certificates)

Explanation:

That’s probably because you do not trust the site you are connecting to. Note that a default installation of Mono doesn’t trust anyone!
http://www.mono-project.com/docs/faq/security/

Possible solution #-1, actively ignore security concerns:

ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => { return true; };

Alternative solutions: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/

[Feature] Excluding multiple components

Excuse me if I am missing something but it looks like when using the IExcludeComponents interface there is no way to exclude multiple components. It looks like we need a Matcher.AnyOf, essentially the opposite of Matcher.AllOf, to allow this behavior.

Is this correct or am I missing something?

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.