Jump to content

  • Log In with Google      Sign In   
  • Create Account


Component based game and component communication


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
32 replies to this topic

#1 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 10 January 2014 - 05:33 AM

Hello,

 

I want to use a component based system in my game. It should have subsystems for logic, and every subsystem has a list of components which stores the data. 

 

The problem is: How to sync the components?

  • Should I have a pointer to another component (Movement subsystem needs position of entity, so its component has a pointer to the position component?)
  • Should I go with a observer pattern, which notifies all other (registered) subsystems, that the position of the entity has changed? Then I need a reference from the movement subsystem to the position subsystem, to get the actual position, because with the notify I only want that the notified subsystem adds a "to-be-processed" entry to it's queue. This should avoid a confuse processing of the entities.

Are there other (better?) approaches?

 

Thank you for your tips!



Sponsor:

#2 AlanSmithee   Members   -  Reputation: 972

Like
1Likes
Like

Posted 10 January 2014 - 07:49 AM

Hi!

 

Im not sure of how your current setup is working, and what a "subsystem" is, but in general a system should act on an entity with one or more component.

For instance, the MovementSystem could move an entity that has a displacement and velocitty component, the RenderSystem could render an entity that has a displacement and appearance component etc. This way the system needs to know about certain components, but the components does not need to know about each other.

 

Look here: http://www.gamedev.net/page/resources/_/technical/game-programming/implementing-component-entity-systems-r3382

 

In some cases I guess components will need to know about each other, I do not have that need yet, so I can not offer you a good answer.

I do however think you should implement some sort of messaging system.

 

Look here: http://www.gamedev.net/page/resources/_/technical/game-programming/case-study-bomberman-mechanics-in-an-entity-component-system-r3159

 

Good luck =)


Edited by AlanSmithee, 10 January 2014 - 07:49 AM.


#3 phil_t   Crossbones+   -  Reputation: 3222

Like
0Likes
Like

Posted 10 January 2014 - 06:55 PM


1) Should I have a pointer to another component (Movement subsystem needs position of entity, so its component has a pointer to the position component?)
2) Should I go with a observer pattern, which notifies all other (registered) subsystems, that the position of the entity has changed? Then I need a reference from the movement subsystem to the position subsystem, to get the actual position, because with the notify I only want that the notified subsystem adds a "to-be-processed" entry to it's queue. This should avoid a confuse processing of the entities.

 

Those two bullets seem like solutions to different problems:

 

1) How do I get component X for an entity, given I have component Y for that entity

2) You have code that needs to know when position has changed, how do you set that up?

 

Can you clarify your question?

 

For (2), I would ask, do you really need this?


Edited by phil_t, 10 January 2014 - 06:55 PM.


#4 ankhd   Members   -  Reputation: 1179

Like
0Likes
Like

Posted 10 January 2014 - 07:26 PM

hello.

There should be no right or wrong way to do this as long as the out come is the same.

 

In my carry Object Component I have a owner pointer.

 

this way when I update the carryobjectcom it calls the owner objects virtual functions for Getpos, size and things

to pick up a object this way the component can do its job and not worry about  what values it need to control as the owner does all that with its other components

you just need a common interface for functions the components need to use to do there job.

 

So for my carry objects componet it can move the object to the unit it wants to pick up and when it gets to the target it picks it up.



#5 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 12 January 2014 - 05:33 AM

The architecture works like sneftel wrote in this thread:

http://www.gamedev.net/topic/463508-outboard-component-based-entity-system-architecture/

 

Given I have a physics system, a translation system and a position system. The component which stores the position is the position component linked to the position system. My physic and translation system have to change the position component.

It seems to me, that there are two ways:

I can store the position in a vector in the translation component and physics component also, and implement a observer system, to sync, when the position is updated, every other component. (The translation system changes the position -> updates the position component over the position system -> the position component notifies all listeners, to sync the position) That means, that my translation system stores a pointer to the position system, to update the position.

 

I can store a pointer to the position component in every component I need it. That means that I also need a pointer to the position system, to get a pointer to the position component. So I don't need to sync the components manually, but my components depends on other, which I don't like.

 

I like way one  a little bit more, because I have dependencies only on system level. But maybe there are other ways to do this.

