noob question: How to activate a sphere object when I tap on a cube object?

I want to have a sphere object named “menu” activate to “true” when I tap on a cube object that is named “unit”. Here is my code, but it doesn’t work. Any help would be greatly appreciated.

void Update () {
if (Input.touchCount > 0) {
if (Input.GetTouch (0).phase == TouchPhase.Ended) {

gameObject.SetActive (true);

}

}

This is the script attached to the “unit” cube object? gameObject.SetActive() will try to set the CURRENT GameObject as active, which makes no sense as, if it weren’t active, the script wouldn’t be running in the first place.

You need to place the script on the “unit” cube object with a reference to the sphere object as a public GameObject reference (called “sphereObject” maybe). Then, in the inspector, drag the sphere over to that new member. In your script, you’ll then call “sphereObject.SetActive(true)” when the tap occurs. The “unit” cube object would need to be active right from the beginning.

1 Like

Omg! you are a great teacher! I got it to work. Except it is activating with me just touching the screen. I need it to activate when just touching the cube. I put the script on the cube. Why is it activating when I just touch the screen anywhere?

public GameObject SphereObject;

void Update () {
if (Input.touchCount > 0) {
if (Input.GetTouch (0).phase == TouchPhase.Ended) {

SphereObject.SetActive (true);

}

}
}

There’s no code in there that checks what’s being pressed- just “if there’s one or more fingers on the screen” followed by “if the first finger was just removed from the screen”.

If you’re wanting to tell what’s being pressed, you’ll need to do a raycast from the point where the finger is pressing on the screen, straight out from the camera into world space. Then you’ll need to check the objects that are “hit” and figure out if one of them is the cube, and if it is, then run the function. You don’t actually have to run any of this from the cube object though- traditionally you’ll have one empty GameObject that you’ll put an InputManager script on which controls all of the various inputs (or at least, in this case, the touchscreen inputs).

I recommend doing some research on Raycasts if you aren’t familiar with them, as that’ll be your next step.

1 Like

As an example (because I’m bored):

public GameObject SphereObject;

void Update ()
{
    if (Input.touchCount > 0)
    {
        if (Input.GetTouch (0).phase == TouchPhase.Ended)
        {
            RaycastHit hit;
            Vector3 touchPoint = new Vector3(Input.GetTouch(0).position);
            Ray ray = Camera.main.ScreenPointToRay(touchPoint);
            if(Physics.Raycast(ray, out hit, Mathf.Infinity) && hit.collider.gameObject == gameObject)
            {
                SphereObject.SetActive (true);
            }
        }
    }
}

Note: not tested.

1 Like

You are awesome. I’m messing around with raycasts, but am wondering if there is a better way to accomplish my end goal.

I want to have multiple spheres on the plain. Then I want to touch my finger to the screen and drag it over all the spheres to ‘collect’ them and put them in a group. Should I use trigger or collider for this? It seems like raycast is great for one target location, but when dragging your finger to get many targets, then raycast might not be the best option. What do you think? Thanks for the help by the way!

I still think raycasts would probably be the best bet, because even if you consider the situation in which all of the spheres are on flat surface (that surface could be the ground, or it could a wall they’re “stuck” to like flies, w/e), the only alternative to raycasting would be to mathematically calculate whether any of the sphere’s colliders (or meshes, or w/e) are within a set radius of the point where a line drawn out from the camera in a straight line where you “press” on the screen intersects the plane that all of the spheres are stuck to. And that’s almost exactly what raycasting already is, except without all of the gritty details exposed (and I’m obviously simplifying it a bit).

You can speed up the processing of using repeated raycast calls by setting a lower maximum distance (enough that you’ll realistically hit whatever you need, times two or even ten- for safety) and also by setting up the process of “while pressing down on the screen” as a coroutine that’s started when the press first occurs and ends when the press ends. That way, you can do something like this:

while(true)
{
    return yield new WaitForSeconds(.2f);
    //raycast
}

and the raycasts will only occur five times a second, rather than every frame or multiple times per frame. That should eliminate most performance issues related to this process.

I completely forgot to mention- you should be doing this from some sort of manager script if you have multiple spheres (not from a script attached to the spheres themselves). The code is mostly identical in that case, except:

  • you’ll most likely want the raycast to be layer-specific to the “spheres” layer, or w/e, so the ray will go through other object types or terrain to find any spheres hiding behind them (if that’s even possible)
  • you’ll want to remove the hit.collider check, or change it to be for a name or tag instead of just comparing it to the current GameObject (because the current GameObject will be the manager, not a sphere)
  • you’ll want to immediately change the layer of any “captured” spheres to be something different so that the raycasts will go through them while they’re stuck under your finger (if I understood your intentions correctly), and then change them back when they’re released back to the wild (assuming that’s a part of it)

Just some thoughts to keep in mind. Have fun!

Thats a good idea. I’m going to try that. I was worried raycasting constantly would be expensive, but putting a delay on them is a great idea.

When I was messing around with your code, it didn’t like it initally. I had to put the input.touch(0).position directly into the Ray variable like below:

Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);

instead of what you had:

Vector3 touchPoint = new Vector3(Input.GetTouch(0).position);
Ray ray = Camera.main.ScreenPointToRay(touchPoint);

There error it gave me was:

error CS1729: The type UnityEngine.Vector3' does not contain a constructor that takes 1’ arguments

Do you know why? Thanks again! You have been more helpful than any tutorial I’ve come across so far.

Oh, because it’s trying to use a Vector2 to create a new Vector3- simply change it to new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 0f);