-
Notifications
You must be signed in to change notification settings - Fork 27
EngineOverview
The engine is split into three distinct layers: the adaptor layer, the common data model and the frontend layer.
In the diagram above, the upper part (the GraphFactory
) is specific to a given Unity scene. If a physics engine is used then this is where the physics engine resides. It is planned that the physics engine will become part of the core engine in future, and it will become easier to swap out the physics engine for other implementations. For a sample scene with physics, see the demo scene called world
in folder Assets/B3d/Demos/Btc/Ocean/Scenes
.
The lower part of the diagram is all provided by the blockchain3d engine in prefab B3dEngineAllInOne
. Requests for graph data flow from left to right. The graph data itself flows from right to left.
Now let's look at each layer in more detail. To follow the implementation of these in Unity, open the prefab B3dEngineAllInOne
from folder Assets/B3d/Engine/Prefabs
. Let's start by looking at the Adaptor Layer.
The adaptor layer is what communicates with the external world. It requests data from a data source. Data sources could be files, web APIs, local applications, whatever we can code for to provide data. The adaptor's job is to manage the data requests and convert the data into a common format called the common data model.
The adaptor layer is stateless, it doesn't cache anything and keeps no record of what data it has dealt with in the past. Each request it receives is treated as a new independent thing that it will blindly fulfil.
An adaptor belongs to a family which is the broadest grouping of data types. A family can be Bitcoin, Ethereum, Twitter etc. An adaptor is also linked to a data provider which is the data source. You can think of an adaptor as being defined by a combination of a family (which defines the data structures) and a data provider (which provides the data).
For example, look at these adaptors in the folder Assets/B3d/Engine/Adaptors/Scripts
:
Adaptor Name | Adaptor Family | Data Provider |
---|---|---|
AdaptorBtcDotInfo.cs |
Btc | blockchain.info |
AdaptorBtcOfflineFiles.cs |
Btc | Files in a Unity resources folder |
These adaptors provide bitcoin data from different data sources. One is online data sourced from blockchain.info, the other is offline data sourced from the Unity resources folder Assets/B3d/Engine/Adaptors/Resources/
.
See the page about adaptors for more details on the adaptors currently available. Now let's look at the implementation of the adaptor layer.
Look at these components on the B3dEngineAllInOne
prefab.
The AdaptorSelector wraps many adaptors, allowing easy switching from one adaptor to another (via script calls to AdaptorSelector.SetChosenAdaptor()
, or via the dropdown list in inspector). Only one adaptor can be active at a time.
The Common Data Model, or Cdm is our modelled truth. The disparate formats of the various data sources are standardised and stored in a common data format based on GraphML. The Cdm is generic and handles any adaptor from any family. The Cdm handles paging and caching. It holds the entire graph pool that we've received so far. It does not know what the "world state" is in the frontend layer. It sends out graph fragments as C# events and any listener can consume them.
The Cdm is implemented with a small class hierarchy that allows for core functionality and family-specific functionality, see the Other Characteristics section later.
In the inspector, the Cdm expects a reference to the game object containing the AdaptorSelector.
The frontend is a visualisation of the modelled truth contained in the Cdm. The bulk of the Unity scene will constitute the frontend layer. All the pretty visuals and the physics engine are here.
In the inspector, the frontend expects a reference to the Cdm being used, and a GraphFactory. The frontend makes requests to the Cdm for data, and when data is returned the frontend calls the appropriate graph factory methods. The graph factory can then do whatever is desired for the particular visualisation (create 3d objects in the scene, for example).
The final inspector field here is the the page size. Any give graph node (in the case of bitcoin, a graph node could be a bitcoin addresss or a transaction) could potentially contain many hundreds or thousands of edges. Instead of trying to request all of the edges at once, the frontend requests data in pages. The page size is simply the number of edges that will be requested per page. For example, consider a bitcoin address that has 100000 transactions (and yes these do exist). With a pages size of 8, page 1 would represent 8 edges linking the address to transactions 1 to 8. Page 2 would represent the edges linking the address to transactions 9 to 16 and so on.
Some of the characteristics of each layer are summarised in the table below:
Layer | Frontend Layer | Common Data Model (Cdm) | Adaptor Layer |
---|---|---|---|
Family | Normally family specific, but doesn’t have to be. Casts the CdmNode and CdmEdge data from the Cdm to the desired family. The family must match the family of the adaptor being used. | Independent of family. Operates on the base classes CdmGraph, CdmNode and CdmEdge. Any family-specific logic is handled by derived classes overriding methods. | Family specific. Operates on the CdmGraph*, CdmNode* and CdmEdge* derived classes. Eg a BTC bitcoin adaptor will use CdmGraphBtc, CdmNodeBtc, CdmEdgeBtc. |
Caching | Not applicable. | Yes. Requests for data will come from the cache here before asking adaptors. | No. Caching only happens in the Cdm. |
Inspector Fields Available | The Cdm to use to send requests to, and to listen to events from. A GraphFactory that implements interface IGraphFactory. The page size to use when requesting data from the Cdm. | The Adaptor to use to send requests to. | The Cdm to use to send graph data to. Adaptor specific fields, eg API keys, URLs. |