phil_t wrote another way, in which he has a sync primitive, which stores two components and after every frame update, updates the position over this primitive.

There are much ways to do this, but maybe there are other pros and cons in my ways, which I don't see.



#6 haegarr   Crossbones+   -  Reputation: 3898

Like
7Likes
Like

Posted 12 January 2014 - 06:34 AM

For a moment take a step back from having a straight look at the components, and take a look at the game loop. It has a structure oriented on tasks: Processing input, a first animation pass, physics, collision resolution, perhaps a second animation pass, and rendering at last (more or less; details are not important here). Notice that the tasks are based on top level sub-systems, and depend on components managed by probably lower level sub-systems.

 

Looking at the rendering sub-system, does it need to be notified about position changes done in any of the animation, physics, or collision tasks? No! At the moment of rendering, the sub-system can safely assume that any and all positions and orientations (i.e. the entire placement) are settled and well defined, because beforehand running sub-systems have done their jobs. Any notification of a "RenderComponent" (I use it here for clarification; I'm not a fan of RenderComponent at all) done before would be a waste.

 

Looking at the collision sub-system, does it need to be notified about position changes? No! Because collision detection is a self-contained process, running in its entirety but not on request on every little move.

 

Of course, having an explicit motion sub-system (or using the animation sub-system) requires a way that the sub-system can set the placement as needed. There need to be a reference from the animation sub-system to a placement component (which is probably managed in another sub-system). But there is neither a need for an animation component (whatever it means exactly) to refer to the placement, nor for the placement component to notify the animation (component or sub-system).

 

In summary I mean that in consideration of all the discussion of linking, messaging, slots and whatnot, one should in the first place think whether notification in each particular case is needed at all. The use of sub-systems allows for concentrated and perhaps in order processing, and that does not work well if the program jumps forth and back in code. Concentration may be yielded in by letting one and the same sub-system handle different but related components, too. (All this does not exclude that in some cases notification may be meaningful.)


Edited by haegarr, 12 January 2014 - 06:44 AM.


#7 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 12 January 2014 - 06:57 AM

Ok you mean, that one system (for example physics system) knows it's dependency to the position system, and every update the first thing it does, is requesting the position. So there is no need for manually syncing.

 

But one question remains, how to store position in the physics component, or is this not needed? I don't want to store a vector in the physics component also, because of duplicate data. A pointer is ok, but I think it breaks encapsulation, because one component needs to know one other...



#8 haegarr   Crossbones+   -  Reputation: 3898

Like
1Likes
Like

Posted 12 January 2014 - 07:33 AM


But one question remains, how to store position in the physics component, or is this not needed? I don't want to store a vector in the physics component also, because of duplicate data. A pointer is ok, but I think it breaks encapsulation, because one component needs to know one other...

A wise man avoids to commit self and says … "it depends" ;)

 

Notice that using an external physics library may require you to copy the placement anyway, and that in both directions. An internal physics solution may read the placement from the spatial sub-system piece by piece on demand, or it may read it in a block and bring it into a format required for an efficient processing (w.r.t. physics). However it is done, the physics system should be able to pull the data (data should IMHO not need to be pushed into the physics sub-system).



#9 wintertime   Members   -  Reputation: 1640

Like
0Likes
Like

Posted 12 January 2014 - 07:34 AM

Well, instead of duplicating components, just extract them by splitting the storage from the systems.

Add some helper template class (component-manager/array/vector/storage/..., whatever you like to call it) that keeps one kind of components and gives search/addition/deletion by id and easy access through iterators.

Then give each system a reference to one or if needed two or more of these.

Then let the systems one after another in a fixed order do their update-work so that they can rely on other systems to have done what was needed before.



#10 PandaDragonThing   Members   -  Reputation: 311

Like
1Likes
Like

Posted 12 January 2014 - 03:53 PM

I think if you want to send data between components, you should have them an anchor to a common root which actually handles sending the information between components.

For example, in my game, I have components bound to individual entities which gives them functionality. I also have some specialized components such as an InputComponent and a RenderComponent. Each component haves a pointer back to it's root entity and my entity has a function called BroadCastMessage( MessageClass data ) which calls the function RecieveMessage( MessageClass data ) for all bound components. All my component has to do is use it's pointer to its root entities to broadcast a message to other components.

