0
\$\begingroup\$

i am a student in austria. I am working on a project for school, where we have to make our own first game with unity. Because it is the first time using unity, i constantly run against problems. Most of them, i fixed already. But this problem got me stuck for a few days now. I am very sorry, that i used that many pictures. Maybe in the picture there is some information i did not give you. The name of the collision map is "FirstLayer_Col"

enter image description here

This is what i have got so far. My map is pretty big. I used the tile palette, to paint them in. I also used different types of layers. The ground layer is mostly gras or water. On top of that, i put the trees on, which are seen in the next picture. I created a new tilemap to make it a collision tilemap. I took a random tile and put it on everything i want to have a collision on.

enter image description here

I changed to order of layer to 10 for the collision tilemap, so i could see where i have to put the tile to stop the player from, so he cant walk over or through it. After i put the tile on my wanted location, i changed the order of layer back to 0 so i couldnt see it anymore. I dont know if that is a problem or not. I have not found any other solution that worked for me. The collision tilemap has a tilemap collider and the player named "South_0" ,because of the sprite i used for it, has a box collider and a rigidbody. Every collider is a 2D one. enter image description here

After i start the application with the collision layer on 10. I can go through it, stand on the place, where the collision should be as there is no collision. When i change the order of layer to 0, so it is not visible, i can walk to the tree, but then my game starts to shake and the player rotates. Then there is some type of collision, but when i try to go through it, my game starts to shake very strong and then my player can stand in the middle of the tree as there is not any collision. It looks very "buggy" and the player rotates in any direction. I can not figure out, how i can make the collision to stop the player from entering the field of my tilemap collision without making the player go crazy and make the whole screen shake. I just want the player to stop in front of it, so that there is no way of bugging through it. I hope i explained my problem so you can understand it. Maybe it is just a small, little fix, but i could not find any solution. The last picture is how my player looks after i ran up against the tree with the collision map on layer 0. The player should not rotate and just go, up, down, left, right. enter image description here

My Code for my Player:

using UnityEngine;
using System.Collections;

public class PlayerMovement : MonoBehaviour {

    Direction currentDir;
    Vector2 input;
    bool isMoving = false;
    Vector3 startPos;
    Vector3 endPos;
    public float t;

    public Sprite northSprite;
    public Sprite eastSprite;
    public Sprite southSprite;
    public Sprite westSprite;

    public float walkSpeed = 0.5f;

    public bool isAllowedToMove = true;

    void Start()
    {
        isAllowedToMove = true;
    }

    void Update () { 

        if(!isMoving && isAllowedToMove)
        {
            input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
            if (Mathf.Abs(input.x) > Mathf.Abs(input.y))
                input.y = 0;
            else
                input.x = 0;

            if(input != Vector2.zero)
            {

                if(input.x < 0)
                {
                    currentDir = Direction.West;
                }
                if(input.x > 0)
                {
                    currentDir = Direction.East;
                }
                if(input.y < 0)
                {
                    currentDir = Direction.South;
                }
                if (input.y > 0)
                {
                    currentDir = Direction.North;
                }

                switch(currentDir)
                {
                    case Direction.North:
                        gameObject.GetComponent<SpriteRenderer>().sprite = northSprite;
                        break;
                    case Direction.East:
                        gameObject.GetComponent<SpriteRenderer>().sprite = eastSprite;
                        break;
                    case Direction.South:
                        gameObject.GetComponent<SpriteRenderer>().sprite = southSprite;
                        break;
                    case Direction.West:
                        gameObject.GetComponent<SpriteRenderer>().sprite = westSprite;
                        break;
                }

                StartCoroutine(Move(transform));
            }

        }

    }

    public IEnumerator Move(Transform entity)
    {
        isMoving = true;
        startPos = entity.position;
        t = 0f;

        endPos = new Vector3(startPos.x + System.Math.Sign(input.x), startPos.y + System.Math.Sign(input.y), startPos.z);

        while (t < walkSpeed)
        {
            t += Time.deltaTime * walkSpeed * walkSpeed;
            entity.position = Vector3.Lerp(startPos, endPos, t);
            yield return null;
        };

        isMoving = false;
        yield return 0;
    }
}

enum Direction
{
    North,
    East,
    South,
    West
}
```
\$\endgroup\$
5
  • \$\begingroup\$ Can you show us how you're moving your player currently? A common mistake that leads to symptoms like this is moving a physics object using its Transform component, which bypasses physics checks that would normally stop an object from clipping into a collider. \$\endgroup\$
    – DMGregory
    Mar 22, 2020 at 11:43
  • \$\begingroup\$ @DMGregory yes, i just added the code \$\endgroup\$ Mar 22, 2020 at 13:10
  • 1
    \$\begingroup\$ Yep, there's your problem. You're moving the player into an invalid location with its Transform. Then the physics step runs and the physics engine finds two colliders wedged together. "Who made this mess!?" It demands, and shoves them apart. Then your coroutine runs, and shoves your player back into the collision. Then the physics step runs and pushes them apart again, on and on, creating the vibration that you observe. \$\endgroup\$
    – DMGregory
    Mar 22, 2020 at 13:14
  • \$\begingroup\$ @DMGregory so how do i fix this \$\endgroup\$ Mar 22, 2020 at 19:53
  • \$\begingroup\$ You may want to consider checking whether there is a collider at your destination before you start a coroutine that tries to move there. "Look before you leap" — you can use Physics2D.OverlapBox or similar methods to do this check. \$\endgroup\$
    – DMGregory
    Mar 23, 2020 at 10:38

1 Answer 1

0
\$\begingroup\$

This problem usually occurs when you try to move a gameObject with a Rigidbody / Rigidbody2D component through an environment made of Colliders / Collider2Ds by manipulating its Transform. Don't do that. Changing the transform isn't "moving" an object, it's "teleporting" an object. Teleporting an object into a solid wall never ends well.

If you want to move an object with a rigidbody, then move it by using the methods of the rigidbody. There are several ways to do that. I made a little demo game a while ago which explains the differences between different movement methods. You can check it out here.

If you want to keep it simple, you might want to use rigidbody.MovePosition(newPosition). But you might also consider to control the movement of your player using rigidbody.AddForce(forceVector) to give it physically correct acceleration, deceleration and also the ability to shove (and get shoved by) other rigidbodies in a physically correct way. This requires a bit experimentation with the force strength and the mass and drag settings of the rgidbody to get right, but the end result often feels much more organic.

Regarding the rotation of your character: You can get rid of that by freezing the rotation axis in the Rigidbody / Rigidbody2D.

\$\endgroup\$

You must log in to answer this question.

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