Astra Unity 2.6.6
Astra Unity Plugin
Programmer's Guide

This guide will help you understand the Astra SDK for Unity, walking you through some of the architecture and a few short examples. This is meant for programmers familiar with Unity to learn how to integrate Astra into their own projects. If you're interested in a custom engine or Unreal support please contact jjanz.nosp@m.er@m.nosp@m.aketa.nosp@m.fi.c.nosp@m.om.

For creating your own content please refer to the Creating Content reference.

For assistance in configuration and installation please refer to the Installation Guide.

For an overview of the folder structure see Astra Project Organization.

Note: All C/C++ calls in the Astra Unity SDK are hidden for you so you only need to deal with the high level calls, greatly simplifying what you need to interface with.

Job System

The Astra SDK uses a custom job system to manage tasks. Most tasks in Astra will be asynchronous and return an Astra.Job or a derived class from this. Handling tasks asynchronously is done to avoid blocking on the main thread and to create consistency during operations (processing, networking, etc).

Jobs can run on both main thread and side threads and their events can fire on either as well. There are some explicit events such as Astra.Job.OnJobDoneMain which will ensure callbacks bound for event OnJobDone are run on main thread.

Generally speaking you will receive a job for a task then wait for the result of the job using events or get a coroutine back and yield.

Job Events

Jobs fire events on either main or side threads depending on their primary mainThread flag. There are exceptions such as OnJobDoneSide or OnJobDoneMain which fire based on their suffix. Job events are fired in order after triggering all events at one stage before moving to the next stage. As such Astra.Job.OnJobDone will fire before Astra.Job.OnJobFinally.

Order Event Thread Description
1 Astra.Job.OnJobDoneSide Side Fired after a job is completed regardless of success or failure.
2 Astra.Job.OnJobDoneMain Main Fired after a job is completed regardless of success or failure.
3 Astra.Job.OnJobDone Either Fired after a job is completed regardless of success or failure.
4 Astra.Job.OnJobSuccess Either Fired after a job is completed successfully.
5 Astra.Job.OnJobFailed Either Fired after a job is completed unsuccessfully.
6 Astra.Job.OnJobAborted Either Fired only if a job is aborted.
7 Astra.Job.OnJobFinally Either Fired after done, success, and failures are triggered. Useful to ensure OnJobDoneXYZ callbacks are finished before this one.
8 Astra.Job.OnJobPostFinally Either Used by the job queue.
Astra.Job.OnJobProgress Either Fired intermittently on some jobs when they have progress to report such as long running tasks.

Handling Jobs from Astra API calls

Here are a few examples of how to handle various returned jobs in Astra from the API

Example - Finding Clothing

// Find clothing items affecting the torso region of the male arcade figure and print their information
var maleRigId = "ce582b3b-dabf-42c6-88b7-d9931e2bc933";
var tags = new List<string>(){"UPPER TORSO"};
var searchJob = Astra.Catalog.SearchForClothing(maleRigId,tags);
// Since we don't need the main thread, we can just use OnJobDone instead of OnJobDoneMain
searchJob.OnJobDone += (_) =>
{
// NOTE: the job passed into this callback is the base class of Job, we could also cast it to a Catalog.SearchCatalogJob
// It's a good idea to check for errors, you can also use OnJobSuccess but be aware if you need to have cleanup
if(!_.IsSuccessful())
{
Astra.Logger.LogError("Failed to find clothing");
return;
}
// Jobs that extend from ApiJobWithResult all have a method called GetResult that is useful for getting the payload of the job
var result = searchJob.GetResult();
foreach(var entry in result)
{
Astra.Logger.Log("Item is: " + entry.Guid + " => " + entry.Name);
}
};
Catalog is used to search for assets such as clothing, hair, morphables, figures, avatars,...
Definition: Catalog.cs:24
static SearchCatalogJob SearchForClothing(AvatarItem avatar, List< string > clothingRegions)
Get the list of clothing items available to this environment for the given clothing regions
Definition: Catalog.cs:300
Handles Astra logging messages in C# allowing filtering and redirection
Definition: Logger.cs:15
static void LogError(object message)
A one-to-one with UnityEngine.Debug.LogError, records as Info level
Definition: Logger.cs:115
static void Log(object message)
A one-to-one with UnityEngine.Debug.Log, records as Info level
Definition: Logger.cs:99
Definition: AnimationManager.cs:10

