- Home /
Diagonal collision script not working (Unity + Orthello, C#)
I recently started coding in Unity after being introduced to the Orthello framework for 2D games, and ran into a problem I can't figure out regarding diagonal movement in a grid. I do not believe that the Orthello framework is what's giving me headaches, however. I'm using a modified version of this script, made by Eric Haines. The movement is grid-based, with each tile being 64x64.
On each update, collision raycasts are recalculated. This gives me a few variables that let me know if my character can go in any cardinal direction. The raycasts only negate booleans, while moving in directions opposite of negated booleans re-enables them.
For example:
if (Physics.Raycast (new Vector3(sprite.position.x, sprite.position.y, 0), Vector2.up-Vector2.right, out hit, 64))
{
moveNW = false;
}
else moveNW = true;
This code works for vertical and horizontal movement:
if(input.y>0 && moveUp){ moveDown = true; sprite.Resume(); if (!isMoving)StartCoroutine(move(transform)); }
else if(input.y<0 && moveDown){ moveUp = true; if (!isMoving)StartCoroutine(move(transform)); sprite.Resume();}
else if(input.x<0 && moveLeft){ moveRight = true; sprite.Resume(); if (!isMoving)StartCoroutine(move(transform));}
else if(input.x>0 && moveRight){ moveLeft = true; sprite.Resume(); if ( !isMoving)StartCoroutine(move(transform));}
So, I always have 8 booleans telling me which directions I can go at any given time. When I try to move diagonally however, the collision detection fails in some cases. When not in a corner, the character clips through the collidables. When in a corner, for some reason, the character stays put if I try to send it through the corner collidable.
Here's the code I'm using for diagonal movement (the raycasting part works correctly, I checked the truth values of the variables through the debugger):
if(input.y>0 && input.x>0 && moveNE){moveSE = true; sprite.Resume (); StartCoroutine(move(transform));}
else if(input.y>0 && input.x<0 && moveNW){moveSW = true; sprite.Resume (); StartCoroutine(move(transform));}
else if(input.y<0 && input.x<0 && moveSW){moveNE = true; sprite.Resume ();StartCoroutine(move(transform));}
else if(input.y<0 && input.x>0 && moveSE){moveNW = true; sprite.Resume ();StartCoroutine(move(transform));}
I'd appreciate any insight more experienced developers can offer about this problem. Again, I mention that the truth variables are correct, as well as the input values.
For possible relevance to the problem, here's the movement function as well, which is a simplified version of Eric's script:
public IEnumerator move(Transform transform) {
isMoving = true;
startPosition = transform.position;
t = 0;
endPosition = new Vector3(sprite.position.x + System.Math.Sign(input.x) * gridSize,
sprite.position.y + System.Math.Sign(input.y) * gridSize, 0);
factor = 1f;
while (t < 1f) {
t += Time.deltaTime * (moveSpeed/gridSize) * factor;
sprite.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
isMoving = false;
yield return 0;
}
Before you mention it, I'm aware that simply raycasting between my sprite's point of origin and the destination on the grid should make the problem much easier to solve. However, I would like to understand the error in this method, efficiency aside.
What caught my eye during a quick skim, was that you use Vector2.up
& Vector2.right
in your first snippet. They are the global directions, along the world axes. This could be a problem if your transform or playing grid has rotated at all. I would use sprite.up
& sprite.right
, as they're the directions relative to the actual transform. (Assu$$anonymous$$g sprite
references the transform.)
Answer by Vehrmt · Sep 28, 2013 at 12:30 AM
Thanks for the feedback, Jamora! I'll look towards using a more unified format if I implement rotation later on.
In the meanwhile, I figured out a solution to my problem. While the diagonal movement conditions were working as expected, my vertical/horizontal if conditions were insufficient. Because I used input.x and input.y by themselves, they didn't restrict input on the other axis, and the movement script triggered.
Here's the edited code for the horizontal/vertical movement conditions:
if(input.y>0 && (input.x == 0) && moveUp){ moveDown = true; sprite.Resume(); if ( !isMoving)StartCoroutine(move(transform)); }
else if(input.y<0 && (input.x == 0) && moveDown){ moveUp = true; if (!isMoving)StartCoroutine(move(transform)); sprite.Resume();}
else if(input.x<0 && (input.y == 0) && moveLeft){ moveRight = true; sprite.Resume(); if (!isMoving)StartCoroutine(move(transform));}
else if(input.x>0 && (input.y == 0) && moveRight){ moveLeft = true; sprite.Resume(); if (!isMoving)StartCoroutine(move(transform));}
Your answer
Follow this Question
Related Questions
Problem with 2D movement 0 Answers
NullReferenceException with Terrain.activeTerrain 2 Answers
I need some help with my script. Im just a beginner and dont know whats happening. 1 Answer
Game object passes through walls 0 Answers
Glitchy collisions 0 Answers