Our Unity Tutorial on Augmented Reality Game Development with Vuforia SDK

Unity AR Tutorial: Augmented Reality Game Development with Vuforia

 

Vuforia is an AR platform that provides amazing opportunities for augmented reality development. Here are some examples:

Vuforia also has a Unity SDK and in the second part of this tutorial  I’ll explain how to integrate and develop it. But let’s start with the Vuforia integration…

Obtaining a Vuforia license

add_license_keyThe first thing you have to do is  register on Vuforia page. After you complete the registration process, you can start developing with Vuforia SDK. You will then need a license for your project.

Head over to the Development tab, and click on the “Add license” button. A little form will show up. Fill in the form as shown on the side and click “Next”.

Then you have to confirm your license key by agreeing with terms and conditions and by clicking “Confirm”. Pretty simple so far, right?

Vuforia’s Unity SDK

It’s time to download the Vuforia SDK for Unity. You can download it in the Vuforia Downloads tab.

unity_sdk

After downloading the package, import it into the existing project inside of Unity.

Prepare the markers

Now it’s time to prepare the markers. Markers are the images that Vuforia will use as the points of reference to display your objects. The more distinct key points the image has, the more accurate or “augmentable” your markers will be. The easiest way to create such  marker is to generate a QR code. QR codes have a lot of key points and they work like a charm. You can generate them yourself or, to make it quicker, you can download mine 🙂

create-databaseOnce you’ve got the marker, it’s time to upload it to Vuforia. Go to the Vuforia Target Manager page and click on the “Add new database” button. Type the preferred name for your database and choose the “Device” as a Type option.

 

Great! Now, select the name of the database you’ve just created and then click on the “Add the new target” to the database.

add-target

Select the Single Image type, pick the marker you’ve downloaded before, set the width to 1, name it the way you want it and click “Add”.

There are other types of targets, for example Cuboid, Cylinder or a 3D object. These can work as 3D markers (you can make them if you feel like it), but preparing them would take a lot more time, because you’d have to create and upload every side of that cuboid to Vuforia and that’s a chore…

Alright, so now you can see your target has been added to the list and it’s ready to be downloaded. Click “Download Database” and import the package to Unity.

Preparing the scene

Setting up the scene is also very easy. Get rid of the existing camera on the scene. Vuforia has its own camera that your scene will use. Drag and drop ARCamera prefab from Vuforia > Prefabs folder into the scene. Your scene hierarchy should look like this:

unity-scene-image

Now, let’s setup the ARCamera properties. ARCamera prefab requires the license key which you can find on the Vuforia License Manager Page.

AR license key

Copy and paste your License key to Vuforia Behaviour Script field of the ARCamera prefab on the scene.

unity-scene-with-script-image

Select ARCamera in your hierarchy, and in the Database Load Behaviour tick the “Load [name] database” checkmark, then “Activate”.

database-load-behaviour

Setting up the markers

Alright, now it’s time to add the markers on the scene! You can do it by dragging ImageTarget prefab from Vuforia > Prefabs to your scene.

Your ImageTarget needs to be set to a specific marker image. It has a script called “Image Target Behaviour”, where you can do that by choosing your database name in the “Database” field and then select the “ImageTarget” from the drop down list. It should look like this:

image-target

Great, you’re almost done! Now it’s time to add some objects to the display. Right click on the ImageTarget in the hierarchy, 3DObject > Cube. Resize the cube the way you want it and the project is ready to be compiled! Alternatively, you can add any 3D object to the hierarchy of the ImageTarget.

As you can see, Vuforia SDK is very easy to setup and it has a lot of nice features you can utilize to make awesome games or apps. For example, you can combine a couple of those markers to make something a bit more complicated like this:

Procuring Graphical Assets

You will need some 3D models. I’d suggest that you download and import these amazing drone models by Popup Asylum.

Next, we’ll need a QR code as an additional marker. You can generate your own, but feel free to use mine if you’re lazy 🙂 Also don’t forget to upload it to the Vuforia Target Manager page and download the updated database after that.

