Log in or register to post comments

Virtual Buttons won't work after instantiation?

November 10, 2011 - 10:10am #1

I've attached a virtual button to a enemy prefab in my project. When instantiated, the does not respond, or destroy the object.

If I drag the object on beforehand (non-instantiated) and touch the button, it works fine.

Are there any known issues / fixes for virtual buttons on instantiation?

Virtual Buttons won't work after instantiation?

September 17, 2014 - 12:23am #14

If I read again aini's post, he was facing this error:

Static member `ImageTargetBehaviour.CreateVirtualButton(string, UnityEngine.Vector2, UnityEngine.GameObject)' cannot be accessed with an instance reference, qualify it with a type name instead

 

As I said in the other link, this is because the code snippet below was using the wrong API, i.e. the static version of the CreateVirtualButton() method, but trying to call it as a non-static one (i.e. as an instance method, by calling "itb.CreateVirtualButton())" .

The "instance method" version of CreateVirtualButton() takes a Vector2 as third parameter, while the static version of the CreateVirtualButton() takes a GameObject as third parameter.

So, this line of code:

VirtualButtonBehaviour vbb = itb.CreateVirtualButton(vbName[i], mSemut.transform.localPosition, mSemut);

 

is incorrect (API-wise) and that's what causes the compile error reported by aini.

See also here:

https://developer.vuforia.com/resources/api/unity/class_image_target_abstract_behaviour

I was not suggesting any "workaround", but only saying "use the right API" and make sure your code compiles, first of all.

 

 

 

Virtual Buttons won't work after instantiation?

September 16, 2014 - 7:39am #13

I have been having a very similar issue as this user and the work around you suggest does not fix the question he asks. please review what it is he is asking.

Virtual Buttons won't work after instantiation?

September 25, 2013 - 2:34am #12

Virtual Buttons won't work after instantiation?

September 25, 2013 - 1:33am #11

i'm so sorry for disturbing all of you,
my english is not good,
but i need help,

this is my code to create new virtual button, and make it to be a child of another object which is child of image target.

// Update is called once per frame
	void Update () {	
		
		if (waktuCounter <= 0 && i!=1)
		{
			int ran = Random.Range(0,1);
			
			//instantiate the object
			mSemut = (GameObject)Instantiate(semut[i], posisi[ran], Quaternion.identity);
			
			//make object to child of image target
			mSemut.transform.parent = temp.transform;
			
			// Create a virtual button
			ImageTargetBehaviour itb = GetComponent<ImageTargetBehaviour>();
			VirtualButtonBehaviour vbb = itb.CreateVirtualButton(vbName[i], mSemut.transform.localPosition, mSemut);
			vbb.RegisterEventHandler(this);
			
			i++;
			//set time for loading the object
			waktuCounter = waktu;
		}		
		
		waktuCounter-= Time.deltaTime;
	}

i want to create a virtual button every clone object loaded to schene,
and this is the error:

Assets/Script/manager.cs(40,58): error CS0176: Static member `ImageTargetBehaviour.CreateVirtualButton(string, UnityEngine.Vector2, UnityEngine.GameObject)' cannot be accessed with an instance reference, qualify it with a type name instead

can anyone help me? Thank you.

Re: Virtual Buttons won't work after instantiation?

December 17, 2011 - 8:38am #10

Hi Again,

Thanks for the fast answer Ksiva.

Finally I managed it to solve the problem, it was not a matter of script ordering though.
The problem was with the CreateVirtualButton call. Even after fixing the signature as you specified before, the function always returned an error. I use now the other function signature and then I change the parent of the button manually:

VirtualButtonBehaviour virtualButton = ImageTarget.CreateVirtualButton( buttonName, 
new Vector2(0.0f, 0.0f), 
new Vector2(vbSize, vbSize));

virtualButton.transform.parent = c4;
virtualButton.RegisterEventHandler(eventHandler);

This way it works fine, I hope it's useful for someone.

Infaust.

Re: Virtual Buttons won't work after instantiation?

December 13, 2011 - 8:46pm #9

Note that virtual buttons must have unique names, the Create method will fail if a button with the given name already exists.

It's also possible this is a script ordering issue. If you're creating your button in the Start method I believe you need to make sure that the TrackerBehaviour's Start method has already had a chance to run. In Unity 3.4 you can use the Project Settings > Script Execution Order setting to guarantee the ordering.

- Kim

