Angled Physics.Raycast not returning true (C# / C sharp)
Intro
In game world theres a capsule player marked with layer !playerBody to be ignorred by ray. Debug.DrawRay(); shows the rays correctly.
Rays are shot from a middle point down and out; forming a cone shape w/ a slight lip underneath player.
Goal
A dynamic amount of rays will test for 'isGrounded' on 'playerBody':
isGrounded == true : On the ground
isGrounded == false : Air borne
Pseudo code
(Player on slope)
1) Ray1:False -> Next, Ray2:False -> Next, Ray3:True -> BoolTrue (Start over)
2) Ray1-16:False -> BoolFalse (Start over)
Problem
Raycast allways returns false.
NOTE
Camera and playerCapsule(rigidBody, constrainedRotation) movement is excluded from example script.
public class X: MonoBehaviour
{
public bool isGrounded = false;
public int rayAmount = 20; //Amount of rays cast
public float rayOffset = -3f;
public float rayRadius = 0.35f;
public LayerMask groundingRayLayerMasking; //Layers to ignore: !playerBody
void FixedUpdate ()
{
Vector3 playerPos = transform.position;
int j = 0; //Do not delete!
for (int i = 1; i < rayAmount; i++)
{
RaycastHit tempHit = new RaycastHit();
if (j > (rayAmount - 1)) // (rayAmount(16)-1)::(since 0 incl. and '0' is required for calc. of 'angle')
{
j = 0;
}
float angle = j * Mathf.PI * 2 / rayAmount;
Vector3 pos = new Vector3(Mathf.Cos(angle), rayOffset, Mathf.Sin(angle)) * rayRadius;
//float temp_rayDistance = Vector3.Distance(playerPos, pos); //TEMP
Debug.DrawRay(playerPos, pos, Color.blue, Time.deltaTime, false);
//Debug.Log(temp_rayDistance); //TMEP
if (Physics.Raycast(playerPos, (pos + playerPos), out tempHit, 5.2f, groundingRayLayerMasking))
{
//Debug.Log("groundRay hit");
isGrounded = true;
i = 0; //Restart squence from 0
j = 0; //Restart squence from 0
//break;
}
else
{
//Debug.Log("No groundRay hit");
isGrounded = false;
if (i > (rayAmount - 1))//Restart sequence reaching end!
{
i = 0;
}
}
j++;
}
}
}
In most case your layer wrong. Since layermask is bit not int.
http://answers.unity.com/questions/8715/how-do-i-use-layermasks.html
First of all thank you for commenting!
Despite refering to layer 10 (!playerBody) as 'bit shifted':
(Yes, the player 'Capsule Collider' has the appropriate layer assigned)
int layer$$anonymous$$askToIgnore = 1 << 10;
if (Physics.Raycast(playerPos, (pos + playerPos), out tempHit, 5.2f, layer$$anonymous$$askToIgnore))
It should ignore the 'Capsule Collider' with start/origin being center of set component.
But either way it won't return true
(even with 'layer$$anonymous$$askToIgnore' incl. in 'Physics.Raycast' or not), only false.
Which puzzles me to no end, again thank you @NoDumbQuestion
I think your physics.raycast direction is wrong. Remove pos +playerPos
Try
Physics.Raycast(playerPos, pos, out tempHit, 5.2f, groundingRayLayer$$anonymous$$asking))
Answer by Ramlock · Aug 28, 2018 at 02:00 PM
The documentation on the Physics.Raycast is a bit poorly written, but in reality the layermask you provide is for the layers you want to collide with, not the ones you want to ignore. I know the documentation says "A Layer mask that is used to selectively ignore Colliders when casting a ray", but that's because in the example it's used as such, but if you notice the actual example code and comments:
// Bit shift the index of the layer (8) to get a bit mask
int layerMask = 1 << 8;
// This would cast rays only against colliders in layer 8.
// But instead we want to collide against everything except layer 8. The ~ operator does this, it inverts a bitmask.
layerMask = ~layerMask;
They invert the bitmask, so in reality the mask has everything except for the selected layer, thus resulting in it being ignored.
In other words, if you add to your code:
private void Start()
{
groundingRayLayerMasking = ~groundingRayLayerMasking;
}
I would expect the collision to behave normally. Please let me and others know if this works.
--EDIT--
I see that you're also setting isGrounded to false whenever a single raycast fails, and that causes only the last raycast to have any effect. Do remove that part as well. Instead, only set IsGrounded to false before the loop, and only set it to true inside the loop, whenever a hit occurs (and then break the loop). PS: Why did you comment out the break; part of your loop? PPS: Why would you want your loop to reset (by making i=0)? Won't this cause an infinite loop in some situations? That could also very well be a reason the loop never exits with a isGrounded == true state.
Your answer
Follow this Question
Related Questions
c# jumping isn't consistent, please help 0 Answers
How can I move an object in the direction another object is facing. 1 Answer
Bugging ragdoll 1 Answer
Problem. Pick up and Grab object script, except all objects in scene are picked up instead of one. 0 Answers
Ray cast to object to transform, instead all objects with script transform. 0 Answers