Difficulty enforcing Collisions with Transform Position (.gif included)?

Hey all!

I’m having a difficult time combining collisions with Transform Position-based movement, rather than “normal” movement (like “AddForce()”, for example).

In the picture below, you see a horizontal row of cubes.

  • The player’s view is fixed to what you see here.
  • The red cube is controlled by the player using the left/right arrow keys or the A or D keys.
  • The red cube should only be able to move horizontally within the row.
  • Whenever the key is pressed (GetKeyDown), the cube should “snap” exactly +1 or -1 along the x axis. This is why I’m using Transform Position instead of AddForce.
  • The purple cubes are the barriers that the red cube should be unable to move into/beyond.
  • My red and purple cubes are all Rigidbodies (Use Gravity off) and Box Colliders. Nothing else is.

Currently, my red cube moves exactly how I want it to (demonstrated below), but colliding with a purple cubes sends everything flying (ignore the yellow cube). While oddly satisfying to watch, it’s not what I want. Here’s what that looks like:

4389355--398695--Collision_Demo.gif

I would like for the red cube to simply not move at all upon colliding with either barrier, in addition to a sound effect playing to denote that a barrier has been reached.
Bonus points if you can guide me on the second part, but the first part is the purpose of this post.

Here is my code:

public class testScript : MonoBehaviour
{
    public bool playerInputEnabled;

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

    // Update is called once per frame
    void Update()
    {
        Vector3 position = this.transform.position;

        if (playerInputEnabled == true)
        {
            if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A))
            {
                position.x -= 1;
                this.transform.position = position;
            }
            else if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D))
            {
                position.x += 1;
                this.transform.position = position;
            }
        }
    }
}

Thanks so much to anybody who is able to assist!

Don’t assign the position field like that. Instead use the Rigidbody instance and use .MovePosition().

Using .MovePosition() causes all physics to “happen,” whereas setting transform.position is effectively a teleport as far as the physics is concerned.

1 Like

Do you even need physics in the game? It seems to me you could simply just raycast in the direction of movement and set the position from that.

1 Like

Yeah, based on your description, I would think the easiest approach is to skip the physics entirely and just have your movement code check whether the movement is in-bounds or not.

1 Like

Wow, for some reason I literally never considered just handling this within the code. I feel stupid, haha.
You’re correct that I didn’t need physics at all for this specific function.

For any curious readers, all I did was change my if statements accordingly:

if (playerInputEnabled == true)
        {
            if (position.x >0 && (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A)))
            {
                position.x -= 1;
                this.transform.position = position;
            }
            else if (position.x <10 && (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D)))
            {
                position.x += 1;
                this.transform.position = position;
            }
        }

Thanks so much everyone!

1 Like

This is really the best part of game development, watching the malfunctions. And physics malfunctions can be among the most amusing malfunctions.

Glad you got your problem taken care of just checking coordinates! Always good to keep it simple.

2 Likes