Re: Virtual Buttons won't work after instantiation?

December 13, 2011 - 8:17am #8

Hi,

I have the same issue with creating virtual buttons at runtime.

I copied exactly the same code that Ksiva posted, getting the ImageTargetBehaviour by passing the ImageTarget to the script.
I fixed the CreateVirtualButton method as well, but I still have the two errors mentioned above:

"Could not register Virtual Button"
obviously followed by:
"NullReferenceException: Object reference not set to an instance of an object"

Following the error, on the ImageTargetBehaviour class, where the first error is launched, I detect that the error is fired because the call: tracker.RegisterVirtualButton(newVBB, this.TrackableName)
returns false.

Someone knows how to solve this problem? I wonder if tominc was finally able to solve it

Thank you very much,
Infaust

Re: Virtual Buttons won't work after instantiation?

November 15, 2011 - 7:50am #7
ImageTargetBehaviour imageTarg = GetComponent<ImageTargetBehaviour>();

This assumes that your vbSpawn script is attached to an ImageTarget (an object with an ImageTargetBehaviour component). Is that the case? If not, you'll want to pass in the ImageTargetBehaviour via a public member variable, or search for it some other way.

Did you open up the ImageTargetBehaviour.cs file and fix the CreateVirtualButton method to take a Vector3 for localScale?

Also, you can get line numbers in the debug log by checking "Development Build" and "Script Debugging" in the Build Settings menu.

- Kim

Re: Virtual Buttons won't work after instantiation?

November 14, 2011 - 6:49am #6

Hey Kim,

My intention is to instantiate an object on constant running timer and give each object its own virtual button. Initially I thought making a prefab with a virtual button pre-attached would work,but for some reason this disables the virtual button completely (plus the duplicate button names is a bit of a kill).

To achieve this I've tried combining my enemy death script with the VB creator, so I can attach a working button to the spawning prefab object. My idea is that when instantiated, the start function will generate and register a button for that object. Here's my code:

 
using UnityEngine;
using System.Collections;

public class vbSpawn : MonoBehaviour, IVirtualButtonEventHandler{

	public GameObject parent;

	// Use this for initialization
	void Start () {

	Vector3 pos = parent.transform.localPosition;
		
ImageTargetBehaviour imageTarg = GetComponent<ImageTargetBehaviour>();
VirtualButtonBehaviour vbb = imageTarg.CreateVirtualButton("buttonName", new Vector3(1.0f, 1.0f, 1.0f), parent);
vbb.RegisterEventHandler(this);
		
	}
	
	
	 public void OnButtonPressed(VirtualButtonBehaviour vb)
    {
        Debug.Log("OnButtonPressed");
        vb.GetImageTarget().DestroyVirtualButton(vb.VirtualButtonName);
        Destroy(this.transform.parent.gameObject);
    }

    public void OnButtonReleased(VirtualButtonBehaviour vb)
    {
        Debug.Log("OnButtonReleased");
    }
	
}

This code runs fine, but doesn't generate a virtual button. When I check the debug log it shows the following error:
"NullReferenceException: Object reference not set to an instance of an object"

This error is apparently linked around these lines:

 
VirtualButtonBehaviour vbb = imageTarg.CreateVirtualButton("buttonName", new Vector3(1.0f, 1.0f, 1.0f), parent);

vbb.RegisterEventHandler(this);
		

Any thoughts on how I could fix this to generate the button this way?

Re: Virtual Buttons won't work after instantiation?

November 12, 2011 - 9:46pm #5

Sorry for the delay. I looked into this and there seems to be a bug with that version of the method. You can either use the other method:

    public VirtualButtonBehaviour CreateVirtualButton(string vbName,
                                                      Vector2 position,
                                                      Vector2 size)

Or fix the existing one by changing the signature:

    public VirtualButtonBehaviour CreateVirtualButton(string vbName,
                                                      Vector3 localScale,
                                                      GameObject immediateParent)

Here's the script I used for testing, in case it's helpful:

using UnityEngine;
using System.Collections;

public class VBCreateTest : MonoBehaviour {

    private int mButtonCounter = 0;

