Hi,
I first apologize for my bad english, foreigner talking.
I’m getting mad on some strange behaviour i have on my project.
I have a basic map with walls and holes and npcs moving in it.
Their move are tile based and i choose the direction according on if raycast tests hit tag walls or not (holes are tagged as walls too)
This is working about 99% of the time but there is always a moment where my raycast don’t see the wall/hole.
All my code is in Update since i’m not using lots of physics. I tried to put my code in FixedUpdate just to test but i have the same issues.
I tried many things like change the mesh colliders in box for performance, lower the maximum allowed time, the speed of my npcs (which were already slow)
I’m confused and i don’t want to go further in my program until i fix this so i come here to beg for any help.
A preview is attached where you can see all my debug raycast (green for no walls, red for walls).
As you can see my npc go through the wall because they are using a trigger collider but that’s irrevelant.
I give you my code for the detection too, It’s a bit long i apologize for that but maybe it will help you to see my problem better.
void Update()
{
Move(); //npc movement
// i check if my steap is ready to do before entering in my fonction
if ((isWalking || isRunning) && !isTurning && !isTurningBack && stepDone)
{
transform.position= new Vector3(lastPos.x, 1f, lastPos.z); //i reposition my npc to a rounded position in case it would solved my issue.... no luck
CheckWall();
}
}
void CheckWall()
{
int layerMask = 1 << 8; //my player is ignored for the raycast
layerMask = ~layerMask;
RaycastHit hitF;
RaycastHit hitL;
RaycastHit hitR; // i originally had only one raycast and i tried to do more to see if this would change my issue.... still no luck.
if (Physics.Raycast(transform.position, transform.forward, out hitF, 5f, layerMask) && hitF.transform.tag == "Wall")
{
Debug.DrawRay(transform.position, transform.forward * hitF.distance, Color.red ,rayTime );
if (Physics.Raycast(transform.position, -transform.right, out hitL, 4f, layerMask) && hitL.transform.tag == "Wall")
{
Debug.DrawRay(transform.position, -transform.right * hitL.distance, Color.red,rayTime);
if (Physics.Raycast(transform.position, transform.right, out hitR, 4f, layerMask) && hitR.transform.tag == "Wall")
{
Debug.DrawRay(transform.position, transform.right * hitR.distance, Color.red,rayTime);
if (isWalking)
{
isWalking = false;
isTurningBack = true;
anim.SetTrigger("turnBack");
}
else if (isRunning) // my npcs are not running anymore until i solve that issue
{
isRunning = false;
isTurningBack = true;
anim.SetTrigger("deadEnd");
}
direction = 3; //direction = 0 for left, 1 for right, 2 for straight and 3 for turnback
// set the final angle for the turn back animation based on the approximation of the current angle
if (transform.eulerAngles.y >= 45f && transform.eulerAngles.y < 135f) //around 90
angleLimit = 270; //adding 180
else if (transform.eulerAngles.y >= 135f && transform.eulerAngles.y < 225f)
angleLimit = 0;
else if (transform.eulerAngles.y >= 225f && transform.eulerAngles.y < 315f)
angleLimit = 90;
else if (transform.eulerAngles.y >= 315f || transform.eulerAngles.y < 45f)
angleLimit = 180;
}
else
{
Debug.DrawRay(transform.position, transform.right * 4f, Color.green,rayTime);
direction = 1;
}
}
else if (Physics.Raycast(transform.position, transform.right, out hitR, 4f, layerMask) && hitR.transform.tag == "Wall")
{
Debug.DrawRay(transform.position, -transform.right * 4f, Color.green,rayTime);
Debug.DrawRay(transform.position, transform.right * hitR.distance, Color.red,rayTime);
direction = 0;
}
else
{
Debug.DrawRay(transform.position, -transform.right * 4f, Color.green,rayTime);
Debug.DrawRay(transform.position, transform.right * 4f, Color.green,rayTime);
direction = Random.Range(0, 2);
}
}
else if (Physics.Raycast(transform.position, -transform.right, out hitL, 4f, layerMask) && hitL.transform.tag == "Wall")
{
Debug.DrawRay(transform.position, transform.forward * 4f, Color.green,rayTime);
Debug.DrawRay(transform.position, -transform.right * hitL.distance, Color.red,rayTime);
if (Physics.Raycast(transform.position, transform.right, out hitR, 4f, layerMask) && hitR.transform.tag == "Wall")
{
Debug.DrawRay(transform.position, transform.right * hitR.distance, Color.red,rayTime);
direction = 2;
}
else
{
Debug.DrawRay(transform.position, transform.right * 4f, Color.green,rayTime);
direction = Random.Range(1, 3);
}
}
else if (Physics.Raycast(transform.position, transform.right, out hitR, 4f, layerMask) && hitR.transform.tag == "Wall")
{
Debug.DrawRay(transform.position, transform.forward * 4f, Color.green,rayTime);
Debug.DrawRay(transform.position, -transform.right * 4f, Color.green,rayTime);
Debug.DrawRay(transform.position, transform.right * hitR.distance, Color.red,rayTime);
direction = Random.Range(0, 2);
if (direction == 1)
{
direction = 2;
}
}
else
{
Debug.DrawRay(transform.position, transform.forward * 4f, Color.green,rayTime);
Debug.DrawRay(transform.position, -transform.right * 4f, Color.green,rayTime);
Debug.DrawRay(transform.position, transform.right * 4f, Color.green,rayTime);
direction = Random.Range(0, 3);
}
switch (direction)
{
//same routine as for turning back based on the direction it picked
case 0:
isTurning = true;
if (transform.eulerAngles.y >= 45f && transform.eulerAngles.y < 135f)
angleLimit = 0;
else if (transform.eulerAngles.y >= 135f && transform.eulerAngles.y < 225f)
angleLimit = 90;
else if (transform.eulerAngles.y >= 225f && transform.eulerAngles.y < 315f)
angleLimit = 180;
else if (transform.eulerAngles.y >= 315f || transform.eulerAngles.y < 45f)
angleLimit = 270;
break;
case 1:
isTurning = true;
if (transform.eulerAngles.y >= 45f && transform.eulerAngles.y < 135f)
angleLimit = 180;
else if (transform.eulerAngles.y >= 135f && transform.eulerAngles.y < 225f)
angleLimit = 270;
else if (transform.eulerAngles.y >= 225f && transform.eulerAngles.y < 315f)
angleLimit = 0;
else if (transform.eulerAngles.y >= 315f || transform.eulerAngles.y < 45f)
angleLimit = 90;
break;
}
stepDone = false; //my step is done so i can start a new one
}