For the testing purposes you’ll need these two markers printed, so I’ve also prepared a pdf for you to download.

A few more textures for you to import: drone_shadow, white_ring.

Scene setup

Drag and drop 2 ImageTarget prefabs from Vuforia > Prefabs to the scene. Name the first one as “DroneTarget” and the second one as “GoalTarget”. After that assign the corresponding “Image Target” to each one of them in the Image Target Behaviour Script. In the same script, change the width of the DroneTarget to 3 and GoalTarget to 2. It should look like this for the DroneTarget:

dronetarget

And like this for the GoalTarget:

goaltarget

Now in the ARCamera object in our hierarchy, head over to the Vuforia Behaviour Script and change the value of “Max Simultaneous Tracked Images / Objects” to 2. Then in the “World Center Mode” section select “SPECIFIC_TARGET” from the drop down list and in the section “World Center” choose the DroneTarget from the hierarchy. It should look like this:

ar-camera

Connecting Models to Markers

We’ve got the markers, let’s add the 3D models they will represent…

Right click on the DroneTarget and select “EmptyObject”. Make sure this new object has a position of [0;0.5;0] and scale of [0.33;0.33;0.33]. I’ve also changed the name of it to “Drone”. Then, add a 3D model of any drone as a child to this object and change the position of it to [0;0;0] and scale to [0.33;0.33;0.33]. Now the hierarchy looks like this:

drone-model-setup

So, let’s add a model for our GoalTarget. Add an empty object same way we did for the DroneTarget and change its name to “Ring”. Then add a Sprite Renderer to that object and in the “Sprite” section, choose our ring sprite. After that you can change its color to whatever you’d like. You also might want to resize it, change the position to make to fit the QR marker. It kind of looks like this for me:

all-model-setup

Nav Mesh setup

Alright, so we’ve got the scene, let’s now get to the main functionality… Pathfinding. So we need to bake a Nav Mesh. For more info, please, go to Unity navigation tutorial page.

Baking a Nav Mesh requires a presence of a regular mesh on the scene to walk on first. Right click on the hierarchy 3D Object > Plane. Rescale the plane so it covers an area around the markers where you potentially would like your drone to move. Now open up the navigation window (Window > Navigation) and in the Object tab make sure your plane is selected along with a “Navigation Static” checkbox. After that click “Bake”. Fantastic! If your scene looks somewhat like this, you’re on the right track!

navmesh-with-plane

So what do we do with that annoying white plane obstructing the view? Well, it’s time for us to get rid of it. Yeah, just delete it, we won’t need it anymore, since the Nav Mesh is already baked.

Once we’ve got our Nav Mesh, it’s time to setup a Nav Mesh Agent, an actor that would travel using the Nav Mesh. The Nav Mesh Agent functionality should obviously be applied to the drone, so select the first child in the “DroneTarget” hierarchy…

select-the-drone

… and add NavMesh Component to the inspector. You’ll see a whole bunch of parameters for this component. I’m not going to explain what each and every one of this parameters means since that’s not the point of the tutorial. (If you’re interested in the commentary over the parameters, please watch this video and here’s Unity docs). Here’s a screenshot of my Nav Mesh Agent parameters for the drone:

nav-mesh-agent

Coding time

The initial scene setup is ready and it’s time to write some code for it to work… Create a script in one of your folders and add it to the “Drone” object (DroneTarget first child).

The whole moving mechanic is pretty simple. We’d need two variables variables:

A function to track a position of the second marker and move the drone towards it:

That’s it. Just execute this function in the update and don’t forget to select the “Ring” (GoalObject child) object as a public variable in the inspector.

movement-script

You can now build the project onto your phone and check whether it works with the markers.

NOTE: The DroneMarker should always be in the camera view for the whole app to work since we’ve declared it as the world center and the whole drone logic is attached to it.

Drone leaning

You might also want your drone movement look more realistic, so let’s add movement leaning. The done will lean forward depending on its current speed.

MapRange function

There’s a great function I use pretty often called MapRange. It converts numbers within a range to numbers within another range depending on the current value.

