- Home /
Gameobject becomes null without a reason
Short intro: I am trying to make an Augmented Reality App, where the only interaction is that the user can scale the augmented model by pinching and play animation by just tapping on the screen. So there are several animations per model and by single touching the screen you can play one animation after the other. I thaught this should be pretty simple to handle, but i've run into a lot of problems and have tried many different things.
In my update method I am checking for Input Touches and then want to play the animation. The currentObject is statis. The interesting part is, that in the update method i can access the currentObject before the for statement in the logCurrentObject method. But then some lines later (in the Debug.Log("RENDERER...) its suddenly null. I do not understand how it can turn null, when there never is happening something with it. Note: the currentObject gets set whenever the camera found and trackable Image in the scene. This works.
void Update ()
{
logCurrentObject();
for (int i = 0; i < Input.touchCount; i++) {
if (Input.touchCount == 1 && Input.GetTouch (i).phase == TouchPhase.Ended) {
Debug.Log("RENDERER: " + currentObject.name + "; ENABLED: " + currentObject.renderer.enabled);
if (Input.GetTouch (i).position.x < Screen.width && Input.GetTouch (i).position.y < Screen.height) {
if (currentObject.renderer.enabled) {
if (counter >= currentAnimations.Length) {
counter = 0;
}
currentObject.animation.Play (currentAnimations [counter++]);
}
}
}
}
}
public static void setCurrentObject(GameObject go, string[] animationList){
currentObject = go;
currentAnimations = animationList;
initialScale = go.transform.localScale;
logCurrentObject();
}
private static void logCurrentObject(){
Debug.Log("Currentobject: " + currentObject.name);
for( int i = 0; i < currentAnimations.Length; i++){
Debug.Log("CurrentAnimations: "+ currentAnimations[i]);
}
}
void LateUpdate ()
{
DetectTouchMovement.Calculate ();
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 && this.gameObject.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);
}
}
Also if anyone has a recommendation how i can implement what i want to achieve, i would be really happy for every solution.
UPDATE: I was able to narrow it down a little bit. I can only access the name of the currentobject, but no component of it, like the renderer or in that case the animation. So maybe I am messing up something when setting the currentObject. As mentioned earlier I am doing this in another script which is part of the Vuforia Framework in the OnTrackingFound() method. See:
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");
}
When does the function setCurrentObject(...) is called ? I assume this is the only place where currentObject is valuated. Is it called in the Awake or Start function ?
Its called by another script which is attached to ImageTargets (the gameobject which represent real life objects which can be tracked) If the camera finds this object then the OnTrackingFound method is called (this script is part of the Vuforia framework). I just added some lines in this method where i call the setCurrentObject method from this script. This setup of the currentobject work.
So I suppose it is normal behavior.
While your other script has not valuated currentObject, this Update method will play with errors.
you should check at the beginning that currentObject != null
Ummm, no. When i put the line
Debug.Log("Currentobject is " + currentObejct.name);
inbefore the for statement in the update method, then i have the correct currentObject (as long as I am tracking one target of course). But then in the same method in the lines after the for statement, the currentObject is suddenly null. And that is what is struggling with me. Again, the problem I have is that one variable (currentObject) changes it values as it seems, during one method call (update method) though I am not accessing the variable at all.
Answer by GrannySmith · Aug 05, 2013 at 12:55 PM
I got it running now like this: 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]);
}
}
}
And in the DefaultTrackableEventHandler the OnTrackingFound() method, looks like this:
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 call the resetScale() method from my AnimController Script, so that whenever the trackable is lost, its initial scale is reset.
However there is one issue left, because i tried to assign the currentObject like this: public static void setCurrentObject (GameObject go, string[] animationList) { currentObject = go;
} But this does NOT work. This way i can only access the name of the currentObject and no other Components whatsoever. This is something I do not understand and wish to have clarification on this. So what does this direct assigning of one GameObject to another one actually do?
Answer by vfxjex · Aug 14, 2016 at 05:55 AM
If you use Vofuria All static Gameobject will be null when you load a scene. I'm not sure if this is a bug or they purposely make it like this.
Your answer
Follow this Question
Related Questions
How do I ask if RaycastHit returns null? 3 Answers
Accessing other GameObjects Script Variables 2 Answers
[SyncVar] GameObject Instantiate returns null. 1 Answer
Gameobject as Optional Argument 0 Answers