Augmented Reality Wave Reflection

Recently, as part of our consultation project, the requirements are to vizualise sound wave reflection off a wall. It is required that the AR does not use markers so we used ground plane tracking. This is the outcome. By using the mic on mobile devices, students can record their own voice, the voice will be transmitted to the wall and reflected back. The students then can hear the echos of their own voices.

When Your Code Is On Fire

Disasters do happen when you are working on projects. I am reminded of a certain situation in which a junior programmer imported something into the core library and errors started popping up everywhere. Like “the whole house is on fire” situation. Now, I know about not touching production rules, backups, etc. There are systems put together in-place to stop this particular problem from happening. But this post is more of how to handle things when shit happens. This guide is mainly for Junior Programmers of Unity, but it may be of help for other software and languages as well.

Do Not Touch, Take A Break first

Hands off, stand up and go drink water. Take a break, take a deep breath, try to calm yourself as much as you can. When your code is on fire, you will be freaked out. But, trying to fix things when you are not having a rational mind is the worst thing that you can do to yourself, it will create more errors, which in turn might be harder to fix afterwards.

Accept The Situation

We screwed up, accept the situation. Things happen, we cannot change what has happen, but we can make up for our mistakes by fixing it. You might be getting an earful, but you need to make things better.

Analyzing the errors, and fixing it

You need to look at the errors that pops up. Here are some of the patterns you need to look at:

If the errors looks like it comes from the same method, variable or class reference:

This means, you have inadvertently overwritten a certain class or file. If the class/file belongs to you, you can fix this by finding out what changes have you made from the current version and the old version. But, given the fact that you are reading this guide I am assuming that its not you that developed that particular class/file. In that case, you would need to ask your co-worker that written the class to see if he has a backup. If he does not, he can still help you since he understands his code better than you. Just be sure to say sorry, thank you for the help, and buy them lunch or something.

If the errors looks like it comes from a particular library:

When this happens, chances are your library versions are mismatched, one of them is either older or newer. Find out what the old version number is. Download the old one, create a backup of the current code, replace the library with the old version. Sometimes, different versions of libraries have what we call breaking-changes. These are changes to the codes that makes our old implementation to no longer works. So, do not simply upgrade a library without glancing through the change notes.

If the errors looks like it comes from multiple libraries:

Sometimes this happens because you messed with or mismatched their dependencies. Chances are, there are libraries that uses the same dependency components from other libraries. Go through the codes that contains the errors and find out which dependency they share, and replace that dependency library with the correct version.

When all else fails

You tried fixing it, but it does not work, the errors does not make sense. Here is what you should do.

  1. Backup the code. I am literally asking you to have a backup of your error ridden project. Just in case you turned the fire into inferno, you can always go back to just fire.
  2. Isolate the parts that does not have errors, move them out of your burning project folder into another project folder. Save what you can from the burning wreckage. You do not have to start from scratch.
  3. Reimport the libraries, download from original/error free source.
  4. Bring one of the code files that have errors into your new project, see if it still burns in the new project. If it does, see what is wrong, and fix them first. Do not add more files until you fixed this one code file.
  5. Repeat step 4 until you have a working version again. It might take time, but this will allow you to focus on the problems one at a time.

Learning from disasters

Here are a few things that you can do to avoid such disasters:

  1. Backup!, Backup!, Backup! before doing any changes, especially to Production/Core.
  2. Do Not Touch Production or Core. Make a copy of it in your machine, and make changes in that instead. If it is okay, run it by your person in charge, he will move it to core safely.
  3. Always refer the person in charge before doing anything in Production / Core. They are the ones who are responsible for the whole codebase, do not bypass them, ever. They are the ones that will be either saving you from disaster or help you out of one.
  4. If you are not sure, ask and clarify.

Simpler Way To Play Animation for Vuforia (2021 Update)

Okay, you want to play an animation, then nooooooo………..the model has more than one animation, so what do you do? Do you go through the process and create transitions, add parameters and do all of that? No you don’t need to actually. This is a handy tool for doing things fast. Here is the download link, and also as usual the explanation part of it, coz what use is things that you don’t understand or learn from?

How to use

  1. Add the Animation Player script to your model, it will give you the names of the animation clip

2. Call PlayAnimation using Vuforia Default Trackable Event Handler or Button

3. Type in the name of the animation you want to play in the slot. Done! When your ImageTarget is detected, the animation will play.