A simple example of this function working is… let’s say we want to change the color of the ball depending on player’s distance from it. s would be our current distance from the ball. a1 – minimum observed distance, a2 – maximum observed distance. So we want the ball to be blue if the distance is more than 3 meters and red if player is 1 meter away or less. everything in between would be automatically purple -ish. So the implementation with MapRange would look like this:

playercolorball

Back to the drone leaning…

so in case of movement leaning, exploiting MapRange() would be this simple:

Add PitchCtrl() to the update function and you’re good. The drone will lean forward while moving.

Shadow

Let’s add a shadow to the drone. A simple static shadow. That’s a piece of cake since we just have to add a sprite to the existing hierarchy. Make sure your shadow object is the second child of “Drone”. Just like that:

first-shadow

Line renderer

In order to setup a line renderer we should add a sprite, but don’t worry, there’s no need to import one, just head over to your project window and open the folder where you store your sprites. Hit Right click > Create > Sprites > Square. You’ve got your new sprite which we’ll use for the new material that we’re about to create.

Right click > Create > Material. Material’s shader should be changed to Particles > VertexLit Blend and Particle Texture to the earlier created Square sprite. Sounds hectic, but just look at this picture and you’ll get it:

laser-material

Create a new script. Let’s say the name of this script is Goal. Attach the Goal script to our Ring object.

ring-line-renderer

Also attach line renderer component to the “Ring”. Line renderer would require a material, so please add the material we just created to it.

line-renderer

So, it’s time to write the code, which is also very simple. Here the whole Goal script code and it’s pretty much self-explanatory:

If you run the app now, you’ll see the ring’s line/laser pointing to the drone destination. It’s great but we can also make this destination look a little bit more clear by adding another object… Just a game object containing a Sprite Renderer and Animation components.

destination play

Create a public variable destSprite and update MoveToTarget() function.

That’s it, run your project on a smartphone and you’ll have the same result as in this video:

Thanks for reading and don’t forget to subscribe to our newsletter not to miss any of the new Unity development blog posts!

Coroutines in Unity Part 3

Coroutines in Unity – Encapsulating with Promises [Part 3]

 

In the last part of the series we’re going to build a real example of a REST API Interface using Unity’s Coroutines as an internal web requests tool and Promises as an encapsulation layer. We’re going to use the fake REST API service available for everyone to test their services on. It’s a simple API that implements the classic user to-do lists, posts & comments section as well as the album & photos scenario. Very useful if you’re building your own front-end but don’t have your own running server just yet.

NOTE: This tutorial is a bit more advanced and it won’t teach you REST backend theory or JSON serialization. It also assumes you’re already familiar with the RSG Promises we’ve covered in Part 2.

The project

Our project is going to be based around the user to-do lists. The main feature is simple: it’ll take a username as input and provide a list of tasks associated with that user. The application is going to get a list of all the users, find the searched username in it and if that user exists it will then grab all the tasks. Ideally you’d want the user searching to be done server-side, but for the sake of this example let’s say someone hadn’t thought it through and left you to do your job.

For JSON deserialization we’re using the popular JSON .NET framework. If your project is going to be cross-platform you should take a look at JSON.NET for Unity, which uses the same namespace and structure so it can easily be used as a drop-in replacement.

We’re going to work with Unity 5.4.0f3. You can download the .unitypackage here with a complete project and all the necessary plugins. Let’s dive into it.

The project features a Plugins directory, Scenes directory with the single example scene as well as Scripts directory, where the whole codebase sits. The code is structured as follows:

devenv_2016-08-24_11-09-12

Let’s start from the top.

The Models

The Models directory is where the data models’ classes are. They’re essentially the classes with properties mapped to JSON object keys. For example our JSON of a single Task object looks like this:

The associated Model class is then being implemented in the following way:

As you can see, JSON .NET allows for an extremely easy mapping using the JsonProperty attribute. Actually, you can skip these entirely if the property name matches the JSON key. Personally I prefer camelCase in my JSONs and PascalCase in my properties. Keep in mind that for AOT platforms you should use JSON .NET for Unity or use regular fields. Refer to the documentation for more information.

