Moving Platform Script - Easier way to do it?

Hey all,

I don’ write scripts much but gave this a crack to build a moving platform in a 2D platformer. Just wondering if there is a simpler way to do this/if my script can be streamlined at all?

Basically, I’ve got a “Moving Platform” object with the following children: Platform (which has the sprites, colliders, etc), and a number of nodes (4 maximum) which are just empty objects to position around the scene. The platform heads between each node and cycles back to the first, checking how many nodes there are as it goes. At the moment, the script requires additional lines for every additional node. Not sure I’ll ever really need more than four, but wondering if there is a way to automate that element of it? Here’s my C# script:

using UnityEngine;
using System.Collections;

public class MovingPlatformScript : MonoBehaviour {

    public float speed = 5f;
    public float NodesHit = 1f;

    //Setting up the Platform and Nodes
    Transform Node1;
    Transform Node2;
    Transform Node3;
    Transform Node4;
    Transform Platform;

    void Awake () {

        //Find the Platform and Nodes children
        Node1 = transform.Find("Node1");
        Node2 = transform.Find("Node2");
        Node3 = transform.Find("Node3");
        Node4 = transform.Find("Node4");
        Platform = transform.Find("Platform");
    }
   
    void FixedUpdate () {


        //Control the movement of the Platform between nodes
        if (NodesHit == 1f) {
            Platform.position = Vector2.MoveTowards (Platform.position, Node2.position, speed * Time.deltaTime);
        }

        if (NodesHit == 2f) {
            if (Node3 != null) {
                Platform.position = Vector2.MoveTowards (Platform.position, Node3.position, speed * Time.deltaTime);
                }
                else {
                    Platform.position = Vector2.MoveTowards (Platform.position, Node1.position, speed * Time.deltaTime);
                }
            }

        if (NodesHit == 3f) {
            if (Node4 != null) {
                Platform.position = Vector2.MoveTowards (Platform.position, Node4.position, speed * Time.deltaTime);
            } else {
                Platform.position = Vector2.MoveTowards (Platform.position, Node1.position, speed * Time.deltaTime);
            }
        }
        if (NodesHit == 4f) {
            Platform.position = Vector2.MoveTowards (Platform.position, Node1.position, speed * Time.deltaTime);
        }

        //Keep track of the nodes that have been hit
        float Node1Check = Vector2.Distance (Platform.position, Node1.position);

        if (Node1Check <= 1) {
            NodesHit = 1f;
        }

        float Node2Check = Vector2.Distance (Platform.position, Node2.position);

        if (Node2Check <= 1) {
            NodesHit = 2f;
        }

        //Check for additional nodes and continue to count if they exist, otherwise head back to the first node           
        if (Node3 != null) {
            float Node3Check = Vector2.Distance (Platform.position, Node3.position);
            if (Node3Check <= 1) {
                    NodesHit = 3f;
            }
        }
        if (Node4 != null) {
            float Node4Check = Vector2.Distance (Platform.position, Node4.position);
            if (Node4Check <= 1) {
                    NodesHit = 4f;
                }
            }           
    }
}

Yes, just create an array of nodes and loop over them.

You could for example create the nodes as an inspector variable, that way they’re easy to assign and you can have as many or as few as you’d like. public Transform[] nodes

Then you’d need an index variable, so you know which node is next private int index = 0

And the in your update, you use MoveTowards nodes[index] and if the distance to this node is really small, increase index by one, or reset it to 0 if there are no more nodes

index++;
index = index % nodes.Length

You can use a list to store all your nodes then just hold a single id to know which one you are currently travelling to.

I recently dealt with this & here is the code that i wrote to handle it.

You can increment along the path however you want. I have a script below just to follow the path over time

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

public class PathFollower : MonoBehaviour {
    public Transform pathParent;
    List<Transform> pathLocations = new List<Transform>();
    [Range (0.0f, 1.0f)]
    public float startingProgress = 0.5f;
    public bool slerpToLocation = false;
   
    float m_progress;
    float m_fullLength = 0.0f;
    bool m_validPath;
   
    void Awake(){
        if(pathParent){
            for(int i = 0; i < pathParent.childCount; i++){
                pathLocations.Add(pathParent.GetChild(i));
            }
        }

        if(pathLocations.Count > 1){
            m_validPath = true;
            m_progress = startingProgress;
            for(int i = 0; i < pathLocations.Count-1; i++){
                m_fullLength += Vector3.Distance(pathLocations[i].position, pathLocations[i+1].position);
            }
           
            PlaceOnPath(startingProgress);
        }else{
            m_validPath = false;
        }
    }
   
    void PlaceOnPath(float prog){
        if(!m_validPath){
            return;
        }
       
        if(prog <= 0.0f){
            transform.position = pathLocations[0].position;
            return;
        }else if(prog >= 1.0f){
            transform.position = pathLocations[pathLocations.Count-1].position;
            return;
        }
       
        float dist = m_fullLength*prog;
       
        float curDist = 0.0f;
        for(int i = 0; i < pathLocations.Count-1; i++){
            float thisDist = Vector3.Distance(pathLocations[i].position, pathLocations[i+1].position);
            curDist += thisDist;
           
            if(curDist >= dist){
                float segmentProg = (1/thisDist) *  (dist - (curDist - thisDist));

                if(slerpToLocation){
                    Vector3 nextLoc = Vector3.Slerp(pathLocations[i].position, pathLocations[i+1].position, segmentProg);
                    nextLoc.z = transform.position.z;
                    transform.position = nextLoc;
                }else{
                    transform.position = Vector3.Lerp(pathLocations[i].position, pathLocations[i+1].position, segmentProg);
                }
                return;
            }
        }
    }
   
    public void SetProgress(float progress){
        if(progress > 1.0f){
            progress = 1.0f;
        }else if(progress < 0.0f){
            progress = 0.0f;
        }

        m_progress = progress;
        PlaceOnPath(m_progress);
    }
   
    public float GetProgress(){
        return m_progress;
    }
}
using UnityEngine;
using System.Collections;

public class FollowPath : MonoBehaviour {
    public float travelTime = 10.0f;
    public bool reverse = true;

    float m_speed;
    bool m_inReverse;

    PathFollower m_pathScript;
    // Use this for initialization
    void Start () {
        m_pathScript = GetComponent<PathFollower>();
        m_speed = 1.0f/travelTime;
    }
   
    // Update is called once per frame
    void Update () {
        float step = m_pathScript.GetProgress();
        step += m_inReverse ? -m_speed * Time.deltaTime : m_speed * Time.deltaTime;

        m_pathScript.SetProgress(step);

        if(m_pathScript.GetProgress() == 1.0f && reverse){
            m_inReverse = true;
        }else if(m_pathScript.GetProgress() == 0.0f && m_inReverse){
            m_inReverse = false;
        }
    }
}

Thank you, Steego and Lordconstant! Both really helpful comments.