2D Tap and destroy game

Hi,
I am trying to create a game where a game object is instantiated in 2d space, if clicked, it will change texture, and if not, it will disappear. I have managed to cover most of it but my main issue is the fact that for the period when the game object is visible, I can’t tap it except if I somehow got it at the exact frame it was spawned. Please does anyone have any idea on how I can make the game object “tapable” for the entire time its visible?
A snippet of my code:

#pragma strict
var prefeb : GameObject[];
var Spawnpoint : Transform[];
private var prefeb_num;
private var tele_num;
private var clone : GameObject;
private var timeLimit = 3.5; //accelaration time ie..time before speed increase
private var waitingtime = 1.6; //time before sprite disappears
var tappedSprite : GameObject;//sprite was tapped
var missedSprite : GameObject;//sprite was not tapped
private var tapped = false;// initial
private var elapsedtime : float = 0f;
private var destruction; //check if time to destroy prefab

function Start () {
tele_num = Random.Range(0,10);
prefeb_num = Random.Range(0,5);
clone = Instantiate(prefeb[prefeb_num], Spawnpoint[tele_num].position, Quaternion.identity );
Destroy (clone, waitingtime);
WaitAndDestroy();
while (1) //i'm using a while loop in start instead of an update function as update doesn't do well with delays
{
yield WaitForSeconds(waitingtime);
Spawn();
WaitAndDestroy();
}
}

function Update () {

}

function Spawn() //spawn at one of my spawn points
{
tele_num = Random.Range(0,15);
prefeb_num = Random.Range(0,5);
clone = Instantiate(prefeb[prefeb_num], Spawnpoint[tele_num].position, Quaternion.identity );
Destroy (clone, waitingtime);
//elapsedtime = Time.time + waitingtime;
}

function WaitAndDestroy(){
if(Time.time >= timeLimit)
    {
     // remove 0.18 from the time...
     waitingtime -= 0.1;
     if (waitingtime <= 0.3){
     waitingtime = 0.3;}
     // make it wait another 3.5 seconds...
     timeLimit += 3.5;
    }
    checktap();
    if (tapped) //when tapped
    {
    Destroy (clone); //destroy
    var tappedclone = Instantiate(tappedSprite, Spawnpoint[tele_num].position, Quaternion.identity ); //put the good sign at the same position
    yield WaitForSeconds(0.1); //wait small
    Destroy (tappedclone);//destroy the good sign
    tapped = false;
    }
   
  /*  if (!tapped && destruction ) //no tap + time up
    {
   //yield WaitForSeconds(waitingtime); //wait
   Destroy (clone); //destroy
   var missedclone = Instantiate(missedSprite, Spawnpoint[tele_num].position, Quaternion.identity ); //bad sign instead
   yield WaitForSeconds(0.1); //wait small
   Destroy (missedclone);// destroy
   }
  
   if (!tapped && !destruction ) //no tap + time left
    {
   checktap();
   } */
}

function checktap()
{
if ((GameObject.FindWithTag("Slyer")))
{
if (Input.GetKeyDown ("space"))
{tapped = true;
Destroy (clone); //destroy
var tappedclone = Instantiate(tappedSprite, Spawnpoint[tele_num].position, Quaternion.identity ); //put the good sign at the same position
yield WaitForSeconds(0.1); //wait small
Destroy (tappedclone);//destroy the good sign
}
if (!Input.GetKeyDown ("space"))
tapped = false;
}
}

Thanks for any help :).

Your code seems confusing, I can’t make sense of your logic.

You spawn an object, then destroy it 3 seconds later. Then you wait and destroy, only to spawn it again.

Why use while(1)? While will always run, as 1 can never not be one. Then inside that you ep yield and wait for seconds, to perform waitanddestroy, something you have already called.

Sloppy.

Can you explain better your issue?

How are you running input? As you are saying tap must be precise at some point.

I spawn random objects (tagged “slyers”) at random spawnpoints one at a time. Once spawned, they should last for 3 seconds, if the user hasn’t tapped spacebar, they should disappear and another random object is spawned which also has the same lifespan. If the spacebar is tapped, it should change the game object by destroying it and instantiating another object (not a “slyer” this time) at the exact position the object was. This new object should only be visible for about half a second or so. The issue is that the spacebar tap doesn’t seem to be detected during the lifespan of the object but only at the exact moment its spawned which is almost impossible to catch.

Kind of like a 2d fruit ninja. But instead of the fruits flying up and down, I want each fruit just appear on the screen for a period of time;
If spacebar is tapped within that time period, it should divide.
If its not tapped, it should get rotten.
Then there should be a short wait; then the next fruit should appear and the cycle continues.

So do you have a time frame for when fruit are available to slice? Ex, fruit appear, a random amount, in random positions, they stay there for x time, then are removed, (if they have not been destroyed by the user), then the steps are taken again?

Edit.
If so, and since your problem seems to be that the items can only be tapped at spawn, somehow, your space bar input is losing track of the items.

I would do this, look into…
Pooling, pool instances of the fruit.
List, have two lists, one for active fruit, in scene and inactive out of scene.
Have a manager. This manager will pull inactive fruit from the pool list. Remove any selected fruit, from the inactive list, add to active.
During the window of time when fruit are available, if space bar hit, (here is where you lose me because how do you know which fruit you hit?) but, if space bar pressed, any active fruit, is removed from scene, removed from active list, added to inactive.

It doesn’t matter for now which fruit was hit because I assume they are all just fruits but with different textures. Your method seems reasonable. Please how do I go about implemeting that in code? Thanks for the help :).

Hm
Tricky thing you ask, becuase if your asking you likely have no idea to do something, kind of simple but very fundamental, to most gameplay.

Go over my edited post from above.
You need to look up, pooling, Lists, and input.

//mng
public List<itemScript> items;

void gatherItemsForScene(){
int itemsCount = items.Count;
for (int i = 0; i < itemsCount; i++){
items[i].loadIntoScene();
}
//itemScript
public void loadIntoScene(){
itemsMng.items.Remove(this);
itemsMng.activeItems.Add(this);
// now set pos, renders etc.

What you have done is have a manager run thru all its items in a list and inform each to load into scene. Upon doing so, this item removes itself from the mngs items list and adds itself to an active items list. This is a way to know which items are in scene. Of course if all your items are inScene, each time, then there is no need.

You will then need to monitor input and remove items that are active appropriately. When you remove an item from scene remove it from the acticeItems list and ad it to the idle, items list. Now, this item can be recycled.

1 Like

Thank you so much for the help