Home>


I'm trying to make something like the following using

unity.
Place two boxes (box, box (1)) on the red table and move them while keeping balance.
The player moves the dish left and right.
In the case of the image, the box is likely to fall to the right, so I want to move the plate to the right and put the top box in a balanced state, with the two on board.
The plate and box are both boxcollider2d and ridibody2d, and the plate is kinematic.
Friction is set to 0.5 for both plates and boxes.

Error message

Even if you move the pan, the box will drop down regardless of the pan movement.
If i don't make the box a child element of the plate, the plate will only move when the plate is moved.
However, if it is a child element, the box will be the relative position of the dish and will collapse regardless of the movement of the dish.
Eventually I would like to make a game that carries a box from the starting point to the goal point while balancing, but if there is any good way, thank you.

The pan moves with the following code.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerManager: MonoBehaviour
{
    Vector3 pos = new Vector3 ();
    float speed;
    // Start is called before the first frame update
    void Start ()
    {
        pos = transform.position;
        speed = 0.1f;
    }
    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKey (KeyCode.RightArrow)) {
            pos.x + = speed;
            transform.position = pos;
        } else if (Input.GetKey (KeyCode.LeftArrow)) {
            pos.x-= speed;
            transform.position = pos;
        }
    }
}
  • Answer # 1

    What about using Rigidbody2D.MovePosition to move it?
    As shown in the reference explanation, this seems to be better for physical interaction.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class PlayerManager: MonoBehaviour
    {
        new Rigidbody2D rigidbody2D;
        Vector2 pos = new Vector2 ();
        float speed;
        // Start is called before the first frame update
        void Start ()
        {
            rigidbody2D = GetComponent();
            pos = transform.position;
            speed = 0.05f;
        }
        void FixedUpdate ()
        {
            if (Input.GetKey (KeyCode.RightArrow)) {
                pos.x + = speed;
                rigidbody2D.MovePosition (pos);
            } else if (Input.GetKey (KeyCode.LeftArrow)) {
                pos.x-= speed;
                rigidbody2D.MovePosition (pos);
            }
        }
    }

    The move processing timing has been changed toFixedUpdateto match the reference recommendations. As a result, the status ofInputis acquired inFixedUpdate. This time there may be no problem with state acquisition methods, but the type of methods that detect state changes such as "~ Up" and "~ Down" may cause input loss or excessive reaction. I think that it is better to useUpdatetogether.

    When you move it with friction 0.9, it looks like the following figure.

    However, this method will reach the top speed in an instant. If acceleration/deceleration is too rapid and difficult to operate, it would be better to change to an AddForce-based movement method.
    Or you can try out GetAxis easily. As you can see in the annotation at the end of the reference, the value obtained by this method changes gently, so I think that the degree of acceleration/deceleration can be relaxed somewhat.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class PlayerManager: MonoBehaviour
    {
        new Rigidbody2D rigidbody2D;
        Vector2 pos = new Vector2 ();
        float speed;
        // Start is called before the first frame update
        void Start ()
        {
            rigidbody2D = GetComponent();
            pos = transform.position;
            speed = 0.05f;
        }
        void FixedUpdate ()
        {
            pos.x + = speed * Input.GetAxis ("Horizontal");
            rigidbody2D.MovePosition (pos);
        }
    }