Log in or register to post comments

Scaling model and playing animations dynamically

August 5, 2013 - 1:44am #1

Ok, I am trying to make an AR App where at the startup an assetbundle of 3D content and the Dataset is getting downloaded. The only interaction for the user is to scale the 3D models by pinching and playing through all the animations by tapping on the screen. Everything with the assetbundles and the dataset works well so far, but i am not able to get the interaction working. Pls have a look at the question I asked on UnityAnswers, which also describes a little bit better what i am doing:

http://answers.unity3d.com/questions/508085/gameobject-becomes-null-without-a-reason.html

The reason why i am posting this here is because i have to understand how OnTrackingFound() is working. As you can see in the link above, my currentObject behaves very weird. It has the correct values in on line and in the next line it suddently becomes null without me doing anything to it.

The only time i interact with this variable is when a Target is being found (therefore Vuforia calling the OnTrackingFound() method) i call my setCurrentObject() method from within OnTrackingFound().

So my question is: Is it possible that this method interfers in some way with the update method of my script? Because i can't explain myself why the currentObject has correct values in one line and is null in the next line.

I would also be very happy, if someone has a different solution or idea for this problem, because i thaught that this won't be much of a problem, but now i am stuck for a rather long time on this.

 

thanks in advance

Scaling model and playing animations dynamically

October 12, 2014 - 10:36pm #10

i got the code from vuforia forum for scaling the gameobject in arview.

but it's not working..please reply as soon as possible.

 

Scaling model and playing animations dynamically

August 5, 2013 - 11:39pm #9

I've tried all of this. Everytime with the same outcome. I only was able to access the name of this GameObject and no components like the renderer or the animation. This gameObject was never null, only its components and the name was always the correct one. So this is what i really didn't understand, because when it has the correct name it must have been the correct gameobject. I even printed out the whole gameobject hierarchy because i thaught, maybe there are duplicat objects or something similar. But no.

There must be some behaviour with references in Unity with GameObjects I simply don't know.

Scaling model and playing animations dynamically

August 5, 2013 - 6:32am #8

You should not need to call GameObject.Find() as it traverse the entire hierarchy.  Moreover, Unity preassigns a variable named "gameObject" to the currently running script:

http://answers.unity3d.com/questions/36109/get-the-gameobject-that-is-connected-to-the-script.html

 

So with this in mind I took the DefaultTrackableEventHandler.cs

...and added this at the top:

 

static GameObject currentObject;

 

then this:

 

private void SetCurrentObject(GameObject go)

{

    currentObject = go;

    Debug.Log("SetCurrentObject = " + currentObject);

}

 

..and finally modified this 

 

private void OnTrackingFound()