My MessageClass is basically this:

struct MessageClass
{
   char* pchName;
   void* pvData;
}

You would use the name to listen for certain events from other components like maybe "UpdateXPos" or something to that effect. Also since I know how a message would be built based on the name, I'll know how to typecast the data to its correct format. Another way you might do it, but it leads to a bit more work, is to use an array of bytes for the data. You would have to break down the data you need to send into individual bytes and then rebuild it up when a component receives it.

 

EDIT
Here's a complete example:

//InputComponent
void KeyPressed( char chKey )
{
   if( chKey == 'w' )
   {
      int iMovement = 10;
      pEntity->BroadcastMessage( MessageClass( "UpdateXPos", &iMovement );
   }
}

//RenderComponent
void RecieveMessage( MessageClass data )
{
   if( strcmp( data.pchName, "UpdateXPos" ) == 0 )
   {
      m_iPosX += *((int*)data.pvData);
   }
}

Edited by PandaDragonThing, 12 January 2014 - 04:08 PM.


#11 phil_t   Crossbones+   -  Reputation: 3222

Like
4Likes
Like

Posted 12 January 2014 - 06:20 PM


But one question remains, how to store position in the physics component, or is this not needed? I don't want to store a vector in the physics component also, because of duplicate data. A pointer is ok, but I think it breaks encapsulation, because one component needs to know one other...

 

I've seen some ECS implementations that do just that - the physics component would store a pointer to a position component.

 

In most implementations I've seen though, you can avoid this by having it be the physics system that knows about the physics and position components. The individual components don't need to know about each other. This implies that a system needs to be able to correlate two components together (i.e. know that they belong to the same entity). I've seen a few ways to do this:

    1) A component knows which entity it belongs to, and so the physics system enumerate though all Physics components, find their entity and ask that entity for the Position component.

    2) A system is kept up-to-date with a list of entities (or entity ids) that apply to it (e.g. for the physics system, this would be all entities that have both a Physics and Position component. It enumerates through these entities and asks for their Position and Physics components. 

    3) A system enumerates through all entities and asks if they have a Physics and Position component. For those that have both, it does its thing. For those that don't, it just ignores it.

 

(2) and (3) are just slight variations on the same basic concept, and have the advantage (?) that a component doesn't need to actually know to which entity it belongs.

 

The "one true position" is stored in the Position component, no "syncing" between components are systems is required. Of course, like someone mentioned earlier, your Physics system may be using a 3rd party library to do its physics, and so when the physics system does its processing you will need to keep positions sync'd between the physics library and the Position component.


Edited by phil_t, 12 January 2014 - 06:21 PM.


#12 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 14 January 2014 - 05:28 AM

Ok every time I update a physics component, I first ask the position system, for the position of this component. Seems pretty good for me. So I don't have dependencies at component level only, on system level.

 

But now, there is another problem, most rendering engines (like OGRE or Irrlicht, I use Irrlicht) have a scene manager, in which their entities, positions and rotations are stored. This rendering libary is no system it will be initialized in the application class, which also initializes a entity manager (this manager is responsible to initialize the systems, I hope you can imagine this architecture, if not ask).
That means I need a reference to my render libary in my render system, and my render system is responsible for adding the entity also to the render libary, and update the position in the render libary.

 

Is that a good way to go? Or should the render system initialize it's "own" rendering libary? Make this a difference? Maybe several things of Irrlich should initialized in the application and several should initialize the render system???

So much questions!



#13 crancran   Members   -  Reputation: 372

Like
1Likes
Like

Posted 14 January 2014 - 11:51 PM

First off, don't be afraid to break parts of a process with the entity system into multiple passes.  

 

Our scene (aka map) loader process loads map metadata.  It's during this process where entity IDs get allocated and whatever metadata references components is used to create the necessary components associated to this entity ID.  At this end of this first phase, the entity is in an inactive state and the components which have been allocated are stored in the various owning subsystems but are flagged as pending commits.  (Think relational database here).

 

Once the entity has been constructed either by using a combination of prefab archetype data and map metadata or simply map metadata, the next step must begin.  This next step is an inspection pass where systems or components (depending on your design) can look into an entity and determine what other stuff exists.  If required, references to other systems or components can be obtained and stored.  

 

