Entities (aka. Component Owner/Composite Component)
- High-level "Game object" or "simulation object" which is "built" from multiple "Components" which are attached to it (and owned by it). Therefore thisoften scripted, AI driven, or which represents a major "actor" (participent) in the game/simulation or visible world.
- Often this should be relatively lightweight, user-defined, application-specific class, and should usually not be derived from classes like SceneObject or Actor
- Examples include: Avatar, Unit, Character, Player, Mission, Scenario, Objective, Goal, Aircraft, Vehicle
- In some cases, depending on the application requirements, this may also include: Props/Inventory Items (like Weapons) and Terrain Features (aka. World Geometry/Objects, like buildings, roads, trees, etc.)
Data Objects
- This usually refers to "anything other kind of object" which can be saved (serialized) and which is added to the Asset Database, but which is not technically a "Component" (or any other specialized/pre-defined Visual3D asset type)
What Is the Benefit of Using Asset Database?
Asset Management (Finding, Organizing, and Using by Drag & Drop)
Any Asset Item (or object which is added to the Asset Database), will then be able to be edited, saved, and shown in Asset Explorer, as well as drag-dropped, and shown/found in Asset Selector Dialogs and Add New/Add Instance context menus.
Objects added into Asset Explorer are, in most cases, automatically "persisted" (found, saved, and loaded), can be more reliably found and referenced (via a primarily unique and constant NameID string).
Persistence References
Soon, we will handle automatic "cross-asset" (or cross-file/system) reference persistence, allowing assets to transparently reference other assets (via saved properties) without resulting in these referenced assets being "duplicated" in the file each using asset is saved to. This also applies for networking, allowing consistent referencing across multiple computers (eg. clients and servers).
Loading asset items by a unique NameID allows avoiding complex, slow and error prone "file name-based" references and file system access, and avoids some of the problems with files, such as them being moved, renamed, modifed, or being ambigous (with wrong file beign used due to same file name in different paths/directories).
Prototype Inheritance (Smart Copies, Compact Files)
Also, soon, Asset Items will support "prototype inheritance", which basically means that all instances of the asset will be a "cheap copies" which are very concisely defined (eg. using as little as a few bytes), by only having those property values (or components/settings) which differ from those of their prototype being saved. This will also allow you to have a "centralized" definition of an asset, so that you can modify the prototype (eg. via Object Editor, Entity Editor, or Asset Explorer), and have all instances (which don't override the property which had been modified) to "inherit" that property change.
Source File Syncronization (and Virtual File System)
Asset items which have a "Source File" they were imported from (eg. such as is often the case for Media Assets like Models and Textures), will automatically be associated with that source file, so that they can be looked up by file name/path. And, in many cases, when a source file has been "modified" or "updated", it will be automatically "reimported" - syncronizing changes made in Architect with those made in a 3rd party tool and/or replacing the asset with the newly imported version, depending on the asset type. In some cases, the user will at least be notified of the modified/updated asset, and prompted as to whether it should be reimported (especially important if this would replace changes made to the asset in Architect, instead of just syncronizing changes).
Asset items can be used (by developers/content creators) and deployed (distributed to end-users) without needing the "source files" to be downloaded or deployed as well, reducing download time, disk space used, and start/content loading time (by avoiding need for time consuming importing or caching), and restricting unauthorized modification or use of those assets.
Collaborative Editing
During development (by game developers and content creators), each asset is saved to a XML-based .v3dx files, which can be more easily debugged, hand-edited, and used by other tools/applications. Also, this format allowing them to be stored in version control systems as as Subversion (SVN) or CVS, and allowing multiple users/team members to make modifications to different assets at the same time, or even modifications to the same asset, in cases. More robust logic for "merging" changes made by multiple users to the same asset at the same time, will soon be implemented. However, "syncronizing" (updating and commiting) changes often (eg. daily or even automatically, every several minutes) can greatly help in reducing conflicts in "collaborative editing" or "collaborative world building."
Deployment and Digital Rights Management (DRM)
The many assets which are each saved into their own .v3dx XML file during development will be combined into
Structure of Asset Database
Asset Database has distributed structure. It consists from several parts which are situated in the same locations where project packages are.
Single Asset Database package consists from file named with pattern "<PackageName>.manifest.v3dx" (which is an database index for this part of database) and folder "#Assets" which is situated in the same location as manifest is. The folder contains serialized assets (object's data exactly), when manifest contains only short descriptions of assets to make their populating fast.
Parts of Asset Database can be connected to or disconnected from your project by defining/removing connected packages in project's config file (Tech Demos.v3d for Tech Demos):
<ContentPackages>
<ContentPackageInfo Name="Standard Assets" ShowProjectFolder="true" />
<ContentPackageInfo Name="Demo Assets" ShowProjectFolder="true" />
<ContentPackageInfo Name="Tech Demos" ShowProjectFolder="true" />
</ContentPackages>
Using this example, 3 packages are connected to the project: "Standard Assets", "Demo Assets" and "Tech Demos".
For this case, Asset Database can be situated in such locations:
- File "Projects\Standard Assets\Standard Assets.manifest.v3dx" and folder "Projects\Standard Assets\#Assets" (if exists).
- File "Projects\Demo Assets\Demo Assets.manifest.v3dx" and folder "Projects\Demo Assets\#Assets".
- File "Projects\Tech Demos\Tech Demos.manifest.v3dx" and folder "Projects\Tech Demos\#Assets".
One of the connected packages should be default. Default package name defined in project's config like this:
<DefaultObjectDBProject>Demo Assets</DefaultObjectDBProject>
(Note: DefaultObjectDBProject will be renamed to DefaultAssetPackage).
Default package will be used for saving new assets created in the project when Asset Database is saved.
For saving Asset Database you should:
- Press "Save World" button
- Press Ctrl-S hotkey
- When closing Architect, answer "Yes" on question "Would you like to save changes in Asset Explorer?"
For all this 3 cases, Asset Database, current scene and terrain/environment will be saved.
How Do I Make A Class Saveable (or Serializable)?
So long as you have your class "marked up" with standard .NET attributes (or implementing a standard .NET interface) for serialization, then that class can be added to the Asset Database, and any changes made to instances of it will be persisted to disk when you perform "Save World" (and if the asset is explicitly saved by other actions such as "Save Scene", "Save Terrain" or "Save Game").
The suggested way of doing this is by applying [DataContractAttribute] to your asset/component type (eg. class) and only applying [DataMemberAttribute] to those fields or properties which should be saved, which can include non-public (eg. private) members.
You should also be sure that your base classes (which you have derived from directly or indirectly) are marked up in a similar way (usually using the same types of attributes or interfaces) as your own class.
Classes which are marked up with [SerializableAttribute] (as was often done prior to .NET 3.0 for use with BinaryFormatter), are also supported, in which case all fields (whether public or non-public) are saved by default, and you have to mark those which should not be saved with [NonSerializedAttribute].
Classes which implement ISerializable or IXmlSerializable are also saved, though using the custom logic defined in those interface implementations. Usually user-defined derived classes will not be able to add additional members (fields or properties) which are able to be saved, however.
Enums or Enumerations are automatically saveable, however, you can apply [EnumMemberAttribute] to define the name used for saving each enum member/value, as well as [DisplayNameAttribute] to control what text is shown for that enum member/value in Object Editor.
If a class does not have [DataContractAttribute] or [SerializableAttribute] applied to it, and does not implement ISerializable or IXmlSerializable, then usually it will default to serializing all read/writable public members (fields which aren't constant or readonly, and properties with a getter and setter). In this case, you can apply [IgnoreDataMemberAttribute] to public members which should not be saved (ie. excluded from serialization). This is similar to how XmlSerializer works, in serializing all public members which do not have [XmlIgnoreAttribute] applied to them, except that attributes for XmlSerializer are not supported by default for our default saving format, which is based on .NET 3.0 WCF Serialization (eg. via NetDataContractSerializer or DataContractSerializer).
How Do Add/Load/Get Assets from the Asset Database?
Adding/Getting Prototypes Using Code
To create an "instance" (clone or smart copy) of a "prototype" asset item, you should do the following:
This logic will be simplified with some overloads and utility methods soon.
The "old" way of doing this (which will work in some cases, but will soon be removed), is as follows:
//this works for some classes, but not all, and this technique is going to be removed soon.
ParticleSystem prototype;
if(Library.Database.Has(out prototype))
{
ParticleSystem instance = prototype.CreateInstance(); //or if not implemented, you can use Reflector.DeepClone() or Reflector.MemberwiseClone()
instance.TypeInfo = prototype; //set the "prototype" or asset from which this instance was created (and inherits its definition/settings from).
}
Also, in some cases we now use "serialization" instead of (Memberwise/Shallow or Custom/Deep) cloning, however, soon, we will use serialization instead to create instances of a prototype in almost all cases, and will remove or ignore implementation of IInstanced.CreateInstance().
However, this is automatically done, however, for instances created by drag-drop, Add New/Instance context menus, and certain Asset Selector dialogs).
The IEntityComponent.TypeInfo property is automatically set to the AssetInfo (or database entry/metadata which "wraps" the prototype/asset item) for which an object was created (or "instanced") from. This is needed for Prototype Inheritance, so that we can have "smart copies" which automatically update when their prototype (centralized definition) is modified (unless they override those properties with a different value), and this is needed so that we can therefore have very compact (or compressed) saved asset (eg. .v3dx or .v3d) files and serialized networking commands (or messages). These enhancements are currently under development.
The reference to the prototype's AssetInfo is serialized by the EntityComponent.TypeInfoRef (or TypeInfoID) property, which, like other Asset references, is represented by a NameID string.