The User model is a stripped model as the jsonplaceholder returns a much bigger JSON, but for the purpose of this example we will not implement all the properties.

Promises as a service interface

Let’s say you’re working on a REST API for a month only to find out that management of your company decided to move to Websocket. Or perhaps you’re ahead of your backend department and want to test new features on your own without the need of using a real server. To remedy this it’s a good idea to implement the Factory pattern which let you choose the exact implementation of your service (APIServiceFactory) by encapsulating a common interface for all of them (IAPIService). The interface is using Promises as the abstraction layer so it’s very easy to use.

To search users and list their tasks we only need two functions:

If you’re going to need another API implementation in the future all you have to do is create a new class that will implement these two methods. The instantiation is done via the factory and the provided config (IClientConfig and ClientConfig):

RestAPIService

The REST API implementation uses the Unity’s Coroutines and the UnityWebRequest class under the hood. Because of that, the factory creates a GameObject and attaches the RestAPIService class, which also extends the MonoBehaviour. This lets us encapsulate the coroutines even further – you’ll be able to use the service in all of the classes, because the interface deals with Promises only. For example, getting the user tasks is done like so:

Notice how easily we control the output with promise.Resolve() and promise.Reject().

TestAPIService

The test implementation is just an example of what you can do. It returns objects without any external calls, but you could also use it as a room to test your JSON deserialization without launching a real server. The bottom line is that this should be the space to mess around with no worries that you’re hard-coding some test scenarios which need to be commented out later. All you have to do is change the config to the real service and you’re done.