    void Update ()
    {
        if (Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Began)
        {
            Debug.Log("tap!");

            // Assumes this script is attached to the ImageTarget, and that there is an event handler also attached
            ImageTargetBehaviour imageTarget = GetComponent<ImageTargetBehaviour>();
            VirtualButtonEventHandler eventHandler = GetComponent<VirtualButtonEventHandler>();

            // Get touch point on target plane
            Plane targetPlane = new Plane(imageTarget.transform.up, imageTarget.transform.position);
            Ray ray = Camera.main.ScreenPointToRay(Input.touches[0].position);
            float dist = 0.0f;
            targetPlane.Raycast(ray, out dist);
            Vector3 touchPoint = ray.GetPoint(dist);

            // Instantiate a prefab (in this case, a cube) and place above the touch point
            GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            cube.transform.parent = imageTarget.transform;
            cube.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            cube.transform.position = touchPoint;
            cube.transform.localPosition += new Vector3(0.0f, 0.3f, 0.0f);

            // Create a virtual button and register the event handler
            string buttonName = "mybutton" + mButtonCounter;
            VirtualButtonBehaviour virtualButton =
                    imageTarget.CreateVirtualButton(buttonName, new Vector3(1.0f, 1.0f, 1.0f), cube);
            virtualButton.RegisterEventHandler(eventHandler);

            Debug.Log("created button " + buttonName + " with position " + virtualButton.transform.localPosition);

            // Add a mesh representing the virtual button, for debugging purposes
            CreateVBMesh(virtualButton);

            // Increment button counter for unique button names
            mButtonCounter++;
        }
    }

    public static void CreateVBMesh(VirtualButtonBehaviour vb)
    {
        GameObject vbObject = vb.gameObject;

        MeshFilter meshFilter = vbObject.GetComponent<MeshFilter>();
        if (!meshFilter)
        {
            meshFilter = vbObject.AddComponent<MeshFilter>();
        }

        // Setup vertex positions.
        Vector3 p0 = new Vector3(-0.5f, 0, -0.5f);
        Vector3 p1 = new Vector3(-0.5f, 0, 0.5f);
        Vector3 p2 = new Vector3(0.5f, 0, -0.5f);
        Vector3 p3 = new Vector3(0.5f, 0, 0.5f);

        Mesh mesh = new Mesh();
        mesh.vertices = new Vector3[] { p0, p1, p2, p3 };
        mesh.triangles = new int[]  {
                                        0,1,2,
                                        2,1,3
                                    };

        // Add UV coordinates.
        mesh.uv = new Vector2[]{
                new Vector2(0,0),
                new Vector2(1,0),
                new Vector2(0,1),
                new Vector2(1,1)
                };

        // Add empty normals array.
        mesh.normals = new Vector3[mesh.vertices.Length];

        // Automatically calculate normals.
        mesh.RecalculateNormals();
        mesh.name = "VBPlane";

        meshFilter.sharedMesh = mesh;

        MeshRenderer meshRenderer = vbObject.GetComponent<MeshRenderer>();
        if (!meshRenderer)
        {
            meshRenderer = vbObject.AddComponent<MeshRenderer>();
        }
    }
}

- Kim

Re: Virtual Buttons won't work after instantiation?

November 11, 2011 - 10:12am #4

My best guess was to add a seperate script called "vbSpawn" to the object that is being instantiated with the following code:

public class vbSpawn : MonoBehaviour {
	public string vbName = "test";
	public Vector2 localScale;
	public GameObject parent;

	// Use this for initialization
	void Start () {
	
		 ImageTargetBehaviour createScript = GetComponent<ImageTargetBehaviour>();
		 createScript.CreateVirtualButton(vbName, localScale, parent);
	}
	

Issue is that this doesn't actually create a virtual button (or do anything notable). Any ideas how I could implement this correctly?

Re: Virtual Buttons won't work after instantiation?

November 11, 2011 - 3:52am #3

So to clarify - I'm just instantiating the enemy object, without a virtual button pre-attached as a child? Then I create the virtual button that will be childed using the following image target method

public VirtualButtonBehaviour CreateVirtualButton(string vbName,
                                                  Vector2 localScale,
                                                  GameObject immediateParent)

Slightly confused as to how I would go about running this from the instantiation script?

Re: Virtual Buttons won't work after instantiation?

November 10, 2011 - 8:51pm #2

At runtime you have to call the ImageTargetBehaviour's CreateVirtualButton method to create and register the virtual button with the tracker. That will return a VirtualButtonBehaviour. Then you can instantiate your prefab, and make the virtual button a child (or a parent) of it. I don't think you can change the owner of a component once it is created, so you can't attach it directly to your instantiated prefab.

- Kim

Log in or register to post comments