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][1], 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.
[1]: http://wiki.unity3d.com/index.php?title=GridMove
↧