It seems entity systems are really popular here. Links posted by other users convinced me of the power of such system and I decided to try it. (Well, that and my original code getting messy)

In my project, I originally had a SceneManager class that maintained needed logic and structures to organize the scene (QuadTree, 2D game). Before rendering I call selectRect() and pass the x,y of the camera and the width and height of the screen and then obtain a minimized list containing only visible entities ordered from back to front.

Now with Systems, originally in my first attempt my Render system required to get added all entities it should handle. This may sound like the correct approach but I realized this was not efficient. Trying to optimize It I reused the SceneManager class internally in the Renderer system, but then I realized I needed methods such as selectRect() in others systems too (AI principally) and make the SceneManager accessible globally again.

Currently I converted SceneManager to a system, and ended up with the following interface (only relevant methods):

/// Base system interface
class System
    virtual void tick (double delta_time) = 0;

    // (methods to add and remove entities)

typedef std::vector<Entity*> EntitiesVector;

/// Specialized system interface to allow query the scene
class SceneManager: public System
    virtual EntitiesVector& cull () = 0;

    /// Sets the entity to be used as the camera and replaces previous ones.
    virtual void setCamera (Entity* entity) = 0;

class SceneRenderer // Not a system
    vitual void render (EntitiesVector& entities) = 0; 

Also I could not guess how to convert renderers to systems. My game separates logic updates from screen updates, my main class have a tick() method and a render() method that may not be called the same times. In my first attempt renderers were systems but they was saved in a separated manager, updated only in render() and not in tick() like all other systems. I realized that was silly and simply created a SceneRenderer interface and give up about converting them to systems, but that may be for another question.

Then... something does not feel right, isn't it? If I understood correctly a system should not depend on another or even count with another system exposing an specific interface. Each system should care only about its entities, or nodes (as optimization, so they have direct references to relevant components without having to constantly call the component() or getComponent() method of the entity).

Edit (answer chosen):

I've chosen the suggestion to the IsVisible component. But I added the following optimization:

First I created a IsVisibleOptimized class that descend from the original IsVisible.

The IsVisibleOptimized instances share a list where they push all the entities that are visibles and remove the ones that are not. Most systems are already designed to use the IsVisible component, they not need to change, because the IsVisibleOptimized component registers with both names and can be casted to a IsVisible. But the RenderSystem that is a critical system of the game and need to work as fast as possible, it calls the static function IsVisibleOptimized::getAllVisibles() rather than iterate through all the entities in game to see which are visible.

The CullingSystem uses the QuadTree that the SceneManagementSystem maintains updated each frame. First a call to the getAllVisibles() function and then to the quad tree selectRect(). If there are new entities they are set as visibles (causing them being added to the list too) and the ones that are not visible any more are set as not visible (this removes them from the list too). No more SceneManager with cull() function that had no sense.

The reason to have both versions of the IsVisible component is that the optimized version may not suit all type of games.

If I replace the IsVisibleOptimized for a simple IsVisible at entity build, the game still works (maybe not as efficient) and only the RenderSystem and the CullingSystem need to be replaced for implementations that don't use getAllVisibles().

IsVisibleOptimized makes sense in a game that have big maps with more hidden entities than visible ones and where the screen rect represents a small part of the game map.

I happy with this solution.

  • \$\begingroup\$ Generally any scene management specific to rendering will go inside the rendering system. Eg. Unity has a Transform component which stores the object's position, rotation and scale. It also has a scene hierarchy (in the GameObject component), and a component's Transform is relative to the hierarchy. This way you can switch out rendering systems as needed (eg. a map view, game view, etc..). As far as breaking rules - it's often better to have more queries between small components, rather than shoveling tonnes of stuff into a single component to avoid "breaking the rules" \$\endgroup\$ – pentaphobe Dec 5 '12 at 5:27
  • \$\begingroup\$ The problem here is that my scene management is not specific to rendering. If was only rendering I could maintain a quadtree internally in the rendering system and update the quadtree each render system tick. But I use the same quadtree for collisions. SceneManager updated the quadtree when an entity changed. \$\endgroup\$ – Hatoru Hansou Dec 5 '12 at 11:43
  • \$\begingroup\$ yeah, sorry - to clarify: I meant that the rendering system will often have its own (optimised) scene management separate to logical scene management \$\endgroup\$ – pentaphobe Dec 12 '12 at 0:24

