sschmid / entitas Goto Github PK
View Code? Open in Web Editor NEWEntitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
License: MIT License
Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
License: MIT License
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.
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/
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.
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.
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?
Hi,
Below is the project configuration :
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
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
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?
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:
Any hint would be greatly appreciated.
Thanks,
Sven
Entitas.Migration project misses target framework which can lead to build errors, since VS can decide which framework it uses and apparently it defaults to 4.0.
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.
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:
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.
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.
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.
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.
About 20% of the time I stop the game in the editor I get a MissingReferenceException occurring in VisualDebugging. I created a new project and an empty scene with only a camera with the code in the following gist attached and I still get the error. Try playing and stopping over and over again and you should be able to reproduce it.
https://gist.github.com/SvDvorak/a15926de8c4f8f519498
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");
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.
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:
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?
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"};
There are two main reasons why one would consider introducing logging in a game.
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.
There are multiple reasons for gathering user data:
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.
In order to analyse the logging data every logging statement has to be provided with context.
Time seems to be the important data point for this context. Two other data points can be seen as optional.
I see two types of events which can help developers in finding and fixing Bugs
This events also need context which is Entitas specific:
For component related events it would be nice to see the data the component was storing.
Something like:
This would be hard to achieve automatically because a component can store any kind of data. Therefore I suggest to introduce a ILoggable
Interface:
interface ILoggable {
public string LogString {get;}
}
Which when implemented by a component class will lead to a more verbose log statement.
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 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.
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)
Hey guys,
I just recently got finished converting the Unity 2d roguelike example over to Entitas.
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.
The README should be updated with the new repository URL for the Go version of Entitas. It has moved to https://github.com/wooga/go-entitas
see #48
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:
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.
Reproduced in a new Unity Project:
Create a folder "Plugins" in Assets
Add the Entitas package into Plugins. So the structure looks like:
Assets/Plugins/Entitas/Enitas
Assets/Plugins/Entitas/Enitas.CodeGenerator
Assets/Plugins/Entitas/Enitas.*
Create a simple PositionComponent
Configure Entitas generated folder as: Assets/Source/Generated/
Click Generate
Actual: ComponentIds and Pool are Generated, PositionComponent is not. Moving Entitas into Assets fixes the problem.
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)].
Hi, I am quite confuse now. Is retained entities bad? Is there anyway to clear the retained entities or move it to reusable entities?
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.
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
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)
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.
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.
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:
CreateEntitySystem : IInitializeSystem
ListenToAnyComponentSystem : IReactiveSystem
CreateEntitySystem.Initialize()
: Add a AnyComponent to that EntityCreateEntitySystem.Initialize()
: Destroy that entity immediatelyMatcher.AnyComponent.OnEntityAdded()
entity.AddComponent(...)
will lead to: new EntityIsNotEnabledException("Cannot add component!")
Expected behaviour: Destroyed entities shouldn't be passed into IReactiveSystems anymore
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?
Add a compiler flag ENTITAS_FAST_BUT_NO_EXCEPTIONS
Potential code to exclude:
Checks on entity
Checks on Pool
and maybe more...
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
RenderNextTurnSystem
shows NextTurnComponent.timeBeforeNextTurn
valueComputeNextTurnSystem
decreases NextTurnComponent.timeBeforeNextTurn
valueNextTurnComponent.timeBeforeNextTurn
reaches 0 => call RemoveNextTurn()
from Entity
NextTurn
component and RenderNextTurnSystem
and ComputeNextTurnSystem
won't be executedConsole 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
The PoolsGenerator generates code, that won't compile.
Assets/Generated/Pools/Pools.cs(11,72): error CS0103: The name 'CoreComponentIds' does not exist in the current context
The wiki page Code Generator at https://github.com/sschmid/Entitas-CSharp/wiki/Code-Generator contains a broken link in the first paragraph:
"In a pure C# project, simply choose your generators like this."
I expected to find a reference implementation of how to fire up a code generator, but found none.
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.
For history reason,my unity version is 4.5.5f1, when I building Match-One example scene,there have some errors as follow:
It would be nice to replace the existing home-grown code gen solution with CodeDom, as the generation code already looks like it's starting to complicated.
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:
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").
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)
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...
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?
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).
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.
Usually, I'd try to use IReactiveSystems
as 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 ScoreSystem
in Match One:
https://github.com/sschmid/Match-One/blob/master/Assets/Sources/Features/Score/ScoreSystem.cs
However, the OnEntityRemoved
matcher 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 OnEntityWillBeDestroyed
event of the pool directly, in order to access relevant component data before it's too late.
Is this the recommended way to design this behaviour? If not, I'd request new matchers for this scenario.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.