Example - Loading a ClothItem

// Load a clothing item into the scene but don't attach it to an avatar
var clothItemId = "27b3475f-41dd-4b42-bea2-eb33a2f9fb55";
var clothLoadJob = Loader.LoadCloth(clothItemId);
// we don't need to attach any events but we can if we want to wait for something
clothLoadJob.OnJobDoneMain += (_) =>
{
if(!_.IsSuccessful())
{
Astra.Logger.LogError("Failed to load cloth: " + clothItemId);
return;
}
//move the object since we're on main thread we can do this
var result = clothLoadJob.GetResult();
result.gameObject.transform.position = new Vector3(1f,1f,0f);
};

Example - Loading a ClothItem using a Coroutine

using System.Collections;
using UnityEngine;
using Astra;
// This sample assumes you already have astra initialized
public class LoadClothingCoroutine : MonoBehaviour {
void Start () {
StartCoroutine(RunJob());
}
IEnumerator RunJob()
{
// Load a clothing item into the scene but don't attach it to an avatar
var clothItemId = "27b3475f-41dd-4b42-bea2-eb33a2f9fb55";
var clothLoadJob = Loader.LoadCloth(clothItemId);
// Instead of using OnJobDoneMain as a callback, we'll wait for the job to finish through a yield
yield return clothLoadJob.AsCoroutine();
if(!clothLoadJob.IsSuccessful())
{
Astra.Logger.LogError("Failed to load cloth: " + clothItemId);
yield return null;
}
//move the object since we're on main thread we can do this
var result = clothLoadJob.GetResult();
result.gameObject.transform.position = new Vector3(1f,1f,0f);
yield return null;
}
}
Definition: LoadClothingCoroutine.cs:6

Job Queue

Jobs are generally created, then pushed into the main queue for running at a later time. They can also be run inline by firing the Astra.Job.Run method which will run the job immediately and not push it into the queue. To push a job into the queue, which is the recommended way of running a job, simply use Astra.MainQueue.Push.

Example - Custom Job Example

You can create your own jobs quite simply.

// Creates an empty job
var job = new Astra.Job();
// For debugging purposes naming a job is useful
job.name = "Test Job";
// By default jobs run on side threads, if you need to run on the main thread
// such as if you plan to access GameObjects you can do so by setting
//job.mainThread = true;
// Bind an anonymous function that is executed when the job is run
job.function = (_) =>
{
// A copy of the job is passed in when running as the first argument
// this is especially useful if you have a named function instead
UnityEngine.Debug.Log("Job: " + _.name + " is running");
// We can auto complete our job by returning true or false which
// mark it as done with success or failure respectively.
// If we return a null it means the job will be completed externally
// and it will remain running.
// Complete the job as successful
return true;
};
// This function will fire after the job is run
job.OnJobDone += (_) =>
{
UnityEngine.Debug.Log("Job: " + _.name + " is complete, was successful: " + _.IsSuccessful());
};
// Inserts the job into the main queue which will run if astra is initialized and AstraManagerGO is in the scene
// The job has a chance of running immediately during the Push in certain circumstances but it may also run at a later time
int Push(Job job, bool runImmediatelyIfPossible=false)
Place a new job into the appropriate queue, returning the id of the job enqueued
Definition: JobQueue.cs:370
A job is a unit of work that you need done you can provide data to it, talk to it,...
Definition: Job.cs:44
string name
Name of the job, which makes it easier to debug. Optional.
Definition: Job.cs:382
A wrapper around the primary Astra system primary JobQueue
Definition: AstraManager.cs:720
static JobQueue Instance
Retrieves the main JobQueue.
Definition: AstraManager.cs:748

Jobs can depend on the successful completion of other jobs, this is controlled through Astra.Job.DependsOn. In addition there are other helper methods such as Astra.Job.CompleteAfter which will trigger the caller job to auto complete when the callee job is completed. For additional information about the Job system in general check out the Astra.Job class.

Assets Overview