So for example, if you’d like to test how your tasks` UI look, but don’t have the tasks functionality done server-side just yet, simply implement the test service and the GetUserTasks() method to return a bunch of test objects:

Notice that you can resolve promises instantly when needed.

The result

The payoff is the example test scene and the MainScreenController class which utilizes the interface. First, it initializes the service using the Factory:

As mentioned earlier, changing to Test implementation is as simple as swapping that APIType property in the config. The UI consists of a single input field where you type in the username and a button to get all the user tasks. Using the common interface it couldn’t be any simpler:

2016-08-24_10-46-14

Summary

And at last we come to an end of the series. Again, the final project can be downloaded as the .unitypackage here. In conclusion Promises prove to be a great way to abstract your code from Unity specific Coroutines. They can also be used in many different cases and are an elegant way to create clean interfaces. We hope you’ll enjoy them as much as we do. If you have any questions about the series or the example project, feel free to leave a comment in the section below.

Couroutines in Unity Part 2

Coroutines in Unity – Encapsulating with Promises [Part 2]

In the last article we focused on the internals behind Unity’s Coroutines and went in depth on how they work. We covered IEnumerator interface and iterator blocks to get a grasp on how the engine takes care of the coroutine functions. We’ve also managed to list a few problems with the implementation and shortcomings that you can stumble upon if a need to write more complex coroutines arises.
In today’s article, we’re going to present you the idea of Promises and where they originated from.

Callbacks

Most asynchronous operations in Javascript APIs return a result with a callback (in C# terms: an Action delegate) when they finish work. You can explicitly provide a function for those, but to follow asynchronous code easier many decide to implement callbacks using anonymous functions. In theory it does seem like a decent upgrade to our Coroutines. Let’s try to form an example of how to do that in C#:

Not bad! As you can see that actually works fairly well. It gives us a possibility to return a value as well as raise errors and react to them. The problem, however, is the code growing horizontally with more indents as you stack coroutines in a sequence. Also, the error checking has to be done in each and every one of them. Eventually, with more complicated functions you end up in a callback hell. What is that? Well, let’s just copy our coroutine calls and stack four of these bad boys:

Just look at the pyramid shape and all the } and })); at the end. Yikes! You’d also need to get really creative with the names as they have to be unique. In terms of errors, you could probably clean it up a bit if you moved error handling to another function. But it still doesn’t look appealing and here we only have four coroutines stacked. When writing more complex functions or perhaps APIs for your backend services, that number can increase drastically. So, what’s the solution?

Promises

Promises have been popularized by many 3rd party Javascript libraries before getting a native implementation in ES6. It’s interesting to note that the idea itself had been actually researched and introduced in the 70s and 80s. Promises as we know them today were first introduced in a year 1988 by Barbara Liskov and Liuba Shira, but a similar idea came from the functional programming languages years before.

A C# library conforming the Promises/A+ Spec was released a couple of years ago and is a big game changer for managing asynchronous operations. Let’s dive into the code.

A Promise is an object that you return from your asynchronous function immediately, so the caller can await resolution (or error) of your operations. Essentially, it represents a proxy for a value not necessarily known when the promise is created. A Promise can be later resolved or rejected once you complete your actions. This allows asynchronous methods to return values and run like synchronous methods: except instead of the final value, they return a promise of having a value at some point in the future. The best part, however, is the simplicity of stacking them with a simple interface. Here’s how we can redo our first example and implement Promises instead of pure Action delegates:

Much better on the caller side! You get to hide and encapsulate coroutine behavior while getting all the advantages from the promises. With .Then() function you can easily stack new promises in a logical order and handle different result types throughout them. Moreover, with .Catch() you can catch exceptions in all of your promises. If any of the above gets rejected, then the promise chain will get immediately terminated and the code will jump to the nearest catch. Not only that, the catch function actually uses Exception type, so you can also easily throw your own exceptions:

As long as you extend from Exception class you can write your own exceptions, mimicking try…catch behavior. Handle them like this:

Summary

As you can see, Promises provide a great mechanism to handle your asynchronous operations. You can easily throw errors from any of your promises in stack, handle returning values as well as hide the coroutine implementation if you use it while working with Unity. You retain all the powerful aspects of Coroutines in terms of the implementation, but also improve greatly the interface for your complicated APIs and services. The library offers much more than what was covered and we strongly recommend looking up the documentation to see what else it has to offer.
In the final part of the series, we’ll show you a real example of writing a REST API interface using Unity’s Coroutines & Promises to achieve the cleanest code possible.

Continued in Part 3 here.

Coroutines in Unity Part 1

Coroutines in Unity – Encapsulating with Promises [Part 1]

Every Unity developer should be familiar with Coroutines. For many they are the way to script a lot of asynchronous and time-delayed tasks. If you’re not up to the speed, they’re pretty much special methods that can suspend and resume their execution for any time desired. In practice, they can be perceived as an illusion of concurrent functions (although they have nothing to do with threads!). There are, however, some problems that many programmers stumble upon while using them. Let’s take a closer look.

The internals

So what exactly are Unity’s coroutines under the hood? How do they work? Granted that we don’t have a direct access to Unity’s source code, but gathering evidence from Manual and expanding on the knowledge from C# we can assume this is more or less how they’re done. Let’s lean over this simple example:

You don’t have to be genius to figure out that this will log “Hello there!” in the console and “Hello from future!” after 2 seconds. But how? To understand coroutines one must first look at the function’s signature – more precisely, the returned type. The IEnumerator serves as a way of performing iterations on a collection. It controls moving from one object to the next one in a sequence.

To do it, it declares two very important members: a Current property, which has a reference to the element that enumerator (or a cursor you could say) is currently over, and a MoveNext() function, which moves to the next element whilst calculating the new current value. It also has a Reset() function that sets the enumerator to its initial position, but we’ll skip that.

Now since the IEnumerator is just an interface it doesn’t explicitly specify the Current type (other than it’s an object). We can do whatever we want to calculate the next object. MoveNext() will simply do the job and return false if we end up at the end of a sequence.

Iterator blocks

In pure C# we can easily “implement” this interface in special iterator blocks. In practice, C# compiler converts iterator blocks into state machines. Those are the functions that return the IEnumerator type and use the yield return statement to return the values (yes, multiple ones). Calling that makes the MoveNext() function simply return true and set Current to whatever you’re returning. If you want to stop the enumerator you can just call yield break which makes sure that MoveNext() returns false and terminates the sequence (think of it like break; in a loop). An example:

Compile this on your own and you’ll get the following output:

111111

This example uses the generic interface IEnumerator<T>, but as previously mentioned, you can use the regular one, IEnumerator, where your Current will be of any type. This is exactly what Unity requires in coroutines.

So, with that in mind, we start to get a clearer picture on what Unity actually does with coroutines. StartCoroutine adds the coroutine to some sort of a container. Unity iterates through every executed coroutine in StartCoroutine and performs MoveNext() on those which are ready to continue their work. As shown in the example above, it evaluates expressions between yield return statements and returns a value. If it returns false then it obviously tells Unity to terminate that coroutine (as it simply has just finished). If true, it checks the Current property (remember, non-generic interface!) and sees if there are any familiar types. Remember WaitForSeconds() in the very first example? Unity sees that and pauses the coroutine for seconds specified. In fact, it actually extends from YieldInstruction base type. You’ve also got:

  • WaitForEndForFrame, which resumes the coroutine at the end of the frame after all cameras and GUI are rendered
  • WaitForFixedUpdate, which waits until next fixed frame rate update function
  • Coroutine type itself, which you could use for nest coroutines
  • CustomYieldInstruction, introduced to write your own custom yield statements – just extend from that class and override keepWaiting property

So where’s the catch?

It goes without saying that with these simple types you can suddenly script some time-based game logic as well as asynchronous events very easily. You can show a UI notification after few seconds in just a few lines of code without any dirty timers. Not only that, but you can even yield return the UnityWebRequest.Send() function and pause your function until you get a HTTP response. “What’s the problem with that then?”, you may ask.

First of all, you can’t easily return a value from coroutines. The signature needs to return IEnumerator to keep a track of when and where to resume your method. Second of all, there is no exception handling at the coroutine level. You can’t use try…catch block with a yield statement in it. You would have to basically try catch every non-yield expression in your coroutine. But what if there are multiple expressions segregated with multiple yields? Or maybe you’d like to stack coroutines one after another. But how to communicate to the coroutines down below the pipe that the top one has encountered a runtime exception?

Fortunately, there is a solution. In the next part we’ll take a look at Promises and their origin from Javascript. Read it here.

Finite State Machines [Part 3]

Here’s our final blog tutorial for the FSM. We will review what we’ve discussed on the first part, and implement the FSM System that we did before.

Just a recap on the previous parts:

sOSpPXe__WTretdttbvYesQ

This will be the loop of our FSM. First we initialize the FSM, create states, create actions, and map them all together. After we have mapped them, we will now start the FSM and indicate the state that the AI will start to. Now, the AI will change to a specific state, and the FSM will initialize the action, update it until it the action finishes and sends an event indicating that the action is finished. Finally, the FSM will go back and change the state.

Now it’s time to implement them.

Text Action

Let’s create a TextAction so that we’ll see the FSM System first hand.

1FReRU4CWYFVPXTHKa65PQqfu7VQx6nJ3poP4_6A

Let’s first import the Common.FSM so that we could use our FSM system, and let this class inherit the FSMAction class.

Let’s now write the variables and constructor for this specific action.

textToShow is the string that we will print out in the console when updating. Duration is the length of this action, and the finishEvent is the call to transition to another state.

Let’s override the virtual functions of the FSMAction so that the FSM could call them.

OnEnter will handle all the things that we want to do when starting an action. Just like a Start() in MonoBehaviour, we will initialize our action at this stage. Update will be called by the FSM’s action processor, that is called by the FSM’s Update function, and that is called by our AI’s class. On exit of course, will be the things that we will do when we finishes an action. Personally, I’d rather have a finish function that will send the event.

AI Implementation

Now that we’ve made an action, let’s make an AI.

1vBWCxCqzAGoyCv4XThrLnrhqyVKfgTpDvPZN4Tk

Let’s create an empty that will hold our AI script.

1fHeGwtXW1jPMC7ezRqHJpHrrztNsHa7yKHwb3q4After creating an empty, let’s create a script that will implement our FSM system and the action that we made.

Let’s make two FSMStates and two FSMAction for our AITest. Don’t forget to import Common.FSM or we won’t be able to use the FSM system that we’ve made.

Again, fsm will be the engine of our state machine, we will have two kinds of state, PatrolState, and IdleState. It’s up to you how you want to name them. Lastly, we will have two text actions, one for each state, PatrolAction, and IdleAction.

Let’s now create the FSM, States, and Actions in the Start() function.

First, we will initialize the FSM, then add new states. Remember, FSM.AddState() returns FSMStates so that we won’t have to declare a new FSMState, and add them to the FSM.

Now that we have states and action, let’s now map everything, and add event ids to every transitions.

We mapped the PatrolState to IdleState when an event was sent to the state and vice versa. Let’s now initialize our actions.

The first property which is a string, will be the output of our action, the second one will determine the duration of the action, and the last property will be the event that it will send out after the action is finished.

Keep in mind that everything here is inside the start function. Let’s now try and make the FSM work by calling the FSM.Start() and FSM.Update();

Again, fsm.Start() is called after all initialization under the Start(). Now let’s attach the AITest to the empty game object that we created earlier and press Play in the editor.

Now finally, watch the automation happens!

1s-7f6nFEDuhmfFSXjaXAk0_Fh0Jyhs1P_N6EKsQAI will print out Idle for every 2 seconds and will Patrol every 3 seconds.

Moving Action

1VwqSEDvSaDRP50DJsCX2w-dso9Bch-lcqp0D9y8Now let’s take it to another level. Let’s make a moving object and at the same time, printing out strings in the console. But we’re not going to do it in one action. We’ll be creating another action that will be added to the same state.

Let’s make another script called AITestTwo.

1IU-GFRQu-tgoJLrMoM_GZ2SxE0rq6sMd5cfswRALet’s create another action called MoveAction. This will be a generic action for moving object.’

Open up the MoveAction.cs and let’s write the action.

 

MoveAction.cs is different, we have to have a reference to the object’s transform so that the action could move it.

 

Let’s discuss the properties. As I said above, we will need to have the object’s transform to be referenced in this action since we want THIS action to move the object, NOT the AI Class. Pretty self explanatory, Vector3 from, and to. Again, duration of the action, and the finish event.

As you see there, we have two variables that aren’t included in the Init() properties which is the journeyLength, and polledTime. We will use them for our Vector3.Lerp function later on. The polled time will be included in our calculation later on.

Now we added a helper function for position which is the SetPosition() to make things easier for us. Again, OnEnter() initializes the action, the OnUpdate() will be the one that will execute the Lerp function. This is also where we will calculate the ratio that is needed for the Lerp function. When the action finishes, we will set the object to the desired final position, and reset our variables.

Multi-action Implementation

Now, let’s go and set up the second AI.

We now have two actions for each state. The FSM will now update two actions in one state. What we did here is just the same from what we did on the TextAction.cs. We made instances of the classes, added the actions to states, and added transitions and calls to those states, and initialized the actions.

Now let’s hit play and hope that it works properly.

1KDFzVJldz17rgpUe8XPO884SAYqx5JYzd5D8jaA

1RmIMDg8oKBNpn_2JPWFTLf1FNPbdbYj0YmMe4Ic

As you can see, the AI is now doing the actions at the same time. You can mix different actions and add them dynamically to your desired state.

What’s great about this is that you can add a lot of actions and contain them into one state and do them simultaneously. Although it will cause you some performance issues if you’re on mobile. What I suggest is that, when you use it for mobile, just do at least 1 or 2 actions simultaneously just for safety. I haven’t done real tests for mobile though.

So there it is, we have concluded our Dynamic FSM tutorial. I hope that this will become helpful for your games. You could use this in any game, in any way. Whether you use it on UI, GameObjects, or whatever fits your needs. Please do remember to comment if you have any questions, I am happy to send a reply as soon as I can!

FSM is a really big topic to cover in three parts, so here are few of the FSM-related articles and implementations if you want to understand it a little better. I believe these will explain FSM much further:

This is the link for the unity package if you want to see the whole project.

This is the link for the scripts that we made all throughout.