I’m currently playing around with some movement for my 2.5D side-scroller project, but Physics.Raycast gives me some trouble. I know these rays are casted once per frame (I’m having them in FixedUpdate however), and I’m using them to detect ground and walls around me etc. They are casted from the center point of the character (a simple box), and extends 0.2F outside of the box.
But when my character jumps and falls back the the ground, it’s always a different height he lands at (depending on which frame the ray detects ground in, I think…), and that’s not quite what i want. I want my character to land when the ray detects the ground, but it’s always different, sometimes he evens lands a bit inside of the ground, if he had a high jump and gravity has accelerated enough. I’ve looked at some tutorials, and everybody using raycast for ground detection have their character landing in a consistent height.
Do you have any idea to fix this, or know what I’m doing wrong?
Here’s the code:
using UnityEngine;
using System.Collections;
public class movement : MonoBehaviour {
public Vector2 velocity;
Vector3 leftButtomVec;
Vector3 rightButtomVec;
Vector3 LowVec;
Vector3 MidVec;
Vector3 HighVec;
float distButomRays;
float gravity;
float maxGravity;
bool grounded;
bool canMoveXaxis;
float moveSpeed;
bool inputJump;
float jumpForce;
float distSideRays;
void Start () {
gravity = 0.3F;
maxGravity = -100F;
grounded = false;
distButomRays = collider.bounds.extents.y + 0.2F;
canMoveXaxis = true;
moveSpeed = 150;
jumpForce = 7;
distSideRays = collider.bounds.extents.x + 0.2F;
}
void Update()
{
Debug.DrawLine(leftButtomVec, leftButtomVec + new Vector3(0, -distButomRays, 0));
Debug.DrawLine(rightButtomVec, rightButtomVec + new Vector3(0, -distButomRays, 0));
Debug.DrawLine(LowVec, LowVec + new Vector3(-distSideRays, 0, 0));
Debug.DrawLine(MidVec, MidVec + new Vector3(-distSideRays, 0, 0));
Debug.DrawLine(HighVec, HighVec + new Vector3(-distSideRays, 0, 0));
Debug.DrawLine(LowVec, LowVec + new Vector3(distSideRays, 0, 0));
Debug.DrawLine(MidVec, MidVec + new Vector3(distSideRays, 0, 0));
Debug.DrawLine(HighVec, HighVec + new Vector3(distSideRays, 0, 0));
}
bool IsGravityHigerThenMaxGravity()
{
if (velocity.y - gravity >= maxGravity)
{
Debug.Log("Accerlerating ..!");
return true;
}
else
{
Debug.Log("Max gravity speed!");
return false;
};
}
public float CantMove(float horizontal, string dontMove)
{
if (horizontal < 0 && dontMove == "left")
{
return 0;
}
else if (horizontal > 0 && dontMove == "right")
{
return 0;
}
else
{
return horizontal;
}
}
void FixedUpdate()
{
inputJump = Input.GetButton("Jump");
//Buttom rays
leftButtomVec = new Vector3(transform.position.x - collider.bounds.extents.x, transform.position.y, 0);
rightButtomVec = new Vector3(transform.position.x + collider.bounds.extents.x, transform.position.y, 0);
Ray leftButtomRay = new Ray(leftButtomVec, Vector3.down);
Ray rightButtomRay = new Ray(rightButtomVec, Vector3.down);
if (Physics.Raycast(leftButtomRay, distButomRays) || Physics.Raycast(rightButtomRay, distButomRays))
{
grounded = true;
}
else
{
grounded = false;
}
//Side rays vectors
LowVec = new Vector3(transform.position.x, transform.position.y - collider.bounds.extents.y, 0);
MidVec = new Vector3(transform.position.x, transform.position.y, 0);
HighVec = new Vector3(transform.position.x, transform.position.y + collider.bounds.extents.y, 0);
//Left side rays
Ray leftLowVec = new Ray(LowVec, Vector3.left);
Ray leftMidVec = new Ray(MidVec, Vector3.left);
Ray leftHighVec = new Ray(HighVec, Vector3.left);
//Right side rays
Ray rightLowVec = new Ray(LowVec, Vector3.right);
Ray rightMidVec = new Ray(MidVec, Vector3.right);
Ray rightHighVec = new Ray(HighVec, Vector3.right);
if (Physics.Raycast(leftLowVec, distSideRays) || Physics.Raycast(leftMidVec, distSideRays) || Physics.Raycast(leftHighVec, distSideRays))
{
Debug.Log("Hit wall with left side of body");
canMoveXaxis = false;
velocity = new Vector2( CantMove(Input.GetAxis("Horizontal"), "left"), velocity.y );
}
else if (Physics.Raycast(rightLowVec, distSideRays) || Physics.Raycast(rightMidVec, distSideRays) || Physics.Raycast(rightHighVec, distSideRays))
{
Debug.Log("Hit wall with right side of body");
canMoveXaxis = false;
velocity = new Vector2(CantMove(Input.GetAxis("Horizontal"), "right"), velocity.y);
}
else
{
canMoveXaxis = true;
}
//Gravity
if (grounded)
{
velocity = new Vector2(velocity.x, 0);
}
if (!grounded)
{
velocity = new Vector2(velocity.x, IsGravityHigerThenMaxGravity() ? velocity.y - gravity : maxGravity);
}
//Jump
if (grounded && inputJump)
{
velocity = new Vector2(velocity.x, jumpForce);
}
}
void LateUpdate()
{
//Move in x-axis
if (canMoveXaxis)
{
velocity = new Vector2(Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime, velocity.y);
}
//Apply force
transform.Translate(velocity * Time.deltaTime);
}
}