An asset is a low level building block that has a public GUID associated with, which we use to build up things that our Avatars can consume. Assets can be things such as a Mesh, Texture, Rig, Eye, Mouth, Decal, Morphable, or any other basic building block. Assets can also depend on other assets. We use this as a way to build up complex structures from simple pieces. An example of this is our Schematic which in turn can load or depend on things such as Material, Texture, Mesh, or other simple structures. A Schematic in turn is used and extended by high level concepts such as Cloth, Hair, Figure, and others.

Every main asset has a GUID and most sub type also have a GUIDs. Assets, internally, are referenced via GUIDs and you should refer to them via GUIDs as well and not by names.

Assets are almost always loaded onto a new or existing Astra.Asset.AvatarItem.

How Astra Assets Relate to Unity

There are several atomic elements such as textures and meshes along with more complicated elements such as avatars in Astra. Below is a table that shows a loose relationship between Astra's systems and Unity's.

Element Unity Primitive Astra Primitive Astra Component
Texture Texture2D PrimitiveTexture
Mesh Mesh PrimitiveMesh Astra.Asset.MeshItem
Material Material PrimitiveMaterial Astra.Asset.MaterialItem
Rig PrimitiveRig Astra.Asset.RigItem
Avatar PrimitiveAvatar Astra.Asset.AvatarItem
Cloth SkinnedMeshRenderer PrimitiveSchematic Astra.Asset.ClothItem
Hair SkinnedMeshRenderer PrimitiveSchematic Astra.Asset.HairItem
Part SkinnedMeshRenderer PrimitiveSchematic Astra.Asset.PartItem
Figure SkinnedMeshRenderer PrimitiveSchematic Astra.Asset.FigureItem
Decal PrimitiveDecal Astra.Asset.DecalItem
Material Variation Material PrimitiveMaterialVariation Astra.Asset.MaterialVariationItem
Collections PrimitiveCollection Astra.Asset.CollectionItem

Asset Item Types

As seen from the above list Astra exposes most components with the suffix of Item when these are attached to GameObjects. Here is a list of components you will see when using Astra along with a brief description of their purpose.

Item Description
Astra.Asset.AvatarItem The container object that houses the recipe for the character and it's main driver of methods
Astra.Asset.BoneItem Helper component that aids in mapping our bones to the RigItem
Astra.Asset.ClothItem Clothing objects typically attached to an avatar
Astra.Asset.CollectionItem Groups other assets like cloth, hair, decals into a suite loadable all at once as a Collection
Astra.Asset.DecalItem Modifiers to the mesh (note: can be attached to non figure items)
Astra.Asset.EyeItem Used specifically for the container of the eyes
Astra.Asset.FigureItem The overall body of the character
Astra.Asset.HairItem Hair objects typically attached to an avatar
Astra.Asset.MaterialItem Provides additional meta information about materials and links to a Unity Material as well
Astra.Asset.MorphableItem Modifies the mesh and or bones of the avatar
Astra.Asset.PartItem Generic type that can contain other generic types (this is used commonly to deal with the mouth)
Astra.Asset.PoseItem Used to set the character in specific fixed poses, all base figures will have at least one of these as a T-Pose if using animations
Astra.Asset.RigItem The skeletal system of the figure and is used for other sub assets such as clothing

Querying Assets

Finding assets is done through the Astra.Catalog. The first use of the Catalog will trigger a Astra.Catalog.Refresh call which sends a request to the server and determines which assets are available for the current application configuration being used. If you add new assets on the admin portal and the application needs to see those assets without restarting you should trigger Astra.Catalog.Refresh periodically (such as in a long running application or game).

Assets will appear in the catalog once they are bound to a application via the Asset Category relationship. Looking at the sample whitelabel application is a good way to determine how this process works.

To search the catalog you can use the various SearchXYZ method calls from Astra.Catalog such as Astra.Catalog.SearchForAvatars or Astra.Catalog.SearchForClothing.

Results of these calls will yield a job that upon calling GetResult will typically be a list of Astra.CatalogEntry records.

If you already know the asset GUID or once you have found the asset in question you can load it using the Astra.Loader class.

Asset Filtering

Typically you will filter assets so only compatible assets and potentially specific types of assets (such as shirts but not pants) are returned from the query.

