0
\$\begingroup\$

I want to get this thing working: I have a prefab with coins, some obstacles and enemies, and i want it to be instantiated each time the player got to the right or left on the stage, to make the stage kinda loop. Then, if the player get a coin in this prefab, this coin will not exist in any other prefab, so if the player goes back to his original place, this coin wouldn't be duplicated(because the idea is a loop)

And it can't delete from the original prefab, because then if we start the game again it'll not have the coins anymore.

Exactly like this: https://www.youtube.com/watch?v=ETxoUDWCBvE

As you can see, when the blue bird gets the other birds, the yellow bird it isn't there anymore if you go back, because the stage kinda loops, and i want to do that.

How enemies would work? Or there's another way of doing this?

\$\endgroup\$
0
\$\begingroup\$

(Two ideas here. See bottom for the "simpler" one.)

Answering exact question:

(Instantiate each time the player reaches right/left edge)

Assuming your stages are of similar complexity to those in the video you linked, you can simply give unique GameObject tags to each of the dynamic (can be destroyed/deleted) children in the prefab.

Then have a global StageManager object/script used to keep track of changes, perhaps a dictionary mapping from tag to state.

With that in place, next have the code that instantiates the stage prefab recurse down the object's tree. Get each child object's tag and ask the StageManager about the state of that tag. Register, ignore, or kill the child object depending on the StageManager's response.

Maybe try something like so (warning: have not compiled or tested this):

public void instantiateStagePrefab(GameObject stageObjPrefab)
{
  GameObject stageObj = GameObject.Instantiate(stageObjPrefab) as GameObject;
  for( int i=0; i<stageObj.transform.childCount; i++ )
  {
    registerOrKill( stageObj.transform.GetChild(i) );
  }
}

private void registerOrKill(GameObject childObject)
{
  StageManager.instance.ensureRegistered(childObject.tag);
  if( !StageManager.instance.getState(childObject.tag) )
  {
    GameObject.Destroy(childObject);
  }
  else
  {
    for( int i=0; i<childObject.transform.childCount; i++ )
    {
      registerOrKill( childObject.transform.GetChild(i) );
    }
  }
}

Then in StageManager, have:

... (Singleton stuff) ...
private Dictionary<string,bool> tagStates = new Dictionary<string,bool>();
...
public void ensureRegistered(GameObject tagObj)
{
  if(! tagStates.ContainsKey(tagObj.tag))
  {
    tagStates[tagObj.tag] = true;
  }
}

public bool getState( string tag )
{
  bool state = true;
  if( tagStates.TryGetValue(tag, out state) )
  {
    return state;
  }
  return true; // if it's uninitialized, it's active by default.
}

public bool setState( string tag, bool newState )
{
  tagStates[tag] = newState; // overwrite old value or add as new entry
}

Finally, have your "collected coin!" code:

  1. Call setState with the coin's tag and newState=false.
  2. Use GameObject.FindGameObjectsWithTag(tag) to locate all of the already-instantiated objects with that tag. Then GameObject.Destroy() those.

With this bookkeeping code, any new instantiations of the prefab should be free of any objects you've already deemed 'dead'. This applies to enemies, collectibles, platforms, etc. Really, anything you want to give a tag (again: critical that the tags are unique!).


Simpler answer in the same spirit:

I think it's possible to just instantiate the prefab 2 or 3 times, side-by-side. Then just move the player and camera "back" a screen when the player nears the edge.

In order for this to look smooth, you'll need to make sure all the animated objects are animated identically (same position, same frame, etc.) or there will be visual artifacts when you shift the player and camera.

You'll still benefit from the 'tag' approach here. E.g. when a coin is collected, the other 1-2 coins with tag "Coin26" can be found by tag and deleted.

This approach takes a lot less bookkeeping, but will also be a lot nicer on whatever machine you're running this on. Instantiating a large "stage" prefab regularly might cause hiccups in rendering/responsiveness, no fun.

No code suggestions here - just move the camera and player left or right by the width of the stage prefab. Should be imperceptible.

Ugly graphical representation!

Hope all this helps!

\$\endgroup\$
  • \$\begingroup\$ I think the first option is what it will work, but now i gotta work to make it work(lol that sentence). I'm still newbie, so i have a lot to study from your code and understand, but i was thinking. There's a IA enemy that comes after the player, then if we get some coin in the B instation, it deletes on the A. But, if you're in the middle of both instatiations, and theres a enemy following you, and it is behind you. When you go to second instatiation, you should see it's butt going after you, but if we instatiate other prefab, it'll generate another enemy following you from other position \$\endgroup\$ – AdowTatep Apr 8 '15 at 3:22
  • \$\begingroup\$ Yes - whatever you implement to make an enemy follow you will need to inform every instance of the same thing. When you decide an enemy is going to follow the player and give it some behavior, with bit of cleverness, you can copy that same behavior for all of the enemies with the same tag. No matter which approach you take, you'll need to copy the behavior out to every instance - GameObject.FindGameObjectsWithTag can make that painless. \$\endgroup\$ – Chris Mills-Price Apr 8 '15 at 6:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.