0
\$\begingroup\$

I'm making a platformer with Unity. In one of the scenes, I have a moving platform that moves back and forth. The problem is that the player can't walk (or sometimes jump) properly on the platform and it seems like a force or collider makes it cling to the ground. This effect is visible in the gif. I think this is because of the fact that the player becomes a child of the object (otherwise it will fall behind while the platform is moving). Is there a way to fix this?

Moving Platform code:

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

public class MovingPlatform : MonoBehaviour
{
    public GameObject platform;
    public float moveSpeed;
    public Transform currentPoint;
    public Transform[] points;
    public int pointSelection;

    private void Start()
    {
        currentPoint = points[pointSelection];
    }

    private void Update()
    {
        platform.transform.position = Vector3.MoveTowards(platform.transform.position, currentPoint.position, Time.deltaTime * moveSpeed);

        if(platform.transform.position == currentPoint.position)
        {
            pointSelection++;

            if(pointSelection == points.Length)
            {
                pointSelection = 0;
            }

            currentPoint = points[pointSelection];
        }
    }
}

enter image description here

The second gif is for after using the new code. Here, the player is moving but even when it is in idle mode, it will fall behind. enter image description here

Note: Moving platform script is on an empty game object (on default layer) and that object has three children: the platform that has sprite renderer and box collider and start point and end point which have only a transform component.


Edit: Code after reading the answer by Philipp:

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

public class MovingPlatform : MonoBehaviour
{
    public GameObject platform;
    public float moveSpeed;
    public Transform currentPoint;
    public Transform[] points;
    public int pointSelection;
    
    private Vector2 velocity;
    private Rigidbody2D rb2D;

    void Awake()
    {
        rb2D = gameObject.AddComponent<Rigidbody2D>();
    }

    private void Start()
    {
        currentPoint = points[pointSelection];
        velocity = new Vector2(1.75f, 1.1f); // This
    }

    private void Update()
    {
        //platform.transform.position = Vector3.MoveTowards(platform.transform.position, currentPoint.position, Time.deltaTime * moveSpeed);

        if(platform.transform.position == currentPoint.position)
        {
            pointSelection++;

            if(pointSelection == points.Length)
            {
                pointSelection = 0;
            }

            currentPoint = points[pointSelection];
        }
    }

    void FixedUpdate()
    {
        rb2D.MovePosition(rb2D.position + velocity * Time.fixedDeltaTime);
    }
}
\$\endgroup\$
5
  • \$\begingroup\$ How did you implement the movement of the player-character? Does the platform have a rigidbody? \$\endgroup\$
    – Philipp
    Jun 15 '21 at 8:45
  • \$\begingroup\$ Player has a Rigidbody 2D component. The platform didn't have a rigidbody but I added one to it (to the platform child not the parent which has the script). I also had a question. Do I need to check "Use Full Kinematic Contacts" checkbox in the inspector? \$\endgroup\$
    – Ali
    Jun 15 '21 at 13:15
  • \$\begingroup\$ OK, but how did you implement the movement of the player using a rigidbody? There are several ways to do that. Changing the transform.position, changing the rigidbody.position, rigidbody.MovePosition, rigidbody.velocity, rigidbody.AddForce... that are those I can think of immediately, but there might be a couple more. \$\endgroup\$
    – Philipp
    Jun 15 '21 at 14:47
  • \$\begingroup\$ Player inherits from a script called Physics Object which is a little complicated and long script. But in general it uses velocity, velocity.x and Physics2D.gravity. Not sure if this is related to rigidbody.velocity or not. \$\endgroup\$
    – Ali
    Jun 15 '21 at 15:36
  • \$\begingroup\$ when your player touches the moving platform you can make your player child of the platform and detach ot when plauer plauer not touching. \$\endgroup\$ Jun 16 '21 at 10:44
1
\$\begingroup\$

When you want to have a moving collider in your game which interacts with rigidbodies in the way you would expect it to, then that collider needs a Rigidbody too. When you want to take complete control of its movement, like you would do with a platform moving along a fixed path, then mark that rigidbody as "Kinematic". That way its movement is unaffected by gravity or collisions.

When you control an object with a rigidbody using a script, then you should avoid moving it through the transform. Move it through the Rigidbody/Rigidbody2D component, for example with MovePosition or velocity.