Here is a list of how assets types are filtered for compatibility matching

Type Mesh Rig Notes
Cloth X
Hair X
Decal X
Part X
Pose X
Material Variation X
Morphables X X MeshTargets use mesh guids, RigTargets use rig guids
Collection X X Typically collections are filtered by rigs though

When filtering with a Rig this will come from the Astra.Asset.RigItem.AstraGuid, you can locate this for a loaded avatar via:

// Assumes avatarItem is of type Astra.Asset.AvatarItem
avatarItem.BodyManager.GetRigItem().AstraGuid;

In most cases when using a mesh filter, like in decals, this will be the Astra.Asset.MeshItem.AstraGuid of the body mesh.

// Assumes avatarItem is of type Astra.Asset.AvatarItem
avatarItem.BodyManager.BaseFigure.Meshes.GetItemAtIndex<MeshItem>(0);

Thankfully the Astra.Catalog takes care of this for you if you pass in your Astra.Asset.AvatarItem into the various search calls. You are encouraged to use these overloaded calls over freeform as it simplifies filtering for you.

To filter by regions such as finding clothing that fits on the torso you will need to specify a list of strings containing these regions as tags.

// Assumes avatarItem is of type Astra.Asset.AvatarItem
var tags = new List<string>(){"UPPER TORSO"};
var searchJob = Astra.Catalog.SearchForClothing(avatarItem,tags);

The following regions are used when creating attachable assets to avatars for cloth and hair.

  • "HEAD"
  • "FACE"
  • "NECK"
  • "LEFT SHOULDER"
  • "LEFT UPPER ARM"
  • "LEFT ELBOW"
  • "LEFT UPPER FOREARM"
  • "LEFT LOWER FOREARM"
  • "LEFT HAND"
  • "RIGHT SHOULDER"
  • "RIGHT UPPER ARM"
  • "RIGHT ELBOW"
  • "RIGHT UPPER FOREARM"
  • "RIGHT LOWER FOREARM"
  • "RIGHT HAND"
  • "UPPER TORSO"
  • "LOWER TORSO"
  • "HIGH WAIST"
  • "LOW WAIST"
  • "PELVIS"
  • "LEFT UPPER THIGH"
  • "LEFT LOWER THIGH"
  • "LEFT KNEE"
  • "LEFT UPPER CALF"
  • "LEFT LOWER CALF"
  • "LEFT FOOT"
  • "RIGHT UPPER THIGH"
  • "RIGHT LOWER THIGH"
  • "RIGHT KNEE"
  • "RIGHT UPPER CALF"
  • "RIGHT LOWER CALF"
  • "RIGHT FOOT"
  • "EYEBROWS"

In addition when creating your own content you can provide custom tags as well and these can be used to filter the same as regions.

Tags are paired using AND boolean logic, so if you provide a list of three tags the content that is in the result will match ALL three tags.

Loading Assets

In most cases assets will be loaded onto an existing avatar. This lets you dress and modify an avatar for your users, or let your users modify them directly as well. You can create a new GameObject and attach the Astra.Asset.AvatarItem component if you wish to make one from scratch. You will then need to load an Astra.Asset.FigureItem to get a basic nude or underwear wearing avatar.

When loading assets onto an avatar most assets, such as clothing, will automatically handle removing assets that are in conflict (such as replacing a pair of pants with a pair of shorts). This greatly simplifies needing to know when and how to remove or hide assets when adding new ones.

Assets are loaded using the Astra.Loader class with various LoadXYZ methods such as Astra.Loader.LoadDecal.

Most load calls accept a parameter that wraps all options for loading, of which you will typically embed an avatar item.

// Assumes avatarItem is of type Astra.Asset.AvatarItem
var options = new Asset.ClothLoadJob.ClothLoadOptions()
{
// A basic shirt for the male arcade figure
guid = "27b3475f-41dd-4b42-bea2-eb33a2f9fb55",
// We want to load this cloth item onto this avatar
avatarItem = avatarItem,
};
// Fire the load event and assume it succeeds
var clothLoadJob = Loader.LoadCloth(options);

Avatars