The Editor Code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;


[CustomEditor(typeof(AnimationPlayer))]
public class AnimationPlayerEditor : Editor
{
    AnimationPlayer myTarget;
    UnityEditor.Animations.ChildAnimatorState[] states;

    public override void OnInspectorGUI()
    {
        // Assign the script to this inspector so that we can play with its properties
        myTarget = (AnimationPlayer)target;
        // create the menu and add items to it
        GenericMenu menu = new GenericMenu();
        
        GetAnimatorStates();

        GUILayout.Label("Animation State Name From Model:");

        foreach(UnityEditor.Animations.ChildAnimatorState b in states)
        {
          GUILayout.Label(b.state.name);
        }


    }

    void GetAnimatorStates()
    {
        // Get a reference to the Animator Controller:
        UnityEditor.Animations.AnimatorController animatorController = myTarget.GetTargetAnimator().runtimeAnimatorController as UnityEditor.Animations.AnimatorController;

        // States on layer 0:
        UnityEditor.Animations.AnimatorStateMachine stateMachine = animatorController.layers[0].stateMachine;
        states = stateMachine.states;
        
    }



}

The Script (called AnimationPlayer)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class AnimationPlayer : MonoBehaviour
{
    Animator animator;
    // Start is called before the first frame update
    void Start()
    {
        animator = gameObject.GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public Animator GetTargetAnimator()
    {
        if(animator == null)
        {
            animator = gameObject.GetComponent<Animator>();
            return animator;
        }
        else
        {
            return animator;
        }
        
    }

    public void PlayAnimation(string animationName)
    {
        if(animationName != "")
        {
            animator.StopPlayback();
            animator.Play(animationName);
        }

        
    }


}

The Explanation

This script has two parts. The first part is the editor extension. The reason we need the editor extension is to access the Animator’s Editor properties in order for us to extract the animation state names. This information is only available through UnityEditor.Animations.AnimatorController.

The second part is the script itself. We need this script to be two things, one is to become the interface that our editor script will rely on to get the reference to the Animator. The second function is for us to ask the animator to play our animation of choice.

Getting Yourself Started with Vuforia with Unity 2019 above (2020 updates)

So, why is this sudden post? Err well, if you install the latest versions of Unity, you will notice that setting up Vuforia will be a little bit different. We will need to use Unity’s Package Manager. So to update this new knowledge, here’s the new tutorial for how to get started with Vuforia. From now on, I will be trying to use Camtasia Studio this time to easily explain things. Leave your comments on how you like it, and how I can improve

Vuforia: Putting 2D Image on your Image Target

In order to complete this tutorial, you need:

  1. An Image, you can download one at www.pixabay.com
  2. You need to have completed the previous tutorial on Vuforia Basics

From the previous tutorial, we have added boxes to our image target.

Now lets import the image we needed to Unity, Drag and Drop the image you needed to the Assets window.

Next, lets right click one of the Image Targets we already have. Under 3D Obeject, select Plane

A Huge plane will appear. Don’t worry, we will resize this once done. But for now drag and drop the image we imported to the plane.

The plane will now have the image we imported. It will look something like this

Resize, rotate and move the plane as needed until it fit on your Image Target.

We no longer need the Cube. So let’s delete the cube. You will get something like this:

We are done! So lets press Play and test it out. You should now have an image and

Publishing Your Android App to Play Store – XZIMG Augmented Vision Tutorial 5 of 7

Filling in App Content settings

Click on App Content

App Content window appears. Click Start

The first question is Target Age. Select your Target Age Group and click Next

The next question is whether the app could unintentionally appeal to children. you may select Yes or No. If Yes a ‘Not designed for children’ label may be shown next to your app on Google Play. In this example, I chose No.

Select your answer and click Next

A summary will appear, read it and if it is correct, click Submit

Success. Now a green checkmark appears beside App Content

Publishing Your Android App to Play Store – XZIMG Augmented Vision Tutorial 2 of 7

Registering For A Google Play Developer Account

Note: You would need to pay a 25$ registration fee in the payment step

Go to https://play.google.com/apps/publish/signup/ and sign in with your Google Account. If you don’t have Google Account, you need to create a new one.

An Agreement Page appears. Agree with the agreement and click Continue To Payment

A payment window appears. Complete the details and press Buy

Finally, after the payment, fill in the Developer Profile form and click Complete Registration

You will then be able to access the Google Play Console. This means your registration is now complete. You would notice though that there will not any app registered unlike my account.

Publishing our app to Google Play Console

Click Create Application

A window appears. Fill in the title of your application and press Create

Uploading the App Bundle (.aab)

Click App Releases

For the purpose of simplicity we will skip beta testing and assume that our program is already the Production version of things. Wooooow. Under Production Track, click Manage

Click Create Release

You will be asked to let Google manage and protect your app signing key, press Continue

Click Browse Files

A file window opens, select our .aab and click Open

Once upload is done, the Android App Bundle will be shown together with its version code and size.

Scroll down to What’s new in this release? Then type a simple description of the changes you made to the app. Since this is the initial release, lets type in “This is the initial release of the application” and press Save

We are not done yet, don’t click Review. Next, we will set a Content Rating

See you in the next part of the tutorial

Deploying our AR to PC – XZIMG Augmented Vision

Now that we have completed our first AR simple project as per our previous tutorial, lets try to deploy our XZIMG Augmented Vision project to PC

Accessing the Build Settings

Go to File, select Build Settings

You will see something like this

Add Current Scene to our Build

Click Add Open Scene to add our current scene to our build

Our scene has now been added to our build. It will be listed in Scenes In Build

Building the Application

Press the Build button

A window appears asking where you want to store the built application. You can store it wherever you feel is convenient. I usually create a folder called Output inside my project folder, once you selected your own folder, press Select Folder

The Application will start building

The completed Application will be stored at our selected folder

Testing the application

When you run the Application, this window will appear. I recommend to check the Windowed option, so that it is easier to move the AR app around when its running, otherwise it will run fullscreen. Its just a preference though

There it is, our application is playing happily from our PC

Simpler Vuforia Event Handling using Unity Events

Edit 2021 Update:

Notice, this codes are no longer needed as Vuforia has provided their own Unity Events Handler. So If you are using the latest Vuforia, it comes built in. It looks like the picture below and it works exactly the same as the one I wrote here.

This post below is still kept as there are people still struggling to update their old projects, so this is for you guys/gals in University, hope you can update soon!


Do you ever wish that Vuforia event handling is as simple as using the OnClick() property in Unity UI’s Button? Wish no more bros and sis. Here the code, and explanation on how I did it.

The Code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Vuforia;

    public class EasyEventHandler : MonoBehaviour, ITrackableEventHandler
    {

    public UnityEvent onMarkerFound;
    public UnityEvent onMarkerLost;

        protected TrackableBehaviour mTrackableBehaviour;
        protected TrackableBehaviour.Status m_PreviousStatus;
        protected TrackableBehaviour.Status m_NewStatus;



        protected virtual void Start()
        {
            mTrackableBehaviour = GetComponent<TrackableBehaviour>();
            if (mTrackableBehaviour)
                mTrackableBehaviour.RegisterTrackableEventHandler(this);
        }

        protected virtual void OnDestroy()
        {
            if (mTrackableBehaviour)
                mTrackableBehaviour.UnregisterTrackableEventHandler(this);
        }


        public void OnTrackableStateChanged(
            TrackableBehaviour.Status previousStatus,
            TrackableBehaviour.Status newStatus)
        {
            m_PreviousStatus = previousStatus;
            m_NewStatus = newStatus;

            if (newStatus == TrackableBehaviour.Status.DETECTED ||
                newStatus == TrackableBehaviour.Status.TRACKED ||
                newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
            {
                onMarkerFound.Invoke();
            }
            else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
                     newStatus == TrackableBehaviour.Status.NO_POSE)
            {
 
                onMarkerLost.Invoke();
            }
            else
            {
            // For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
            // Vuforia is starting, but tracking has not been lost or found yet
            // Call OnTrackingLost() to hide the augmentations
            onMarkerLost.Invoke();
            }
        }
    }

How it looks like

Explanation

Creating the Unity Events and Exposing it in Inspector

This code uses the UnityEngine.Events . Firstly, I create two UnityEvents variable, and make the variables public, doing this I get to expose the events, giving you that familiar On Click () thingy in Unity UI Button.

    public UnityEvent onMarkerFound;
    public UnityEvent onMarkerLost;

Invoking the Events when marker is detected and lost

Then, OnTrackableStateChanged, if the Image Target is detected, I use the UnityEvent’s Invoke() function to Invoke the event, this will then work just like the On Click ()

That’s all folks…… enjoy!