Do be mindful of using pointers, particularly if they're not weak_ptr types.  At any moment, any outside source could cause a component to be removed from an entity and if you depend on that component, have stored a raw pointer and do not have checks in place to eliminate the reference, this could lead to unexpected behavior.  I generally prefer either the use of a component handle where a handle is converted to a pointer at the time of access or maintain copies of the data; generally of which the later is usually more cache friendly and gives a slightly higher performance depending on your data structures.

 

Assuming that your game doesn't support a concept such as teleport, generally the physics component's position & orientation will be seeded from the transform during the inspection phase.  This is what makes sure the physics simulation starts out synchronized with the entity's transform data.  If the entity has no transform, then you cannot initialize the physics component, and thus it remains "pending" or "inactive".

 

The next step is to activate your entity, at which point all systems are informed and the components which were initialized & synchronized successfully are moved into an active state and thus the system's update process will begin to manage the state for that component & entity.  Either here or in the prior inspection step is where you could allocate whatever subsystem specific data objects that are needed.  For example, a RigidBody for physics, a Collider for the Collision system, your SceneNode and various other renderable aspects in the render system, etc.  

 

The point is once activation has completed, the entity's component state should be ready to be manipulated by any outside source.

 

When you begin to apply movement to your entity, the force/direction get applied to some movement/velocity component.  When the physics system begins to step it's simulation, it takes all entities with a physics component and have a force/velocity and applies those values to the rigid bodies in the simulation and then steps the physics world simulation.  If collisions are detected, then an event can be fired and any system interested in collisions can react.  If no collisions took place and position/orientation were modified, the physics system can emit a position/orientation update message.  The transform system can receive it and update the entity's position/orientation.

 

Here you have two options:

A) have the systems which manage your scene render objects also listen for physics events and update the scene's transform/orientation as well

B) have the transform system emit a second message after having changed the transform.  

 

Now if your game had a teleport system, your transform system, physics system and all those render object systems might register to be notified upon a TeleportationEvent, then they simply update their position/orientation based on the transport system's knowledge of where you left and where to spawn your character perhaps on a new map or in another zone or area of the current map.

 

One thing I will also caution you on is try to avoid leaking system specific data into your components.  I find often that people will create say a Light component, place all the data regarding how to construct a light in the render system and then have the component hold a pointer or some reference to the render system's Light object implementation.  Instead, I prefer the idea of creating some internal data structure storage where the system holds the Light object's implementation pointer and can relate that back to a component of a specific entity.  In some cases it's been more efficient to marry parts of the component's data with the specific systems implementation pointers and store all that in a specific structure and simply iterate those each frame and use a series of events to replicate changes from the components or other system changes to the internal structure the system maintains at set intervals.

 

As far as to your last question regarding the rendering library, there is really no set way.  I generally code against a set of interfaces and so my engine's framework is much like that of CryEngine where an IRenderer interface is exposed that gives you access to the 3D rendering library.  This class initializes the library, allows me to attach it to a specific window handle to begin rendering, exposes a render method, has support to restart the 3D library, exposes the scene graph, etc.  I simply have the engine framework construct the Renderer class during startup.  I leave the application class responsible for being a thin wrapper around the framework and exposing a series of listener methods and such which can be overwritten based on application needs such as OnActionEvent(), OnKeyEvent(), OnMouseEvent(), OnPreUpdate(), OnUpdateFixed(), OnUpdate(), and OnPreRender(), etc.

 

Feel free to ask any questions, hopefully it gives you a clearer idea.  Just remember that the entity system is an abstraction layer that sits way above the underlying systems in the engine.  It's basically the system or systems which designers in AAA titles interact with in the editors to create these elaborate games.  What happens at the physics, rendering, and other various low-level systems are well below the entity framework but are influenced by "inputs" given to the components.

EDIT:
One thing I forgot to mention above is that once an entity has been activated and you add/remove components from the entity, those changes are once again considered "pending".  This means that another inspection/activation process must be performed on the entity to allow various systems/components to determine whether or not the entity's state continues to satisfy the requirements of some systems and if not cleanup the existing data if it exists and treat the component as though it was just created but couldn't be initialized due to missing dependencies.