Avatars are the primary building block component that house other sub types such as figures, clothing, hair, decals, morphables, and others. In the SDK these are represented in your scene as Astra.Asset.AvatarItem. When avatars are saved they create a recipe that tells you how to load a complete representation of them at a later point. This allows you to create and save avatars and load them elsewhere (on different devices, different accounts, different applications, etc) and recreate the same avatar.

There are both App Avatars and User Avatars. Where App Avatars are controlled by you, are read-only, and useful for "default characters". User Avatars are what your customers will create and use to modify their own avatars.

Below is an example of an avatar using our Arcade figure with Arcade clothing:

Astra Avatar

Querying and Loading

Finding All Avatars

// Get all avatars available to the user and print information about them
var job = Catalog.GetAvatars(); // We can also use Catalog.SearchForAvatars as well
job.OnJobDone += (_) =>
{
var result = job.GetResult();
foreach(var entry in result)
{
Astra.Logger.Log("Avatar found: " + entry.Name + " => " + entry.Guid + " is app: " + entry.IsAppAvatar);
}
};

Loading by GUID

var job = Loader.LoadAvatar("The-guid-to-assemble-here");

After loading you will have an avatar that may look something like this:

AvatarItem

Astra.Asset.AvatarItem is the main component for avatars; there are many methods inside for handling actions like syncing, serialization, etc. Below is a list of some common ones you might need while developing your game or application.

  1. Astra.Asset.AvatarItem.ApplyAsset - Loads a catalog result item onto the avatar and handles removing old assets
  1. Astra.Asset.AvatarItem.RemoveAllItems - Removes all items on the avatar
  1. Astra.Asset.AvatarItem.Thumbnail - Retrieves the 2D texture preview for this avatar (if present)
  1. Astra.Asset.BodyManager - Manages things like rigs and heights of the avatar
  1. Astra.Asset.AnimationManager - Syncs avatar rigs with Unity's animation retargetting system
  1. Astra.Asset.CompoundManager - Handles systems related to components like cloth and hair
  1. Astra.Asset.MorphableManager - Handles morphables
  1. Astra.Asset.DecalManager - Manages the decal system for this avatar
  1. Astra.Asset.MaterialManager - Manages material variations
  1. Astra.Asset.AlphaMaskManager - Handles the pokethrough system for the avatar
  1. Astra.Asset.MorphableManager.SetMorph - Drives a morph to a specified value on the avatar and projects for all sub assets
  1. Astra.Asset.MorphableManager.RemoveMorph - Removes a specific morph off the avatar by guid
  1. Astra.Asset.BodyManager.Height - Ensures the avatar stays in a specific height (meters)
  1. Astra.Asset.BodyManager.GetRigItem - Retrieves the RigItem component off the avatar (if present)
  1. Astra.Asset.BodyManager.BaseFigure - Retrieves the FigureItem component off the avatar (if present)

Animation

One of the biggest features of the Astra system is dynamically, at runtime, support for updating the mecanim system. The easiest way to use this is to trip the Astra.Asset.AnimationManager.GenerateHumanAvatar from the AvatarItem you want to use. This takes care of creating a new Unity Avatar representation along with updating proportions and muscle restrictions.

This is automatically done for you if using morphables which move bones, you do not need to do this yourself.

//Astra avatars are procedural so we need a human definition built, this method handles that for you
Avatar.AnimationManager.GenerateHumanAvatar((bool success) => {
if(!success)
{
Astra.Logger.LogError("Failed to configure a humanoid");
return;
}
//our function will create the Animator component but it doesn't know which runtime aniimation controller to use, so we'll specify that here
var animator = Avatar.GetComponent<Animator>();
});

You can find an example at Animating an Avatar. Or in your project folder at Assets/Astra/Examples/Animation/AnimatingAnAvatar.cs.

Saving an Avatar

You can save an avatar through the Unity Editor via clicking on an AvatarItem component and clicking on the Save Avatar button. This will in turn call the following code:

var job = avatarItem.SaveAvatar();
job.OnJobDone += (_) =>
{
// your avatar is now saved, you can confirm by checking it's success state of the job
// you can load this avatar at any time in the future by using the guid at avatarItem.AstraGuid
};

Figures

