Hey there,
I have a problem and was hoping someone could help me, i want to create a grid based movement, but with different heights and ramps.
So right now i use the GridMove from the Wiki. I thought about converting it to use a rigidbody.(but i got weird problems whenever you hit a ramp, you start floating)
But i still don’t know how to tackle the problem whenever you come across a ramp-tile.
The idea should be that the player walks up the ramp, automatically updating the Y position but reaching the X or Z position.
Can anybody share some insight on this? It would greatly help me.
I already tried looking on google, so far i saw some great tips. But none of them wanted to use a system with different heights or ramps.
Thanks in advance! Meanwhile i will start thinking of a possible solution.
Cheers,
Darryl
Okay, so i thought about some methods to tackle this and i came up with this:
Cast a ray downwards, and store the hit Y position.
The code now looks like this:
using System.Collections;
using UnityEngine;
class PlayerController : MonoBehaviour
{
public float moveSpeed = 3f;
public float gridSize = 1f;
private Vector2 input;
private bool isMoving = false;
private Vector3 startPosition;
private Vector3 endPosition;
private float t;
private float factor;
public Vector3 groundPosition;
RaycastHit hit;
Transform myTransform;
void Start()
{
myTransform = transform;
}
public void Update()
{
if(Physics.Raycast(myTransform.position, Vector3.down, out hit, 2f))
{
groundPosition = hit.point;
groundPosition += new Vector3(0, myTransform.localScale.y, 0);
}
if (!isMoving)
{
input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (Mathf.Abs(input.x) > Mathf.Abs(input.y))
{
input.y = 0;
}
else
{
input.x = 0;
}
if (input != Vector2.zero)
{
StartCoroutine(move(myTransform));
}
}
}
public IEnumerator move(Transform myTransform)
{
isMoving = true;
startPosition = myTransform.position;
t = 0;
endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
groundPosition.y, startPosition.z + System.Math.Sign(input.y) * gridSize);
factor = 1f;
while (t < 1f)
{
t += Time.deltaTime * (moveSpeed / gridSize) * factor;
myTransform.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
isMoving = false;
yield return 0;
}
}
It is sort of working, but there is a delay in the groundPosition and the actual transform position.
So when walking down ramps, you will float in the air or whenever you walk up a ramp, you will first walk through the ramp.
However, i am a step closer.
Cheers,
Darryl
Okay sorry for all the bumps. But i figured it out!
The problem was, whenever you moved in a direction it only calculated the X and Z axis. Since it casted a Ray downwards from the players position.
So i did a check in which direction the player is moving, casting a ray 1 block away downwards.
And now it works!
So if anyone is interested, here is the code:
using System.Collections;
using UnityEngine;
class PlayerController : MonoBehaviour
{
public float moveSpeed = 3f;
public float gridSize = 1f;
private Vector2 input;
private bool isMoving = false;
private Vector3 startPosition;
private Vector3 endPosition;
private float t;
private float factor;
public Vector3 groundPosition;
Vector3 rayPosition;
RaycastHit hit;
Transform myTransform;
void Start()
{
myTransform = transform;
}
public void Update()
{
if (!isMoving)
{
input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (Mathf.Abs(input.x) > Mathf.Abs(input.y))
{
input.y = 0;
if(input.x >0)
{
rayPosition = new Vector3(myTransform.position.x+1f, myTransform.position.y, myTransform.position.z);
}
else if(input.x < 0)
{
rayPosition = new Vector3(myTransform.position.x-1f, myTransform.position.y, myTransform.position.z);
}
}
else
{
input.x = 0;
if(input.y > 0)
{
rayPosition = new Vector3(myTransform.position.x, myTransform.position.y, myTransform.position.z + 1f);
}
else if(input.y < 0)
{
rayPosition = new Vector3(myTransform.position.x, myTransform.position.y, myTransform.position.z - 1f);
}
}
if (input != Vector2.zero)
{
if (Physics.Raycast(rayPosition, Vector3.down, out hit, 2f))
{
groundPosition = hit.point;
groundPosition += new Vector3(0, myTransform.localScale.y, 0);
}
StartCoroutine(move(myTransform));
}
}
}
public IEnumerator move(Transform myTransform)
{
isMoving = true;
startPosition = myTransform.position;
t = 0;
endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
groundPosition.y, startPosition.z + System.Math.Sign(input.y) * gridSize);
factor = 1f;
while (t < 1f)
{
t += Time.deltaTime * (moveSpeed / gridSize) * factor;
myTransform.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
isMoving = false;
yield return 0;
}
}
If you have anything to add, or maybe some tips. I would still like to hear them!
For now i am just happy for fixing this.
Cheers,
Darryl