- 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