Figures are the basic body of an avatar, they can be loaded standalone via FigureLoader.Load or via the main avatar loading. They typically contain at least a Astra.Asset.FigureItem, one or more Astra.Asset.MeshItem, Astra.Asset.EyeItem, and Astra.Asset.RigItem. The Astra.Asset.FigureItem is a component that is responsible for the overall skin of the figure and ultimately is a primary pivot area that is frequently queried by the developer and Astra.Asset.AvatarItem as a way to get access to the body mesh or the rig for further calculations.

Figures contain all the essential parts of the nude character (bones, eyes, mouth, skin) and as such are also visual skin of the figure (through various materials and mesh items, eyes, and mouth), if you are swapping a character from say an android skin to a human skin you would do so via the FigureItem.

Astra Figure

Loading

Unity C# example

var job = Loader.LoadFigure("The-guid-to-assemble-here");
job.OnJobSuccess += (_) => {
//your figure is ready now
//NOTE: your figure is not yet inside an AvatarItem so won't be fully activated
};

Swapping

If you want to change out the existing skin of an avatar with a new FigureItem you can do so via

Unity C# example

//swap the current figure item with a new figure item that you already have a reference to
avatarItem.BodyManager.BaseFigure.Swap(newFigureItem,(success)=>{
//Your avatar now has it's main figure replaced with the new figure, no components need to be reconfigured
});
//or swap the current figure item with a new figure item that you only have a GUID to
avatarItem.BodyManager.BaseFigure.Swap("Your-figure-guid-here",(success)=>{
//Your avatar now has it's main figure replaced with the new figure, no components need to be reconfigured
});

Rigs

Rigs are a crucial component of any avatar represented in Unity as Astra.Asset.RigItem. They are essentially the hierarchy of the character's bone system. In addition to providing the bone data for an avatar they also handle much of the Morphable syncing requirements such as updating animation retargeting data, bind pose manipulation, and donating their bone data to child nodes such as Hair or Cloth items.

Typically rigs are not handled directly by the developer and instead the Figure will handle loading instead.

NOTE: when loading assets for an avatar, only one rig is used even though dependent assets such as Cloth will have their own rig.

An example of the Arcade Rig:

Astra Rig

Loading

Unity C# example

var job = Loader.LoadRig("The-guid-to-assemble-here");
job.OnJobSuccess += (_) => {
//your rig is ready now
};

Syncing

If you are doing advanced manipulation of your avatar you may find it helpful to trigger the Astra.Asset.RigItem.Sync method which will take care of moving the bones to their desired targets, adjusting the mesh to fit through bind pose manipulation, and regenerating a new Unity Avatar definition (used for animations). Typically this is done for you automatically and you won't need to worry about it.

var rigItem = myAvatarItem.BodyManager.GetRigItem();
var job = rigItem.Sync();
job.OnJobSuccess += (_) => {
//Everything is now updated
};

Cloth

Cloth is how you dress your avatar and is represented in Unity as Astra.Asset.ClothItem. The system for attachment to an avatar typically takes care of automatic swapping (optional). These are handled by the Layering and Eviction system along with which regions the Cloth exists in.

An example of Cloth:

Astra Cloth

Cloth will include a copy of the rig so as to be spawnable outside of an avatar and to link the weights between the desired avatar (if any) and the cloth itself.

Cloth physics is not yet implemented but is a planned feature for 2019.

Loading

//In most cases we want to automatically place this cloth on an existing avatar..
job.OnJobSuccess += (_) => {
var clothOptions = new ClothLoadJob.ClothLoadOptions()
{
guid = "The-guid-to-assemble-here",
avatarItem = avatar //existing avatar
};
var job = Loader.LoadCloth(clothOptions);
job.OnJobSuccess += (_) => {
//our cloth is ready, attached, replaced the previous region's cloth (if any), weighted, etc...
};
};

Decals

Decals, Astra.Asset.DecalItem, allow easy layering of textures on top of the normal mesh. There are two types of decals, static and dynamic, and they can have their compatibilities marked by an optional Mesh GUID.

Decals support preserving order layers and strength of application. They can blend Albedo, Metal, and/or Normal maps.

Static Decals

Static decals are UV based textures that are marked specifically for specific meshes in preconfigured locations. These are typically used for applications as fixed makeup, scars, blemishes, age, wear, dirt or other such features.

