Player Not Moving With Platforms

I’m making the player a child of the platform as it moves so that the player is moved along with the platform.

Here is my script:

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

public class ObjectMove : MonoBehaviour
{
    public float speed;

    public bool playerOnBoard;

    // Start is called before the first frame update
    void Start()
    {
        playerOnBoard = false;
    }

    // Update is called once per frame
    void Update()
    {
        if (playerOnBoard)
        {
            MovePlatform();
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        playerOnBoard = true;
        other.transform.SetParent(transform);
    }

    private void OnTriggerExit(Collider other)
    {
        playerOnBoard = false;
        other.transform.SetParent(null);
    }

    void MovePlatform()
    {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }
}

The result I’m getting is my player is still sliding off, and when I move the mouse it stretches the player out. In the inspector, I’m manipulating its rotation and doing this. In the hierarchy, my player is being added as a child of the platform, and removed from being a child when I jump (or slide) off.

My goal is to just jump on the platform and be carried along while still maintaining control of my character.

Edit: I want to add that I now remember I scripted my mouse to be the player’s rotation. This explains the stretching when the player is a child of the platform. I still do not see why my player continues to fall off the platform.

Edit 2:

This gave me the behavior I was looking for, but my player still stretches out. I’m not sure how to fix that?

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

public class ObjectMove : MonoBehaviour
{
    public float speed;

    public bool playerOnBoard;

    public GameObject player;

    // Start is called before the first frame update
    void Start()
    {
        playerOnBoard = false;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        MovePlatform();
    }

    private void OnTriggerEnter(Collider other)
    {
        playerOnBoard = true;
    }

    private void OnTriggerExit(Collider other)
    {
        playerOnBoard = false;
        other.transform.SetParent(null);
    }

    void MovePlatform()
    {
        if (playerOnBoard)
        {
            transform.Translate(Vector3.forward * speed * Time.deltaTime);
            player.transform.SetParent(transform);
        }      
    }
}

How are you moving the player? Via transforms, or rigidbodies? That dictates the method you use to make the player follow moving objects.

For example the above code won’t work if you’re using physics.

Here’s a very basic script for a character controller that doesn’t need to make itself a child of a platform. It works by moving itself and the platform in a given direction. The platform can be just a basic gameobject with a collider.

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

public class Platformer : MonoBehaviour
{
    CharacterController cc;

    Vector3 playerVelocity;
    Vector3 platformVelocity;
    public float friction=0.9f;

    void Start()
    {
        cc=GetComponent<CharacterController>();
    }

    void Update()
    {
        // Move the player around:
        Vector3 moveDirection=new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
        playerVelocity+=moveDirection;
        if (cc.isGrounded==false)
            playerVelocity.y-=7;    // gravity
        playerVelocity*=friction;   // basic friction
        cc.Move(playerVelocity*Time.deltaTime);
    }

    void OnControllerColliderHit(ControllerColliderHit hit)
    {  
        if (hit.gameObject.tag=="Platform")
        {
            Vector3 platformDirection=Vector3.right*0.2f; // direction and speed that the platform moves in when touched
            platformVelocity+=platformDirection;
            playerVelocity+=platformDirection; // We also want to move the player with the platform 
            if (platformVelocity.y>0.001f) // Is this a rising platform?
              playerVelocity+=Random.insideUnitSphere*0.2f;  // slightly jiggle the player's character controller to prevent it from going crazy (crap physics)
            platformVelocity*=friction;
            hit.transform.position+=platformVelocity*Time.deltaTime; // move the platform
        }
    }
}

I really appreciate that. I’m not at my computer at the moment; wouldn’t placing the code in FixedUpdate() take care of the craziness you mentioned? You may not need to juggle the controller.

FixedUpdate is for physics. Are you using physics?

ok. I would suggest using a Rigidbody. if you don’t like the acceleration of Rigidbody.AddForce(vector3) (like me), then (if your using unity 3d) then set the x and z of Rigidbody.velocity this way you can set add to velocity in lateupdate

I found a great way to do it, but you cannot use the CharacterController component.

Use the animation tab, and set up key frames at the different positions of the platform; mine is just going back and forth, so I made two and then copy and pasted the first one as the third one.

Now, I can just use:

private void OnTriggerEnter(Collider other)
    {
        playerOnBoard = true;
        player.transform.parent = transform;
    }

