How to Instantiate an object onto a path in Unity

606 views Asked by At

I am recently new to c# and I need some help.

Essentially I have two scripts, one for spawning objects and one for moving an object along a path. I need a way to combine these two mechanics so that when a new object is instantiated it automatically joins the path and follows it.

The path is made using iTween. ![The objects the scripts are attached to] (https://i.stack.imgur.com/QPQn2.png)

I've tried changing the variable m_PlayerObj to the cube prefab and I've tried adding the Path script to the instantiation script but nothing seems to work.

The scripts attached do nkt include these attempts I made as I wanted to make the code very clear.

Spawner script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnerScript : MonoBehaviour
{
    public GameObject cubeprefab;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
             Instantiate(cubeprefab, transform.position, Quaternion.identity);

        }
    }
}

Path script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Path : MonoBehaviour
{
    public GameObject m_PlayerObj;
    public Transform[] positionPoint;
    [Range(0, 1)]
    public float value;
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log(iTween.PathLength(positionPoint));
    }
    float tempTime;
    // Update is called once per frame
    void Update()
    {
        if (value < 1)
        {
            value += Time.deltaTime / 10;
        }
        iTween.PutOnPath(m_PlayerObj, positionPoint, value);
    }

    private void OnDrawGizmos()
    {
    iTween.DrawPath(positionPoint,Color.green);
    }
}

As stated above, any help would be greatly appreciated as I am really stuck on this conceot and since I am new to Unity I really can’t see a way around it // how to fix it.

1

There are 1 answers

6
Joseph On

Instead of only storing the player object in the Path script, store a collection of objects. That way, the path can keep track of more than one object.

    //public GameObject m_PlayerObj;    // Get rid of this
    public List<GameObject> followers;  // Add this

Then, in your Update loop, you can loop through all of them.

    void Update()
    {
        for (var i = 0; i < followers.Length; ++i)
        {
            if (value < 1)
            {
                value += Time.deltaTime / 10;
            }
            iTween.PutOnPath(m_PlayerObj, positionPoint, value);
        }
    }

Of course, now, you need to make sure you pass your cube instance to the Path GameObject when you spawn it, so the path knows about the cube follower. That means your spawner also needs to know about the path.

public class SpawnerScript : MonoBehaviour
{
    public GameObject cubeprefab;
    public Path path;   // Need to populate this in the Editor, or fetch it during Awake()

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var cubeInst = Instantiate(cubeprefab, transform.position, Quaternion.identity);
            path.followers.Add(cubeInst);
        }
    }
}

Now a new problem is going to be that each object is going to be at the same position on the path, because the path only stores one value - a better term might be progress. So if they're all the same, like the cube, you won't be able to tell because they'd overlap.

So you have to decide what you want to do instead. Evenly space them? You could do that with some math. Or have them all start from the beginning and keep track of their progress separately? Then you'd need to store progress for each of them. A better place to do that is probably on the cube object, which means you need to add a new script to your cube prefab:

public class PathFollower : MonoBehaviour
{
    [Range(0, 1)]
    public float pathProgress;
}

And, you need to start referring to the prefab by this script, instead of just GameObject:

public class SpawnerScript : MonoBehaviour
{
    public PathFollower pathFollower;
    public Path path;   // Need to populate this in the Editor, or fetch it during Awake()

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var followerInst = Instantiate(pathFollower, transform.position, Quaternion.identity);
            path.followers.Add(followerInst);
        }
    }
}
public class Path : MonoBehaviour
{
    //public GameObject m_PlayerObj;    // Get rid of this
    public List<PathFollower> followers;  // Add this
//...

Finally, you need to make sure to use the individual progress for each path follower, rather than a single progress value like your old Path script did:

        for (var i = 0; i < followers.Count; ++i)
        {
            if (followers[i].pathProgress < 1)
            {
                followers[i].pathProgress += Time.deltaTime / 10;
            }
            iTween.PutOnPath(followers[i].gameObject, positionPoint, followers[i].pathProgress);
        }

Putting it all together (separate files of course, with their own includes!):

public class SpawnerScript : MonoBehaviour
{
    public PathFollower pathFollower;
    public Path path;   // Need to populate this in the Editor, or fetch it during Awake()

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var followerInst = Instantiate(pathFollower, transform.position, Quaternion.identity);
            path.followers.Add(followerInst);
        }
    }
}

public class Path : MonoBehaviour
{
    //public GameObject m_PlayerObj;    // Get rid of this
    public List<PathFollower> followers;  // Add this
    public Transform[] positionPoint;
    //[Range(0, 1)]
    //public float value;  // Don't need this anymore either

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log(iTween.PathLength(positionPoint));
    }

    // Update is called once per frame
    void Update()
    {
        for (var i = 0; i < followers.Count; ++i)
        {
            if (followers[i].pathProgress < 1)
            {
                followers[i].pathProgress += Time.deltaTime / 10;
            }
            iTween.PutOnPath(followers[i].gameObject, positionPoint, followers[i].pathProgress);
        }
    }

    private void OnDrawGizmos()
    {
        iTween.DrawPath(positionPoint,Color.green);
    }
}

public class PathFollower : MonoBehaviour
{
    [Range(0, 1)]
    public float pathProgress;
}