Object Templates |
Part of your exported data are Object Templates and understanding their relationship with your articy objects, how they work and how to use the different types inside unity is part of this guide.
This topic contains the following sections:
If you have never worked with or need a small brush up about the articy:draft template system, read on otherwise you can skip this section
Every object in articy:draft (Entity, FlowFragment, Location etc.) has a predefined set of hardcoded properties like DisplayName, TechnicalName, ID, Text, Attachments etc.. When designing more complex projects using articy:draft you will sooner or later arrive at a point you wish an articy object had a specific property. Lets say your game needs every NPC to contain a property stating how much gold it is worth when killed, now the obvious articy type would be to use an Entity for the NPCs but how do you create a property for the gold? Introducing model templates:
Following is a list of important parts of the template system, if this doesn't make sense at first, continue reading, we will look at each part in more detail:
Every articy:draft object type can have an object template. You create those object templates in articy:draft using the template editor. It is important to understand that an object template is fixed to one type and one type only. When you create an entity template called "Item" you can only attach this template to entities and nothing else.
A template is usually built up of one or many different features. A feature is created via the feature editor in articy:draft. Because features are not bound to an object type they are a good way to share the same kind of properties between different templated articy object types. A feature itself is a container for properties and can have many properties of varying types. Reusing our example above we could create a feature called LootInfo and place it in our entity template NPC. Later on if we create a template for Chests, we could reuse our LootInfo feature.
On the feature we can now start to plan and create our properties. In the feature editor you are presented with a list of different property types and each type can be placed in the feature grid, creating a new property inside the feature. Every property type has different settings depending on the type and allow us to fine tune and guide how the designers can work or modify the property when used. For example when using the Number property type, we can set the amount of decimal places, a unit, min and max value and so forth. Going back to our example above, in our LootInfo feature we would create a new Number property calling it Gold, adjusting its setting, like min and max and maybe set the Unit to "g" for gold.
Sometimes we have a lot of properties in our features that share the same settings. For example we create a feature for an RPG character with many skill attributes and we have to set the min and max value for every property by hand. To simplify this, you can create property definitions that are reusable presets of properties. For the unity plugin and for the remainder of this guide they are not important.
Lets first have a look of how objects with templates differ from objects without templates, for this example we look at the Entity type:
Here we have 3 classes generated by the plugin from the maniac manfred project. In the image above you can see the class Entity with some of its properties like DisplayName, Text, Color etc. If you export Entities this C# class will get generated by the plugin and all your entities will be instances of this class stored inside the database. This is all done for you by the plugin so you can just access your data likeEntity ent = ArticyDatabase.GetObject<Entity>("Chr_Manfred");
Debug.Log( ent.DisplayName );
Character ent = ArticyDatabase.GetObject<Player_Character>("Chr_Manfred"); // access the displayname because a Character is still an Entity. Debug.Log(ent.DisplayName); // access the template Debug.Log( ent.Template.Character.Motivation );
Important to remember
Note |
---|
This example assumes that you have inheritance enabled in the ruleset data layout, which is the default and the prefered way to work. |
With a basic understanding of how templates are created by the plugin, lets look how we can work with them
Character ent = ArticyDatabase.GetObject<Player_Character>("Chr_Manfred"); // access to the template -> the feature called "Character" and the template property "Motivation" Debug.Log( ent.Template.Character.Motivation );
Accessing a template property is very straight forward if you are used to C# properties in general.
<myObject>.Template.<FeatureTechnicalName>.<PropertyTechnicalName>
We can work the same way with template properties as we can with general properties (DisplayName, Color etc.). We just have to remember that the TechnicalName of the property in articy:draft is the property name in C#.This section contains the following subsections:
The basic types are straight forward mapped to their C# types and thus very easy and intuitive to use.
var manfred = ArticyDatabase.GetObject<Player_Character>("Chr_Manfred"); var locationCell = ArticyDatabase.GetObject<LocationSettings>("Loc_Cell"); Debug.Log( manfred.Template.Character.Age ); // Number (float) manfred.Template.Character.Age = 42; Debug.Log( manfred.Template.Character.Motivation ); // Text (small, medium, large) (string) manfred.Template.Character.Motivation = "Converting oxygen to carbon dioxide."; Debug.Log( locationCell.Template.LocationSettings.IsStartLocation ); // Boolean (bool) locationCell.Template.LocationSettings.IsStartLocation = false;
A reference slot is used to provide a link to another articy object.
var locationCell = ArticyDatabase.GetObject<LocationSettings>("Loc_Cell"); var startDialog = locationCell.Template.LocationSettings.InitialDialog as Dialogue;
It is worth noting that the object is lazy fetched, which means everytime you access the property, the property will internally ask the database to get the object again.
When you need multiple objects referenced you should use a Strip in your template. In unity a strip property is of type List<ArticyObject>.
var manfred = ArticyDatabase.GetObject<Player_Character>("Chr_Manfred"); foreach(ArticyObject obj in manfred.Template.Character.Likes) { var entity = obj as Entity; if(entity != null) Debug.Log(entity.DisplayName); }
Note |
---|
Because the plugin has no support for the query language used in articy:draft for calculated strips they are effectively downgraded to regular strips and they contain the calculated data at the time of export. |
Dropdown lists are a good way to visualize limited data. In unity drop down lists are effectively enums, with the drop-down type being the name of the enum. So using a drop-down in unity
var therapistZone = ArticyDatabase.GetObject<Conditional_Zone>("Zon_4B2E23F9"); therapistZone.Template.ZoneCondition.CursorIfConditionMatches = MouseCursor.Take;
All the scripts inside the flow on pins and in instructions and conditions are called by the ArticyFlowPlayer and we usually don't have to worry about it. But scripts in templates have to be used manually. When exported these properties can be ArticyScriptCondition, ArticyScriptInstruction or a plain string depending on which mode you selected in the template editor in articy
The difference between ArticyScriptCondition and ArticyScriptInstruction is simply that the former returns a boolean and is used to check if something is allowed, this is the same for input pins, while the later is just used to execute code and is similar to output pins.You can do 2 things with both script types in unity.
Using scripts inside your code is therefor just a matter of using the CallScript() methods.
var therapistZone = ArticyDatabase.GetObject<Conditional_Zone>("Zon_4B2E23F9"); // call the Condition property first bool result = therapistZone.Template.ZoneCondition.ClickCondition.CallScript(); // check the returned value, a condition always returns true or false depending on the evaluation of the script if(result) { // if we were allowed to click it, execute the instruction therapistZone.Template.ZoneCondition.OnClickInstruction.CallScript(); }
Just to clarify, if you selected "No error validation" on the script property inside the feature editor.
The property will be imported as a simple string property, not having the RawScript or CallScript() method.In articy:draft templates are bound to a specific type, which means you can't assign a FlowFragment template to a DialogueFragment. But because it is often necessary to have the same set of data on multiple types, articy:draft introduced the concept of Features. Features can be reused in templates and are a good way to attach the same set of data to multiple object types. But how can we write code targeting a specific feature, without the need to know the type of the underlying template.
At this point we have only accessed features where knew the type of the template. But its also possible to ask an arbitrary object if it is a templated object and contains a specific feature. To do that, the plugin will generated specialized interfaces for every feature in the form of
IObjectWithFeature<FeatureTechnicalName>
for us. This is the same concept as the property interfaces like IObjectWithLocalizableDisplayName. Now to use it we can type
ArticyObject obj = ArticyDatabase.GetObject("Chr_Manfred"); // some object var characterFeature = obj as IObjectWithFeatureCharacter; if(characterFeature != null) { characterFeature.GetFeatureCharacter().Motivation = "Converting oxygen to carbon dioxide."; }
<Object>.GetFeature<FeatureTechnicalName>()
<TemplateType>.Constraints.<FeatureTechnicalName>.<PropertyTechnicalName>.<Constraint data>
var manfred = ArticyDatabase.GetObject<Player_Character>("Chr_Manfred"); // use unitys Assert to check if the Motivation properties length is less or equal than what we defined in the constraints for that property Assert.IsEqual( manfred.Template.Character.Motivation.Length <= Character.Constraints.Character.Motivation.MaxLength );