You can make CullingSystem that updates entites every tick() and set their attributes: isVisible for rendering and isProcessable for logical updates. Though, in my opinion only rendering should care about entities being inside screen rect. Logic shouldn't know about such thing as screen, therefore its culling algorithm may differ and not depend on scene object.

Scene is only a visual representation (human view) of game world and it's only purpose to help human players interact with this world. If a game architecture is designed in such way, you can see as game world might live and update even without any views attached.

| improve this answer | |
  • \$\begingroup\$ Agree, and that is why I want to separate code and put it in the correct systems. For now I will go for the isVisible component as also recommended in the previous answer. I like the name CullingSystem too. I still open to more possibilities. \$\endgroup\$ – Hatoru Hansou Dec 6 '12 at 17:35

I would wager you're attempting to mix multiple concepts here.

There are multiple culling algorithms used in video games. The most notable is the one used to determine what should be drawn on the screen and to what level of detail. This culling is purely render engine driven and shouldn't live outside the render system at all.

Another is what is considered within the purview of an entity to react upon. For example, once you get close enough to a specific entity that is considered hostile, maybe it will attack you, but only if it can actually see you with it's eyes. If a corner blocks it's vision despite how close you are, maybe it cannot sense you. This type of culling happens with the AI subsystem by exploiting functionality provided by other subsystems.

For example, provide a collision sphere around an entity to represent it's sensory area to detecting other entities, notably players. If an entity enters that collision area, it gets added to a list of collided players associated to that NPC. For every collided player, the NPC attempts a ray-cast to find them. But if obstacles block their view of those collided players, it cannot react. Once I move to where I'm no longer obstructed by a wall, the NPC can enter it's attack state and move toward me because all it's behavior validation succeeded.

There is nothing wrong with inter-system dependencies in a game. What you do want to minimize is the component-to-component dependencies. This way you avoid what can often be expensive lookups during the subsystem's update loop, destroying your cache coherency.

| improve this answer | |
  • \$\begingroup\$ Useful, thanks. Since the day I posted the question, I have come to the conclusion that some dependency between systems is necessary and ok. But I will maintain my current design of a CullingSystem separated from a RenderSystem because my current RenderSystem is only in charge of encapsulating the underlying render api, but it has no sense of culling, it simply render anything you tell it to render (maybe RenderSystem is not the correct name). As this is working and I'm not disconform with its performance I will let it for now. \$\endgroup\$ – Hatoru Hansou Dec 18 '12 at 22:53
  • \$\begingroup\$ I agree that it makes sense to have a layer that abstracts away the render api, particularly in the case where you plan to support both OpenGL and DirectX on various platforms. But the culling aspects of what to show based upon the camera's vantage point is simply another layer atop of the the rendering system. It seems we both agree to this point. But this culling system's purpose isn't to provide any sensory or detection-like functionality for anything else in the system. If that is needed, it should be designed separately based upon data structures that will aid in it's performance. \$\endgroup\$ – Naros Dec 20 '12 at 0:16

If you need to share the SceneManager due to the code architecture, then maybe you could add an isVisible component. That way you could have a SceneSystem which would require an isVisible and Position components and based on those it would add entities to the quad tree. Then in the update function it would set the isVisible component on Entities which are visible. The RenderingSystem would then just query the isVisible, Position and Renderable components when updating. The components are exemplary of course.

I know this isn't the best design when it comes to scene graphs in entity systems, but it should work well given what you already have.

| improve this answer | |
  • \$\begingroup\$ I was thinking about a Visible component. I know the versatility of Entity Systems is payed somehow but I feel it would performs much worse than my previous approach with the SceneManager. Maybe I will try it for now and see how performance is affected as I continue to adding entities. It still doesn't feel right, but maybe I can continue forward and think in a better design for a future project. \$\endgroup\$ – Hatoru Hansou Dec 5 '12 at 12:30
  • \$\begingroup\$ ... now that I think, maybe if I create a special entity representing the set of on screen entities, updated by the scene management code and consulted by the renderer system before rendering. This should be faster than check the Visible component of all entities of the game. And I can forget about the ugly "SceneManager: public System" interface and have only "System" around. \$\endgroup\$ – Hatoru Hansou Dec 5 '12 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.