Edited by crancran, 15 January 2014 - 12:00 AM.


#14 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 15 January 2014 - 02:04 AM

Wow, thank you very much for this long explanation, that made much things clearer.

 

I think, I will use a observer pattern event system on the component, which notifies on value change (position changed) some systems. But instead, of switch to the notified system, and process the event, I only add the entity to a queue, and in the next update the entity will be processed.

 

I like the two pass approach very much, and think, it will be implemented in this way! Also the component handler idea is good, but I think, this will be done in the system base class. My other systems make a positionSystem->getPosition(entityId), and the getPosition method will check if the component exists, so the check will be on data access. Thank you!

 

You talk about low level systems and components. I must confess that I don't know exactly how the architecture above the "low level" systems look like. I thought that I have my components -> systems -> one entity manager -> application. But this is wrong or? My application class would startup and initialize the entity manager, render libary, ai libary and such things. The entity manager gives the pointer to the systems. Do I need another level of "high level" systems? Don't know how the common way is.

 

EDIT:

Do you have a addEntity, removeEntity,... methods in your rendering libary also, so you only have the references to the rendering engine only in your libary class?


Edited by Dominik2000, 15 January 2014 - 09:02 AM.


#15 crancran   Members   -  Reputation: 372

Like
1Likes
Like

Posted 15 January 2014 - 08:57 AM

I think, I will use a observer pattern event system on the component, which notifies on value change (position changed) some systems. But instead, of switch to the notified system, and process the event, I only add the entity to a queue, and in the next update the entity will be processed.

 

Your framework should be capable of support both queued events (asynchronous delayed delivery) and immediate events (synchronous delivery).  Depending on the context of the event that occurred, you can determine which makes the most logical sense.  There are often systems that run after other systems and if the prior systems emit an event that the subsequent systems are interested in, delaying it by queuing it up only attributes to having what is commonly called frame lag.

 

You talk about low level systems and components. I must confess that I don't know exactly how the architecture above the "low level" systems look like. I thought that I have my components -> systems -> one entity manager -> application. But this is wrong or? My application class would startup and initialize the entity manager, render libary, ai libary and such things. The entity manager gives the pointer to the systems. Do I need another level of "high level" systems? Don't know how the common way is.

 

One of the worse things you can succumb to is over engineering things.  There is no real right or wrong way to do it.  If you took various game engines and compared their sources, while you'll find some commonalities between how they separate certain things, they generally are coupled in very different ways that made sense to the developers or architects for those projects.

 

If you think about a car engine or a computer for a moment; there are a multitude of pieces that come together to make the final product.  Those pieces are generally put together in a specific order and some pieces rely on other pieces to exist and expose some "connection" or "joint" in order to apply the next piece, right?  A software program of any kind follow similar practices.

 

I generally separate the engine into several low-level building blocks such as Audio, AI, Graphics, Input, Memory, Networking, Physics, Platform/IO, UI, and others.  

 

If we take Audio for example, I might decide to use some third-party audio library such as FMOD or OpenAL  I then generally create several classes that wrap the library and expose an API that should I opt to change the third-party library to another, it would have minimal impact. This is where coding to Interfaces rather than implementation can really make a significant difference.  At this point, we've created the base low-level things necessary for audio.  

 

The next step is to build on this low-level audio framework and expose various aspects in a plug-n-play type of fashion.  This is where the entity framework & components behind to come into play.  So I develop a set of components such as an AudioEmitterComponent which is responsible for emitting various sounds along with an AudioListenerComponent that listens tongue.png.  Depending on your needs, you might find a few other type of components you might want to expose with various attributes for the audio system but you get the idea.

 

The final step to polish off the Audio framework is to expose a series of system classes that are responsible for managing various aspects of audio.  We generally first create a plethora of systems that handle a very specific aspect of audio.  For example, a system that maintains a continual but non-overlapping playback of audio clips based on events dispatched from the combat system.  We have an audio system responsible for zone ambient music so that as a player transitions from one zone to another, the ambient sound from the prior zone fades out and the new zone fades in.  Once we have all those building blocks for the various plethora of audio concepts we want, we begin to see where those systems can be refactored into a common system or smaller number of systems that perhaps does a multitude of things within each one.  It might also lead us down a path to expose a new component for specific purposes and expose it through a custom audio system.

 