    private void OnTriggerExit(Collider other)
    {
        playerOnBoard = false;
        player.transform.parent = null;
    }

This sets the player as a child of the platform; it works wonderfully, but you cannot use the character controller; it will cause the player to slide off every time. I’m not sure why, but it doesn’t work at all.

Use a solution like this:

// this function has to be called in Update().
        protected void MovingPlatformSupport()
        {
            //_groundedTarget is the transform the player stands onto. this variable should be initialized by your grounded check sphere/raycast.
            //_groundedTargetLastPosition has to be initialized whenever your _groundedTarget value changes.
            // for example something like this:
            //if(Physics.SphereCast(...))
            //{
            //  if (hit.transform != m_groundedTarget)
            //  {
            //      _groundedTarget = hit.transform;
            //      _groundedTargetLastPosition = m_groundedTarget.position;
            //  }
            //}
            //{
            //  _groundedTarget = null;
            //}

            if (_groundedTarget != null)
            {
                Vector3 offsetVec = _groundedTarget.position - _groundedTargetLastPosition;

                if (offsetVec.magnitude > 0.005f)
                {
                    _controller.Move(offsetVec);
                    _groundedTargetLastPosition = _groundedTarget.position;

                    // if you are using iStep, tell iStep about the moving platform movement, otherwise uncomment the below line of code
                    _iStepFootIK.characterExternalMovingPlatformOffsetVec += offsetVec;
                }
            }
        }

hi, I see you are still having trouble. here’s my script for the player:

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

public class PlayerScript : MonoBehaviour
{
    Vector3 force;
    public Rigidbody rb;

    public float mouseSensitivity = 1000f;
    public Transform playerCamera;

    public float playerSpeed = 7f;
    private float playerSpeedNormal;
    public float slowDownMultiplier = 30f;
    public float speedAtRunMultiplier = 2.5f;
    public float jumpSpeed;
    private bool onBoard;
    private Transform onBoardTransform;
    private Vector3 lastobPos;

    private Vector3 addToForce;
    private bool onGround;
   
    void Start()
    {
        playerSpeedNormal = playerSpeed;
        Cursor.visible = true;
    }

    void Update()
    {
        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
        {
            playerSpeed += ((playerSpeedNormal*speedAtRunMultiplier)-playerSpeed)/slowDownMultiplier;
        }
        else
        {
            playerSpeed += (playerSpeedNormal-playerSpeed)/slowDownMultiplier;
        }

        LookAround(mouseSensitivity);
        if (onBoard)
        {
            TrackOnBoard();
        }
        Movement();
    }
    void LookAround(float sensitivity)
    {
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        mouseY = Mathf.Clamp(mouseY, -90f,90f);

        playerCamera.eulerAngles -= new Vector3(mouseY,0,0);

        transform.eulerAngles += new Vector3(0,mouseX,0);
    }

    void Movement()
    {
        float horizontal = Input.GetAxis("Horizontal")*playerSpeed;
        float vertical = Input.GetAxis("Vertical")*playerSpeed;

        if (Input.GetButtonDown("Jump") && onGround)
        {
            rb.AddForce(new Vector3(0,jumpSpeed,0));
        }

        force = ((transform.right * horizontal) + (transform.forward * vertical));
        force.y = rb.velocity.y;
        rb.velocity = force;
        transform.position += addToForce;
    }

    void TrackOnBoard()
    {
        addToForce = onBoardTransform.position - lastobPos ;
        lastobPos = onBoardTransform.position;
    }

    void OnCollisionEnter(Collision other)
    {
        Ray ray = new Ray(transform.position, Vector3.down);
        Physics.Raycast(ray, out RaycastHit hitInfo);
        if (hitInfo.transform != null)
        {
            if (hitInfo.distance > 0.9f)
            {
                onGround = true;
            }
            else
            {
                Debug.Log("NOT ON GROUND: " + hitInfo.distance);
            }
        }

        if (other.transform.TryGetComponent<IMove>(out IMove i))
        {
            onBoard = true;
            onBoardTransform = other.transform;
            lastobPos = onBoardTransform.position;
            Debug.Log("IS A MOVING OBJECT");
        }
        else
        {
            Debug.Log("NOT A MOVING OBJECT");
            onBoard = false;
        }
    }

    void OnCollisionExit(Collision other)
    {
        onGround = false;
        onBoard = false;
        addToForce = Vector3.zero;
    }
}

my hierarchy looks like this:
9132877--1268044--upload_2023-7-8_15-37-13.png
platform has a script called “IMove” which looks like this:

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

public class IMove : MonoBehaviour
{
//ye I move
}

just make sure to not set the “isTrigger” option on any colliders, and everything should work