{

    SetCurrentObject(gameObject);

 

         ..rest is the same
 
 
..and it seemd to print out the current object fine.
 
N

 

 

 

 

 

 

 

Scaling model and playing animations dynamically

August 5, 2013 - 6:05am #7

NalinS wrote:

No problem - so is it working now?

BTW we're all learning...

N

Yes everything is working now how I intended it. Only Problem is like i stated the post before, that I don't understand what the difference between assigning an GameObject directly and calling the GameObject.Find() method is. But i posted this along with my solution now on UnityAnswers too, hoping someone will be able to clarify this to me.

Scaling model and playing animations dynamically

August 5, 2013 - 5:54am #6

No problem - so is it working now?

BTW we're all learning...

N

Scaling model and playing animations dynamically

August 5, 2013 - 5:47am #5

Thanks NalinS for your help and advice.

I worked over a week now on this App (which is rather embarassing considering, that it isn't that much code etc.) and at the time i make a thread right here, I am able to finish it. But nevertheless, here is my solution:

The biggest problem was, that first i wanted to directly set the currentObject like this:

public void setCurrentObject(GameObejct go){
currentObejct = go;
}

This does not work however and unfortunately I still do not know, what happens there in comparison when i do it like this:

public void setCurrentObject(GameObject go){
currentObject = GameObject.Find(go.name);
}

However, this is not an issue related to the VuforiaForums but i just wanted to post this for completeness and it really was a big hassle for me.

So here is the full Script which handles everything, it's attached to the "ARCamera":

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

public class AnimController : MonoBehaviour
{

	public static int counter = 0;
	public static Vector3 initialScale;
	public static List<TrackableInfo> trackables;
	public static float factor;
	public static GameObject currentObject;
	public static List<GameObject> contentObjects;
	public static string[] currentAnimations;
	private static GameObject tmpGO;
	private static string text = "default";
	
	void Start ()
	{
	}
	
	void Update ()
	{		
		for (int i = 0; i < Input.touchCount; i++) {
			if (Input.touchCount == 1 && Input.GetTouch (i).phase == TouchPhase.Ended) {
				Debug.Log ("TOUCHY " + currentObject.name);
				if (Input.GetTouch (i).position.x < Screen.width && Input.GetTouch (i).position.y < Screen.height) {

					if (counter >= currentAnimations.Length) {
						counter = 0;
					}
					currentObject.animation.Play (currentAnimations [counter]);
					counter++;
				}
			}
		}
	}
	
	void LateUpdate ()
	{
		DetectTouchMovement.Calculate ();
		if(DetectTouchMovement.pinchDistanceDelta != 0){
			Debug.Log("Transform " + currentObject.transform.localScale.x + "; initial " + initialScale.x + "; factored " +initialScale.x + factor * 15);	
		}
		if (DetectTouchMovement.pinchDistanceDelta < 0 && currentObject.transform.localScale.x > initialScale.x) {
			logCurrentObject ();
			currentObject.transform.localScale = new Vector3 (currentObject.transform.localScale.x - factor, currentObject.transform.localScale.y - factor, currentObject.transform.localScale.z - factor);
			Debug.Log ("SCALE--------------: " + currentObject.transform.localScale.x + " 2: " + initialScale.x + factor * 15);
		}
		if (DetectTouchMovement.pinchDistanceDelta > 0 && currentObject.transform.localScale.x < initialScale.x + factor * 15) {
			logCurrentObject ();
			currentObject.transform.localScale = new Vector3 (currentObject.transform.localScale.x + factor, currentObject.transform.localScale.y + factor, currentObject.transform.localScale.z + factor);
			Debug.Log ("SCALE--------------: " + currentObject.transform.localScale.x + " 2: " + initialScale.x + factor * 15);
		}
	}
	
	public static void resetScale(){
		currentObject.transform.localScale = initialScale;	
	}
	
	public static void setCurrentObject (GameObject go, string[] animationList)
	{
		currentObject = GameObject.Find(go.name);	
		currentAnimations = animationList;
		initialScale = go.transform.localScale;
		logCurrentObject ();
		factor = initialScale.x / 100 * 5;
		counter = 0;
	}
	
	private static void logCurrentObject ()
	{
		Debug.Log ("Currentobject: " + currentObject.name);
		for (int i = 0; i < currentAnimations.Length; i++) {
			Debug.Log ("CurrentAnimations: " + currentAnimations [i]);
		}
	}
}

 

Another very stupid error was, that i didn't know that a statement like:

currentObject.animation.Play (currentAnimations [counter++]);

doesn't work like i thaught it does, meaning: incrementing the counter variable AFTER the execution of this line.

To make it complete here in this thread, also my code from the DefaultTrackableEventhandler. OnTrackingFound():

	private void OnTrackingFound ()
	{
		Renderer[] rendererComponents = GetComponentsInChildren<Renderer> (true);
		Collider[] colliderComponents = GetComponentsInChildren<Collider> (true);

		// Enable rendering:
		foreach (Renderer component in rendererComponents) {
			component.enabled = true;
			// added by me
			GameObject tmpGO = new GameObject ();
			string[] anims;
			int animCounter = 0;
			Transform[] t = gameObject.GetComponentsInChildren<Transform> ();
			trackables = GameObject.Find ("ARCamera").GetComponent<Init> ().getTrackables ();
			for (int i = 0; i < t.Length; i++) {
				for (int j = 0; j < trackables.Count; j++) {
					if (t [i].name == trackables [j].GetContentName () + "(Clone)") {
						tmpGO = t [i].gameObject;
						animCounter = trackables [j].GetAnimations ().Length;
					}
				}
			}
			anims = new string[animCounter];
			
			for (int j = 0; j < trackables.Count; j++) {
				if (tmpGO.name == trackables [j].GetContentName () + "(Clone)") {
					anims = trackables[j].GetAnimations();
				}
			}
			
			
			AnimController.setCurrentObject (tmpGO, anims);
			
			//.GetComponentInChildren<Transform>().gameObject
		}

		// Enable colliders:
		foreach (Collider component in colliderComponents) {
			component.enabled = true;
		}

		Debug.Log ("Trackable " + mTrackableBehaviour.TrackableName + " found");
	}

And in the OnTrackingLost() method i simply called the resetScale() method so whenever you loose a trackable the scale is reset to its initial value.

 

So sorry for bothering this forum with both my stupidity and misknowledge of Unity and C#.

Scaling model and playing animations dynamically

August 5, 2013 - 4:55am #4

it is described there that i dont setthe currentObject to a NULL value

Well, Vuforia is not changing anything.

 

Looking at your code in Unity Answers, you have this line:

GameObject tmpGO = new GameObject ();

..which may be causing a problem because the object is being instantiated each time.

You may be getting a problem because each potential trackable is able to change this object, and each one is competing to be the "current" object.

My suggestion is that here you only need a reference, and you could place this at the top of the script so there is only one instance.  Then you need to make sure that when you are iterating through the trackables that you deal with potential competition when setting the current object

 

N

Scaling model and playing animations dynamically

August 5, 2013 - 4:46am #3

NalinS wrote:

The reason why i am posting this here is because i have to understand how OnTrackingFound() is working

OnTrackinFound() and ..Lost() are pretty simple in what they do - see the code below.

Basically they are called when the state changes, and for any child of the Image Target (the augmentation) it enables the Renderer component so you can see it, and the Collider component so that you can interact with it.

Ok, so there is no "magic" behind this, because i already had a look at the methods and as you said, its not that spectacular. 

NalinS wrote:

You say that in your OnTrackingFound() you are using setCurrentObject() (which you have not shown), so I cannot think why there may be a problem.  Ther could be a case where your setCurrentObject may be setting a NULL value - probably best to debug this case in Unity and/or print out some log values.

OnTrackingFound()/Lost() will not be doing anything to interfere with this.

That*s why i posted the UnityAnswers link, because there this part is described. I just thaught that it would fit better into UnityAnswers than here. So you can see there how i call setCurrentObject and so on and it is described there that i dont setthe currentObject to a NULL value. Right now i am at least able to go through all the animations once, have a look here:

	void Update ()
	{
		tmpGO = GameObject.Find (currentObject.name);
		
		for (int i = 0; i < Input.touchCount; i++) {
			if (Input.touchCount == 1 && Input.GetTouch (i).phase == TouchPhase.Ended) {
				Debug.Log ("GOName " + tmpGO.name);
				if (Input.GetTouch (i).position.x < Screen.width && Input.GetTouch (i).position.y < Screen.height) {
					Debug.Log ("Animations " + currentAnimations [counter] + "; animlength " + currentAnimations.Length + "; counter "+ counter);
					if (counter >= currentAnimations.Length) {
						counter = 0;
					}
					tmpGO.animation.Play (currentAnimations [counter++]);
				}
			}
		}
	}

 

Scaling model and playing animations dynamically

August 5, 2013 - 2:42am #2

The reason why i am posting this here is because i have to understand how OnTrackingFound() is working

OnTrackinFound() and ..Lost() are pretty simple in what they do - see the code below.

Basically they are called when the state changes, and for any child of the Image Target (the augmentation) it enables the Renderer component so you can see it, and the Collider component so that you can interact with it.

You say that in your OnTrackingFound() you are using setCurrentObject() (which you have not shown), so I cannot think why there may be a problem.  Ther could be a case where your setCurrentObject may be setting a NULL value - probably best to debug this case in Unity and/or print out some log values.

OnTrackingFound()/Lost() will not be doing anything to interfere with this.

What some people have done is to us the augmentation as a button and detect via a Raycast and then play an animation, so this could be an alternative if you cannot get this to work.

HTH

N

 

 

 

 

    public void OnTrackableStateChanged(

                                    TrackableBehaviour.Status previousStatus,

                                    TrackableBehaviour.Status newStatus)

    {

        if (newStatus == TrackableBehaviour.Status.DETECTED ||

            newStatus == TrackableBehaviour.Status.TRACKED)

        {

            OnTrackingFound();

        }

        else

        {

            OnTrackingLost();

        }

    }

 

    #endregion // PUBLIC_METHODS

 

 

 

    #region PRIVATE_METHODS

 

 

    private void OnTrackingFound()

    {

        Renderer[] rendererComponents = GetComponentsInChildren<Renderer>(true);

        Collider[] colliderComponents = GetComponentsInChildren<Collider>(true);

 

        // Enable rendering:

        foreach (Renderer component in rendererComponents)

        {

            component.enabled = true;

        }

 

        // Enable colliders:

        foreach (Collider component in colliderComponents)

        {

            component.enabled = true;

        }

 

        Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");

    }

 

 

    private void OnTrackingLost()

    {

        Renderer[] rendererComponents = GetComponentsInChildren<Renderer>(true);

        Collider[] colliderComponents = GetComponentsInChildren<Collider>(true);

 

        // Disable rendering:

        foreach (Renderer component in rendererComponents)

        {

            component.enabled = false;

        }

 

        // Disable colliders:

        foreach (Collider component in colliderComponents)

        {

            component.enabled = false;

        }

 

        Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");

    }

 

Log in or register to post comments