Changes between Version 7 and Version 8 of SimulationArchitecture


Ignore:
Timestamp:
Jan 8, 2010, 12:57:43 AM (14 years ago)
Author:
Philip Taylor
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SimulationArchitecture

    v7 v8  
    11= Simulation System Architecture =
     2
     3''Part of the [wiki:TDD_Simulation simulation documentation]. (See pages linked from there, for details on the implementation of the concepts described here.)''
    24
    35== Concepts ==
     
    911An important concept in the entity system is the '''entity'''. This represents any kind of 'thing' in the simulation world - a person, a tree, a rock, an arrow, and more abstract things like event triggers, players, and player input controllers.
    1012
    11 Entities consist of a set of '''components'''. A component is a largely self-contained piece of data and code, responsible for one part of the behaviour of an entity. One component might be responsible for rendering the entity; another for keeping track of its location in the world; another for tracking its health and reducing it when damaged and killing the entity when reaching zero.
     13Entities consist of a set of '''components'''. A component is a largely self-contained piece of data and code, responsible for one part of the behaviour of an entity. One component might be responsible for rendering the entity; another for keeping track of its location in the world; another for tracking its health and reducing it when damaged and killing the entity when it reaches zero.
    1214
    1315Each component is an object instance in the C++ code. However, there is no C++ object representing an entity - each component is tied to an '''entity ID''' (an arbitrary integer), and an entity exists only as a concept defined by the set of components with the same entity ID.
     
    1921== Scripting ==
    2022
    21 To simplify development, improve iteration times, and avoid crashes, most gameplay code should be written in !JavaScript. Each component can be written either completely in C++, or completely in JS. Native<->scripted component communication is exactly the same as native<->native and scripted<->scripted, except that a native component may not expose all its methods to script.
     23To simplify development, improve iteration times, and avoid crashes, most gameplay code should be written in !JavaScript. Each component can be written either completely in C++, or completely in JS. Native<->scripted component communication is exactly the same as native<->native and scripted<->scripted, except that a native component might expose only a subset of its methods to scripts.
    2224
    23 Components should be written in C++ only when necessary for run-time performance, memory usage, or to interact with C++ parts of the game engine (e.g. the renderer). Run-time performance should only be a concern for code that is executed every frame (e.g. render functions), or executed every simulation turn for a large number of entities (e.g. checking for any unit coming into range). Components should be initially written in JS, and if profiling indicates they are slow, then try to optimise the JS or call it less often (e.g. run on a timer rather than on every simulation turn), and if it's still unfixably slow then it could be rewritten in C++.
     25Components should be written in C++ only when necessary for run-time performance, memory usage, or to interact with C++ parts of the game engine (e.g. the renderer). Run-time performance should only be a concern for code that is executed every frame (e.g. position interpolation functions), or executed every simulation turn for a large number of entities (e.g. checking for any unit coming into range). Components should be initially written in JS, and if profiling indicates they are slow, then try to optimise the JS or call it less often (e.g. run on a timer rather than on every simulation turn), and if it's still unfixably slow then it could be rewritten in C++.
    2426
    2527Component scripts support ''hotloading'': while the game is running, you can edit and save a script file, and it will be immediately reloaded and used in the game with no need to stop or restart. (The data associated with each component will not be changed at all, only the code.)
     
    2931Most entities will behave similarly to each other, but there are a few cases where we would like to have differing implementations of one type of component.
    3032
    31 For example, most entities should have some kind of `Position` component, which responds to `MoveTo` calls during a simulation update and can be queried by the renderer for the location in the current frame. (Frames are much more frequent than simulation updates). For entities that move smoothly, the component should typically respond to the renderer by interpolating from its position in the previous simulation turn to the current turn, and therefore it needs to remembers its previous position at the start of each turn. For entities that are not expected to move in straight lines (e.g. ballistic units like arrows), linear interpolation will be inaccurate. For entities that are not expected to move at all (e.g. trees), remembering the previous position every turn is wastefully inefficient.
     33For example, most entities should have some kind of `Position` component, which responds to `MoveTo` calls during a simulation update and can be queried by the renderer for the location in the current frame. (Frames are much more frequent than simulation updates). For entities that move smoothly, the component should typically respond to the renderer by interpolating from its position in the previous simulation turn to the current turn, and therefore it needs to remember its previous position at the start of each turn. For entities that are not expected to move in straight lines (e.g. ballistic units like arrows), linear interpolation will be inaccurate. For entities that are not expected to move at all (e.g. trees), remembering the previous position every turn is wastefully inefficient.
    3234
    3335It would be possible for a position component implementation to have a flag that switches between linear and parabolic interpolation, but the code would become increasingly complex as more special cases were added, and it would not be able to optimise the storage and computation of positions for non-moving entities (of which there might be tens of thousands).
     
    6264For components that are large or frequently used, the serialized output for saved games should be as efficient as possible. Any internal caches that can be safely reconstructed after deserialization should be omitted. Any data that was initialised from `paramNode` should not be serialized unless it has changed - store some kind of placeholder value instead and reconstruct the value in `Deserialize`.
    6365
    64 (TODO: the serialization API should expose some way to detect when efficiency is required, vs when the full state should be dumped for checksumming or debugging.)
     66== Entity templates ==
    6567
    66 == TODO ==
     68Entities are constructed from an '''entity template''', defined in XML (typically in the binaries/data/mods/public/simulation/templates/ directory). The root element of the XML file contains one element per component, giving the component type's name. Each component element contains initialisation data for that component - typically either empty, or a series of elements giving various data fields. This data is passed to the component's `Init` method.
    6769
    68 Things to talk about:
    69  * Entity templates and initialisation
    70  * SYSTEM_ENTITY
    71  * The details of actually writing code
     70== System entity ==
     71
     72Some gameplay code is 'global', and it only makes sense to have one copy of it; but it can benefit from being written in the component infrastructure, e.g. for serialization and message passing and script interfacing. This code can be implemented as a ''system'' component, which is like a normal component but (as a convention, not enforced by the system) given the entity ID `SYSTEM_ENTITY`. It can then be accessed and used by any simulation code in the same way as a normal component.