Note
Please note that type constraints are only a visual filter, meant to guide the user inside Unity and doesn't change how the ArticyRef works internally. It is still possible to assign an articy object of any type via script.
Here we show you how you can set references to articy objects in your custom unity scripts to modify them in the Unity inspector and how to access them inside your C# scripts.
This topic contains the following sections:
Rather than hardcoding the Technical Name of your Articy objects into your scripts, you can keep your code generic and reusable by working with references instead. You can set references to Articy objects in the Unity Inspector just like any other public variable:
Create a new C# script file called MyArticyScript and paste the following code
using UnityEngine;
using System.Collections;
using Articy.Unity;
public class MyArticyScript : MonoBehaviour
{
public ArticyRef myRef;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
Saving the file and going back to unity will show the exposed variable in the Inspector:

Now you can select your object directly from the articy database by clicking the browse button on the right side of the textbox and using the object picker to select the reference


Let's see how we can access the referenced object now. The following code will verify that the reference is valid - and then print out its Technical Name to the console:
using UnityEngine;
using System.Collections;
using Articy.Unity;
public class MyArticyScript : MonoBehaviour
{
public ArticyRef myRef;
// Use this for initialization
void Start ()
{
if(myRef.HasReference)
{
var obj = myRef.GetObject();
Debug.Log(obj.TechnicalName);
}
}
// Update is called once per frame
void Update () {
}
}if(myRef.HasReference)
{
var obj = myRef.GetObject<Player_Character>();
Debug.Log(obj.DisplayName); // now we have access to character properties because we specified the more specific type
}By default, ArticyRef accepts all types of articy objects. This can lead to user error. The code might for example be expecting an object of type Character, but nobody is stopping us from setting a FlowFragment in our ArticyRef in the Inspector. We could run into a potential NullReferenceException when our script runs. To remove this potential trap, we can limit what the object picker for our ArticyRef will display. This is called a Type constraint
The code below demonstrates how to limit the objects that can be assigned to our exposed variable to objects of the type Character.
[ArticyTypeConstraint(typeof(Character))]
public ArticyRef playerProtagonist;
There is an important difference in using an object interface, like typeof(IEntity), and a base type, like typeof(Entity)
You can combine as many type constraints as you want. But remember, to have a specific object shown in the picker at least one of the constraints must match
[ArticyTypeConstraint(typeof(Character), typeof(Item))]
public ArticyRef requiredPossession;Utilizing object and property interfaces, we can ask for very specific types
[ArticyTypeConstraint(typeof(IEntity))]
public ArticyRef allEntities; // only entities, with or without templates
[ArticyTypeConstraint(typeof(Entity))]
public ArticyRef onlyEntities; // only entities, without a template
[ArticyTypeConstraint(typeof(IObjectWithLocalizableDisplayName))]
public ArticyRef anythingWithDisplayName; // no matter what, as long as it has the property DisplayName
[ArticyTypeConstraint(typeof(IObjectWithFeatureSoundfile))]
public ArticyRef anyTemplatedObjectWithFeatureSoundFile; // could be any object with a template, as long as it has the feature "SoundFile".If you want you can use lists or arrays of articy refs
public List<ArticyRef> list; // You can use lists of articyRefs if you want
public ArticyRef[] array;And use a single type constraint for every element
[ArticyTypeConstraint(typeof(Character))]
public List<ArticyRef> selectableCharacters; // And you can constraint themIn addition to the type constraints, you can write your own filters. However, these are often advanced use cases and require some experience with the plugin to implement them on your own.
[ArticyCustomFilter(nameof(IsCharacterOfFamilySmith))]
public ArticyRef characterRef;
bool IsCharacterOfFamilySmith(ArticyObject articyObject, object[] args)
{
if (articyObject is Entity entity)
return entity.DisplayName.Value.EndsWith("Smith"); // show only entities which last name is "Smith"
return false;
}You can use parameters:
[ArticyCustomFilter(nameof(IsLastName), "Smith")]
public ArticyRef characterRef;
bool IsLastName(ArticyObject articyObject, object[] args)
{
if (articyObject is Entity entity)
return entity.DisplayName.Value.EndsWith((string)args[0]); // use the argument to test the last name
return false;
}And you can also reference static methods from other classes:
public class Player : MonoBehaviour
{
// show only weapons that are in the user folder "Swords"
[ArticyCustomFilter(typeof(MyArticyRefFilter), nameof(MyArticyRefFilter.EntityUserFolder), "Swords")]
public ArticyRef weapon;
}
public static class MyArticyRefFilter
{
public static bool EntityUserFolder(ArticyObject articyObject, object[] args)
{
if (articyObject is not Entity)
return false;
UserFolder folder = articyObject.Parent as UserFolder;
return folder != null && folder.DisplayName == (string)args[0];
}
}