\$\endgroup\$
5
  • \$\begingroup\$ Thank you for your answer. I added the rigid body and used the MovePosition document you provided to write the code. Now, I just need to change velocity = new Vector2(1.75f, 1.1f); to something else because it changes the platform's position. What do you recommend instead of this? \$\endgroup\$
    – Ali
    Jun 15 '21 at 11:18
  • \$\begingroup\$ I also updated the code, so you can see if there are any problems or errors. \$\endgroup\$
    – Ali
    Jun 15 '21 at 13:10
  • \$\begingroup\$ @Ali I would not advise you to add a Rigidbody2D using code. Add it to the game object / prefab for the moving platform using the editor instead. Also make sure that you set "Body Type" to "Kinematic". It is the first option in the inspector. Or if you really want to do this in code: rb2D.bodyType = RigidbodyType2D.Kinematic. \$\endgroup\$
    – Philipp
    Jun 15 '21 at 14:44
  • \$\begingroup\$ @Ali Regarding your inquiry about the velocity vector you added: What exactly is wrong about it? Didn't this solve the problem? If not, did it somehow change the way the problem manifests? Any other reason why you aren't satisfied with it? \$\endgroup\$
    – Philipp
    Jun 15 '21 at 14:53
  • \$\begingroup\$ I added a gif that shows the problem. The player can't stay on the platform and seems like that force is still there. Also about the velocity, as you can see in the video, the direction of the platform has changed even though the points are in different positions. I think this is because of that velocity part which has two positions. After commenting rb2d add component, I get a Null Reference error in Fixed Update and the platform can't move anymore. I also tried using rb2D.bodyType = RigidbodyType2D.Kinematic instead of the commented line in Awake() but that didn't make any changes. \$\endgroup\$
    – Ali
    Jun 15 '21 at 16:21
0
\$\begingroup\$

One way to handle this is to parent your player to the moving platform while he is on it and remove the parent when he is off of it. This is a script I use on my moving platforms to prevent the weird behavior you are seeing.

private void OnTriggerEnter(Collider other)
{
    if (!other.CompareTag("Player")) return;

    other.transform.parent = transform;
}

private void OnTriggerExit(Collider other)
{
    if (!other.CompareTag("Player")) return;
    
    other.transform.parent = null;
}

This small script along with the code for the movement of the platform is included on the MovingPlatform's script.

\$\endgroup\$
5
  • \$\begingroup\$ Thanks for the answer. Unfortunately, I can't test the code to see if it's working because the platform can't move anymore as I mentioned in the last comment. I get a Null Reference error on rb2D.MovePosition(rb2D.position + velocity * Time.fixedDeltaTime); line. Any suggestions on how can I solve this? \$\endgroup\$
    – Ali
    Jun 25 '21 at 3:14
  • \$\begingroup\$ Not sure what it might be looking at your code. Here is a moving platform class I use that seems to work OK. My _wayPoints appear to do what your points does github.com/Valdarix/2.5DCertificationProject/blob/master/Assets/… \$\endgroup\$
    – James West
    Jun 25 '21 at 13:54
  • \$\begingroup\$ Thanks. I tried the code but I realized that the player won't become the parent of the platform and falls behind. Also, what is the significance of holdTime? \$\endgroup\$
    – Ali
    Jun 27 '21 at 1:29
  • \$\begingroup\$ So the player should become the child of the platform and not the parent. For this, to work the player needs to have a tag of "Player" and the platform has two colliders, the first is the non-trigger collider, the second is the trigger collider that sets just above the surface of the platform. Also, the player is using the Unity Character Controller component. The hold time variable is to control how long the moving platform stays at a given location before moving again. You can see this in action valdarixgames.itch.io/25-d-certification-demo the elevator at the end uses this script. \$\endgroup\$
    – James West
    Jun 28 '21 at 17:14
  • \$\begingroup\$ Okay, so this is all I got so far. First, the player has a tag of "Player". Second, I added another collider to the platform which is the trigger collider and set it to above the platform. I should mention that the two colliders are on the child of the platform which is the graphic. Should I move them to the parent? The parent also has a rb2d component. Third, I tried adding Character Controller component but it says that it cannot be added because it conflicts with Box Collider 2D. \$\endgroup\$
    – Ali
    Jun 29 '21 at 15:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .