Other Issues with "gravity" in grid-based collision system

Discussion in 'Scripting' started by AcinonX, Feb 24, 2024.

1. AcinonX

Joined:
Apr 15, 2021
Posts:
28
I am working on a game that uses a grid-based movement system, and collisions are checked by firing a ray 1 unit (equivalent to 1 tile) in the direction the character is trying to move. If the ray hits, the character will stop moving. I also decided it would be a good idea to move the character up by 1 unit if they happen to walk into a wall that has a floor less than 1 unit above the character. Now, I'm having trouble trying to make the character move down if they walk somewhere with no floor. This is the relevant part of the script so far:
Code (CSharp):
1.     public IEnumerator Step(Vector2 direction)
2.     {
3.         isMoving = true;
4.
5.         float elapsedTime = 0;
6.
7.         _direction = direction;
8.         lastPosition = transform.position;
9.         nextPosition = lastPosition + new Vector3(direction.x, 0, direction.y);
10.
11.         if (!Physics.Raycast(nextPosition, Vector3.down, 1.5f))
12.         {
13.             nextPosition.y -= 1;
14.         }
15.         if (Physics.Raycast(transform.position, new Vector3(direction.x, 0, direction.y), 1))
16.         {
17.             if (!Physics.Raycast(transform.position + new Vector3(0, 1, 0), new Vector3(direction.x, 0, direction.y), 1))
18.             {
19.                 nextPosition.y += 1;
20.             }
21.             else
22.             {
23.                 isMoving = false;
24.                 transform.position = lastPosition;
25.
26.                 yield break;
27.             }
28.         }
29.
30.         while (elapsedTime < stepTime)
31.         {
32.             transform.position = Vector3.Lerp(lastPosition, nextPosition, elapsedTime / stepTime);
33.             elapsedTime += Time.deltaTime;
34.             yield return null;
35.         }
36.
37.         transform.position = nextPosition;
38.
39.         isMoving = false;
40.     }
Basically:
• Check if there's a floor under the character at the next spot they're moving towards
• If there isn't one, shift the target position down by 1 unit
• Check if the character will collide with a wall
• If they will, proceed to check if there is a floor 1 unit or less above the wall
• Otherwise, cancel the step
How do I fix it so that it works as intended?

2. Kurt-Dekker

Joined:
Mar 16, 2013
Posts:
38,697
For any grid-based game do all the logical comparisons in your own data storage mechanism for the tiles, such as a 2D array of tiles.

Otherwise you needlessly bind your game logic into Unity colliders and the Unity API, making it about 10x more complicated than it needs to be.

spiney199 likes this.
3. AcinonX

Joined:
Apr 15, 2021
Posts:
28
So I would have to build the 3D level geometry and the collisions/tile data separately for this to work?

4. Kurt-Dekker

Joined:
Mar 16, 2013
Posts:
38,697
You can build it however you like.

I'm saying for the actual logic, operate against a 2D array of things.

You can make that structure in advance and use it to build the 3D representations, or you can author all the 3D stuff and write some code to analyze it ONCE and get it into a reliable data structure and operate on that.

If you want an example of a 3D representation of a 2D game world, including full source and project, check out my simple Match3 Demo here... full source linked in game comments.

https://kurtdekker.itch.io/match3-demo

It stores all of its data in a 2D array:

PieceController[,] Board;

This allows for easy simple checking in code, not relying on anything like physics.

You should strive to use that pattern for all logic, then only present what is happening in scene.

spiney199 likes this.

Joined:
Aug 1, 2021
Posts:
730
Check CodeMonkey's "Building Grid" tutorial, it'll point you in the right detection.

6. AcinonX

Joined:
Apr 15, 2021
Posts:
28
Okay, I'll have to watch that at some point. Thanks!