Anywho, the point here is to start at the lowest level and build atop of the previous layer.  If you treat creating your game in layers, you'll start to understand how easy it becomes to change things when you want because you've applied sufficient abstraction to do so and decoupled things in a way that supports continual change and maintenance of your codebase without necessarily throwing it away and starting over.  Now don't expect all this overnight of course, this comes with many years of trial and error.  So don't hesitate to throw things away and start fresh if you believe the design is flawed and could be made better.  Iterative programming will lead to better code with time smile.png.

 

TLDR; You wrap your third party library with a set of classes and then you wrap those classes with the entity systems that operate on components.  By manipulating components from the outside in turn influences how the entity system manipulates the internal third party libraries such as OpenAL/FMOD/OGRE/etc.  I use the term wrap lightly in this context because generally some framework allocates your OpenAL/FMOD/OGRE wrapper and then passes the wrapper class reference to your entity systems and then interact with the third party library through your wrapper.  Make sense?


Edited by crancran, 15 January 2014 - 09:04 AM.


#16 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 15 January 2014 - 09:40 AM

Yes it makes sense, you described it very well and detailed.


I don't exactly understand what you mean at your last sentences about a wrapper. Given I have a render system which has initialized my irenderer interface. Behind the interface is OGRE as rendering libary. OGRE has it's own entity and scene node classes. Now I create a wrapper class for these two classes where I store... What? The ogre scenenode and entity? I don't think so, because of the dependencies. Only the mesh and position, and then at the system update the irenderer interface has a setposition method which takes the position maps it in a ogre vector and move it. My render libary Claes is responsible for storing scene node and entity.

#17 crancran   Members   -  Reputation: 372

Like
0Likes
Like

Posted 15 January 2014 - 10:00 AM

Yes it makes sense, you described it very well and detailed.


I don't exactly understand what you mean at your last sentences about a wrapper. Given I have a render system which has initialized my irenderer interface. Behind the interface is OGRE as rendering libary. OGRE has it's own entity and scene node classes. Now I create a wrapper class for these two classes where I store... What? The ogre scenenode and entity? I don't think so, because of the dependencies. Only the mesh and position, and then at the system update the irenderer interface has a setposition method which takes the position maps it in a ogre vector and move it. My render libary Claes is responsible for storing scene node and entity.

 

What I mean by wrapper is a class that knows how to startup OGRE, shutdown OGRE and exposes a set of methods for doing various activities with OGRE.  What you can do is rather than return the Ogre::Entity or Ogre::Mesh objects, you simply expose a set of methods that take the identifiers for those objects, look up their pointers and manipulate them.  Doing so avoids leaking the OGRE objects to the other parts of the engine and keeps it self contained.

 

Of course, there is nothing bad with allowing Ogre's objects to be exposed to your engine if you want, but I generally prefer the former because it enforces a sense of decoupling between implementation and functionality. Some might argue this is highly subjective.


Edited by crancran, 15 January 2014 - 10:01 AM.


#18 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 15 January 2014 - 03:31 PM

It seems also better to me, to have this things separated!



#19 Dominik2000   Members   -  Reputation: 247

Like
0Likes
Like

Posted 17 January 2014 - 04:47 AM

If I have a render system and a render interface, as you described, does the render system have only one component where the render interface pointer is stored? What stores the component in a render system, maybe I could store the mesh string, and the name of the entity?

 

I think, that I have to ensure that the render system runs after each other system, how can I do that? I want the game class to loop trough every system and make an update, but the render system should be the last, because if it run before the position system, it would not move the entity...

 

My way is after all other systems, the render system, get the new position of the entity and sets it in the graphic engine, over my graphic interface api, I think this is a very good way. Are there other improvements, which I can do?



#20 wintertime   Members   -  Reputation: 1640

Like
0Likes
Like

Posted 17 January 2014 - 07:20 AM

Whats so difficult in just calling it last when you need it to be called last? I think its easier to just write a function that calls the system updates in the correct order, than making a loop to handle them generically only to then having to create some complicated dependency checking to make that possible.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS