How to teleport the player to the location of an instantiated projectile?

I want the player to be able to fire three slow moving projectiles with the right mouse button and then teleport to them, one after the other (as long as they still exist) using the left mouse button. This is presenting two specific challenges for me. First, I don’t know how to access/store the position of the instantiated projectiles, so that my player can teleport to them.

You’ll see below that I tried using a tag to find the object but I’m very new to Unity and C# and I am having difficulty.

Secondly, I want to have it so that there can be a maximum of three projectiles at any point. Creating a new projectile once there are already three should destroy the oldest and replace it with the new one. The tricky part for me (even the logic) is that if, say the second projectile is prematurely destroyed (by say colliding with an object), how do I maintain the proper order when adding a new one. In other words, I always want to teleport to the oldest projectile.

Eg. I fire all three projectiles. Projectile1 and Projectile3 both still exist but Projectile two was triggered when it collided with an object and destroyed itself. Now I fire another projectile. I need it to be come after Projectile1 and Projectile3 so that they’ll be used first.

After doing some research I’m thinking an array may be the answer but again, I’m just too new to this to know quite how to approach the problem.

using UnityEngine;
using System.Collections;

public class FireSynapse : MonoBehaviour {

	public float cooldown = 1f;

	float cooldownRemaining = 0;

	public GameObject SynapsePrefab;

	//used for initialization

	void Start () {

	}

	//update called once per frame
	void Update () {
		cooldownRemaining -= Time.deltaTime;

		if (Input.GetMouseButtonDown(1) && cooldownRemaining <= 0) {
			cooldownRemaining = cooldown;

			Instantiate(SynapsePrefab, Camera.main.transform.position, Camera.main.transform.rotation);
		}

		if (Input.GetMouseButtonDown (0)) {
			GameObject Portal = GameObject.FindWithTag("Portal");
			Debug.Log (transform.position = new Vector3(SynapsePrefab.transform.position.x, SynapsePrefab.transform.position.y, SynapsePrefab.transform.position.z));
		}
	}
}

Thank you in advance for your help.

PS: I hope that didn’t count as two questions. I apologize if it did and I can re-post that second part of my dilemna elsewhere if need be. Thanks again.

Question 1

Instantiate() actually returns the object that was created. So you can do this:

GameObject newProjectile = (GameObject)Instantiate(SynapsePrefab, Camera.main.transform.position, Camera.main.transform.rotation);

Note that I’ve put “(GameObject)” before “Instantiate”. That’s called “casting”, and you use it when you’re changing something from one type to another (doesn’t work so simply for everything!). We have to do it here because Instantiate returns an “Object” type, and you need to store the result as a GameObject.

Question 2

To answer your second question, yep, you can use an array, but we’re going to make it easier and use a List<>. This is going to get a little bit more involved, so bear with me! You’re going to need:

  1. A list that stores the projectiles
  2. A way to add to it
  3. A way to remove the oldest projectile
  4. A way to move the projectiles down the list

So, two things for 1… Firstly, after “using System.Collections;” add

using System.Collections.Generic;

Then, after where you’ve got “float cooldownRemaining = 0;” add:

private List<GameObject> projectiles = new List<GameObject>();

Now let’s make a way to add stuff to it:

void AddProjectile(GameObject newProjectile){

	//Run through the list and remove any objects that have been destroyed already.
	//You might be better running a master list of projectiles and having the projectile remove itself from the list when it's destroyed, but this will do for now.
	foreach(GameObject projectile in projectiles){
		if (projectile == null){
			projectiles.Remove (projectile);
		}
	}

	//If the list still has the maximum number of projectiles (i.e. none were removed in the last step, destroy the first one and remove it from the list. List<> is cool because it automatically moves the other items down the list!
	if (projectiles.Count == maxProjectiles){
		//I'm just destroying it here, but you might have an explosion animation to run? If so, now would be the time to call it. Let me know if you have trouble with this, and I'll explain briefly.
		Destroy(projectiles[0]);
		projectiles.RemoveAt(0);
	}

	//Now we can add the new one
	projectiles.Add(newProjectile);

}

Finally, after the line where you instantiated the new projectile, add this:

AddProjectile(newProjectile);

Oh, and then you’re want to teleport to them one after the other. I’m not sure how you want that behaviour to work, but you can get to the oldest one like this:

transform.position = projectiles[0].transform.position;

And you’re done!