2D Toolkit Forum
2D Toolkit => Support => Topic started by: zeteginara on February 28, 2014, 07:19:06 pm
-
So, I'm starting a top-down 2D RPG sort of game, with free-form movement instead of, well, large-grid specific movement. I got a 'basic guy moving across the screen colliding with a tilemap'. However, when I hit a tile with a diagonal collider, I slow way down.
I seem to be doing this: (http://i51.photobucket.com/albums/f363/zeteginara/22869-wrong_zpsa28fc79f.png)
When I should be doing this: (http://i51.photobucket.com/albums/f363/zeteginara/22869-wrong_zpsa28fc79f.png)
My code is very simple and barebones.
float moveHorizontal = Input.GetAxisRaw("Horizontal");
float moveVertical = Input.GetAxisRaw("Vertical");
Movement = new Vector2(moveHorizontal, moveVertical);
rigidbody2D.velocity = Movement * Speed;
I've heard there are things you can do with Raycasts to take a slope into account.... but I haven't done anything with that before. This seems to be a relatively common problem (like any platformer with slopes would have to code against), so I'm sure that it's easy to solve, but I'm not sure where to start.
-
I've been working on this and scouring the internet all day, and getting frustrated.
Here's the entire code that I have:
void FixedUpdate()
{
float moveHorizontal = Input.GetAxisRaw("Horizontal");
float moveVertical = Input.GetAxisRaw("Vertical");
Movement = new Vector2(moveHorizontal, moveVertical);
Movement.Normalize();
rigidbody2D.velocity = Movement * Speed;
}
void OnCollisionEnter2D(Collision2D other)
{
Normal = other.contacts[0].normal;
rigidbody2D.velocity -= Normal * Vector2.Dot(rigidbody2D.velocity, Normal);
}
It seems that no one has a good answer to this, and I imagine this is a relatively standard problem. I'm colliding with a diagonal on a sprite tilemap. What am I doing wrong?
-
I remember reading somewhere that using sphere colliders in slopes produces the smoothest collisions. Can you try changing your colliders to sphere?
-
I'm currently using spheres exclusively, so that's not the problem, but thanks.
-
Update:
One problem was that the velocity was only being updated once when the collision first happened, then was being overriden by FixedUpdate. I've fixed that, and a few other errors that popped up, but there is one other:
Here's my new code:
void FixedUpdate()
{
float moveHorizontal = Input.GetAxisRaw("Horizontal");
float moveVertical = Input.GetAxisRaw("Vertical");
Movement = new Vector2(moveHorizontal, moveVertical);
Movement.Normalize();
rigidbody2D.velocity = Movement * Speed;
if (Colliding && Movement == RecordMovement)
{
rigidbody2D.velocity -= Normal * Vector2.Dot(rigidbody2D.velocity, Normal);
}
else
{
RecordMovement = Movement;
}
}
void OnCollisionEnter2D(Collision2D other)
{
Normal = other.contacts[other.contacts.Length - 1].normal;
Normal.Normalize();
OppositeNormal = Normal * -1;
if ((OppositeNormal != Movement) && (Colliding != true))
{
Colliding = true;
}
else
{
Colliding = false;
}
}
void OnCollisionExit2D(Collision2D other)
{
Colliding = false;
}
However, then I had another problem. Well, several other problems. I've resolved some, but one remains.
If I am up against a wall, and moving parellel to it so that my collider is 'just touching' the wall, and I hit a diagonal from there, then I move just as slow as if my new code didn't exist. After lots of debugging, I found that we are detecting a new collision, but if I try to get the normal of this new collision, I end up with the normal of the old collision (the wall I was sliding against) I don't know if this is a bug in Unity, or a flaw in the colliders generated by the 2D tilemap, or what.
I even tried changing my code to "Normal = other.contacts[other.contacts.Length - 1].normal;", assuming that would get the last element of the array (latest), but no dice, same incorrect normal.
So, any ideas?
-
I finally resolved this! My gut feeling was right: I was overthinking it.
Step 1: Remove all of the code example above and just have a simple:
void FixedUpdate()
{
float moveHorizontal = Input.GetAxisRaw("Horizontal");
float moveVertical = Input.GetAxisRaw("Vertical");
movement = new Vector2(moveHorizontal, moveVertical);
movement.Normalize();
rigidbody2D.velocity = movement * Speed;
}
Step 2: In your assets folder, go to Create > Physics2DMaterial. Create one.
Step 3: Click your new material, and call it whatever you want. I called it "Frictionless". Set Friction to 0, and make sure "Bounce" is 0.
Step 4: Drag your new material to any of the "Physics Material (2D)" fields in any of the objects involved in the equation.
You're done!