An avatar without (left) and with (right) a static decal:

Arcdae Skull Decal

Eyes

Eyes, Astra.Asset.EyeItem, are simple elements that create containers for loading the eyes in the Avatar. Eyes can be either simple pre-designed fixed eyes or contain procedural elements for controlling the pupil, iris, or other elements. Currently eye colors and sizes are modifiable and supported across engines.

Eyes can be modeled as simple orbs, half orbs, or anatomically shaped. They can either use basic shaders, such as on mobile targets, or advanced shaders with parallax effects or photorealistic rendering such as in the Unreal engine.

Example of the default eyes for Arcade:

Arcade Eyes

Loading

Eyes are not typically loaded directly by the developer and instead come pre-packaged with a figure, but if you wanted to swap one out you can, such as the below example:

Unity C# example

//In most cases we want to automatically place eyes on an existing avatar...
var eyeOptions = new EyeLoadJob.EyeLoadOptions()
{
guid = "The-guid-to-assemble-here",
rigItem = avatar.BodyManager.GetRigItem()
};
var job = Loader.LoadEyes(eyeOptions);
job.OnJobSuccess += (_) => {
//our eyes are ready
};

Item

The EyeItem itself has helpers to expose the left and right eye via: EyeItem.LeftMesh and EyeItem.RightMesh which point to their respective MeshItem elements. It's also important to note that the EyeItem component itself is the parent component that references both sub-elements for the eyes which are simpler MeshItem elements.

Hair

Hair, Astra.Asset.HairItem, is used for adding hair to an avatar's body. It can be used for both hair on the top of the head and for facial hair. It is important to note that when processing hair assets you mark them as Hair instead of Cloth so that they can take advantage of upcoming features for hair.

An example of a Hair item compatible with the Arcade figure:

Astra Hair

Currently work is underway for hair based physics both soft body and bone based and will be available sometime in 2019.

Loading

Unity C# example

//In most cases we want to automatically place this hair on an existing avatar...
var hairOptions = new HairLoadJob.HairLoadOptions()
{
guid = "The-guid-to-assemble-here",
avatarItem = avatar
};
var job = Loader.LoadHair(hairOptions);
job.OnJobSuccess += (_) => {
//our hair is ready, attached, replaced the previous hair
};

Meshes

Meshes in Astra contain all the geometry and data necessary to recreate a skinned or unskinned mesh in Unity, Unreal, or any other game engine. They include the vertices, normals, tangents, triangles, uvs, skin weights, and any other supporting data set you would expect a mesh to have. They do not include the Astra.Asset.RigItem however as these are simpler lower level building blocks. Meshes also contain information about their submeshes and how to map between them.

Loading

Meshes are rarely loaded by themselves outside of development purposes, nevertheless you still can manually load them.

Unity C# example

var job = Loader.LoadMesh("The-guid-to-assemble-here");
job.OnJobSuccess += (_) => {
//our mesh is ready
};

Runtime

The Astra.Asset.MeshItem component in Unity exposes a few useful helper parameters and methods that you will have access to.

  1. Astra.Asset.MeshItem.SyncDecals - You can manually trigger this if you've done custom decal modifications and need the layering system to recalculate the decal stack.
  2. Astra.Asset.MeshItem.RecalculateBounds and Astra.Asset.MeshItem.RecalculateBoundsNextFrame - Useful to recalculate the bounding cube volume used in various systems in Unity if you are directly manipulating the mesh yourself.

Pose

Poses, Astra.Asset.PoseItem, are used to force a rig into a specific orientation. Poses can set positions and rotations but not scale. They also have the following types:

  1. PoseUnknown - An error state
  2. PoseT - A rigid T-Pose used specifically for processing, rebinding, and retargeting of animations
  3. PoseRelaxed - Typically this is the rest pose or post rotation pose
  4. PoseFreeform - A generic pose type for custom orientations
  5. PoseUnreal - A slightly relaxed A-Pose used by the UE4 mannequin

You may find the Astra.Asset.PoseItem.HoldPose and Astra.Asset.PoseItem.ReleasePose useful.

An example of an avatar with no specified pose (left) and the posed character (right) in a T-Pose. Astra Pose