I am making a bot for a tank game and right now I am trying to make him evade Obstacles. For that I am using RayCastHit, the problem is that my RayCastHit seams to ignore obstacles. So far I have
public float sensor_length = 10f;
shows how long the sensor is allowed to be
public float car_length = -5f;
the tank is spun with 180 degrees, and this causes the sensor to come from front.
In a Method I have:
RaycastHit hit;
Vector3 sensorStartpos = transform.position;
sensorStartpos.z += car_length;
if(Physics.Raycast(sensorStartpos,transform.forward,out hit,sensor_length))
{ }
Debug.DrawLine(sensorStartpos, hit.transform.position);
So I am getting my object transform point, then locate the front of it and it should fire a RayCast. Here comes the problem, as shown I didnt identify hit so its value is null and in the if statement I should fire one check to the next obstacle, but instead it fires one to point (0,0,0) (I am guessing because hit = null
How do I cause it to hit an obstacle instead?
(The debug line on the bottom causes the Ray Cast to be visualized)
Related
When the mouse is at the Door (red area) i want to do something. I am trying to cast a Ray but the Ray doesn't hit the Door and i cant find where exactly it is hitting. Also how can i Debug.DrawRay this ray?
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
if (hit.collider.tag == "InteractiveDoor")
{
doorInteractGameObject.SetActive(true);
}
else
{
doorInteractGameObject.SetActive(false);
}
}
You might need to create a LayerMask and add it to the parameters for Physics.Raycast; also make sure that the door has a collider on it. You would be surprised how many times I just forgot to add a collider.
In terms of drawing the ray in case this is not working for some reason. Use Debug.DrawRay. I recommend putting it in FixedUpdate() or Update(). Color and duration you can set to whatever you want but I recommend having depthTest be false since you want the ray to be drawn regardless. Then call it like:
Debug.DrawRay(ray.origin, ray.direction, <color>, <duration>, false);
You can draw this ray as:
Debug.DrawRay(ray.origin, ray.direction);
or
Debug.DrawRay(Camera.main.transform.position, Camera.main.ScreenPointToRay(Input.mousePosition).direction);
Option 1 is more direct once you've defined your ray, but option 2 gives you more choice to play around if it turns out this Ray doesn't behave the way you expect it to.
camera.ScreenPointToRay expects a Vector3 but Input.mousePosition returns a Vector2. The Unity docs on Vector3 and Vector2 appear that you should be able to use Vector2 as Vector3 implicitely and it'll populate the z component as 0, but if the Debug.DrawRay shows that the ray is the issue, then you need to append a 0. Maybe something like:
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
The fix is to go to your camera and set the tag to 'MainCamera'. Or you can modify your code to have a camera variable and use that variable instead of Camera.main.
I have a bullet that is fired with a Impuls on the rigidbody.
Then, each frame i do a raycast forward with the speed of the bullet, which sometimes does, and sometimes doesn't find an enemy.
When i skip through the game frame by frame, i can clearly see my debug-raycast inside the (boc)collider of the enemy, but it still won't find it.
Im pretty sure it doesn't just pass the enemy, in the editor i can clearly see the green raycast inside the collider.
Any suggestions? I also tried with a linecast, which i found on here, but that gives the same result. (the line is on the exact same position and also draws the debug-line inside the collider. The layers are also correct, as i said, sometimes it will, and sometimes it wont find the target...
void Update()
{
//get direction and distance
Vector3 direction = _rigidBody.velocity.normalized;
float distance = (_rigidBody.velocity.magnitude * Time.deltaTime);
//raycast for targets
RaycastHit raycast;
if (Physics.Raycast(transform.position, direction, out raycast, distance, HitLayerMask))
{
Debug.DrawRay(transform.position, direction, Color.red);
}
else
{
Debug.DrawRay(transform.position, direction, Color.green);
}
}
You can see the tiny debug ray, aswell als the collider from side-view. It also it almost right in the middle from the front-view.
I'm thinking it might be because the start and end of the raycast are inside the boxcollider?
the rigidbody is moved by
//Speed = 500 in this case, but lowering doesn't change anything
rigidBody.AddRelativeForce(Vector3.forward * Speed, ForceMode.Impulse);
UPDATE:
After some more debugging and testing, i found that it happens because you won't get a hit from inside a collider.
Here's what happend:
bullet is outside target collider, but raycast is to short to find it.
bullet moves forward, enemy also moves forward (closing in on eachother). Bullet is now inside the collider
raycast won't find enemy because thats just how raycast work
What i could do, is make the distance of the raycast further, but also not so far away that it would result in weird hits that would graphically look weird.
i thought that using
float distance = (_rigidBody.velocity.magnitude * Time.deltaTime);
would be enough (since thats the distance the bullet traveled since last frame, but because the enemy also moves, the above can happen. Well, it would be enough if the enemy wouldn't move :/
One possible solution is to go to Project Settings -> Script execution order and put the bullet's MonoBehavior after Default Time. That way everything else has already finished moving before you do the ray cast. A hacky solution but should work.
I'm trying to detect the ground ahead of a cube that doens't have boxcollider or rigid body. I can detect it ok but the distance never changes. I can use very big number or very small ones that it still detects the ground at the same distance.
The debug lines are working fine and nothing is detected before the ground. Even trying raycast without distance keeps the detection at the same distance.
I tried some other variations of the method Raycast with the same results.
Here is my script:
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hitInfo;
Debug.DrawRay(pos, transform.forward * detectDistance, Color.green);
if (Physics.Raycast(ray,out hitInfo, detectDistance)) {
Debug.Log(hitInfo.transform.name);
Debug.DrawRay(pos, transform.forward * detectDistance, Color.red);
}
If your main goal is to calculate the distance between two GameObjects (cube and ground), the use of Raycast is not a must. You can follow this other approach:
Vector3 dist = Vector.distance(cube.transform.position, ground.transform.position);
Debug.Log(string.Format("Distance between {0} and {1} is: {2}", cube, ground, dist));
However if you want to keep with the Raycast, without having all the information about how is your scene and how are the gameObjects located, I can only recommend you to try the following things:
1- Calculate the direction of the Ray like this:
Vector3 direction = ( cube.transform.position - ground.transform.position ).normalized;
Ray ray = new Ray( cube.transform.position, direction );
2- Calculate the distance from hit:
if (Physics.Raycast(downRay, out hit)) {
float distance = hit.distance;
}
3- And just in case calculate the distance from void FixedUpdate()
The problem was the other terrain chunks wasn't generating the collider mesh till you get really close to it.
I did find a way to generate it far away.
Writing a C# script that allow player to construct with simple blocks. For this reason, I strike a raycast forward from playercam. When ray hit some object - I get the collison world coords with hit.point
If I Instantiate a constructing block on that coordinates - it will be created overlapping with other objects. I have to change coords.
How can I get the point that lay as shown in the picture above? This will allow me to calculate created blocks' coordinates
You can take the RaycastHit's point property and move out along the intersected face's normal to your block's extent (half its width; if it's a unit cube, this will be 0.5f); something like this:
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
Instantiate (prefab, hit.point + hit.normal * blockExtent, hit.transform.rotation);
}
}
This will instantiate your new block at the raycast's intersection point (you'd need to calculate the center of the intersected face if you wanted them to align precisely), and inherit the rotation of the intersected GameObject.
Note that this won't prevent a new block from spawning inside an existing block; it will just keep it from spawning inside the block that you raycasted against.
I have an object with circle collider 2d, and an object with box collider 2d. how do i detect when the circlecollider hits the top edge of the box collider. assuming none objects have any rotation. i want to do this in code C#
OnCollisionEnter triggers when something collides with the object containing this script, used like this:
void OnCollisionEnter(Collider collider)
{
foreach(CollisionPoint contact in collider.contacts)
{
//Do something
}
}
The above will give you a list of contact points for the collision, via which you should be able to determine where the collision occurred. An alternative method if you only need to detect collisions at a specified location, you could place an invisible child object within your cube, with a collider at the spot you want.
Edit:
Since you mentioned raycasts, there's 2 ways I can think of that these could be implemented. The first is to fire it upwards from the cube, but this has the issue of the ray firing from just 1 point, meaning some collisions might be missed (depending on the size of the cube & sphere).
The second method that pops to mind is to fire the ray parallel to the cube. This might sound a bit unorthodox, and I haven't tested it, but in theory it should work. Stick it in your cube:
void Update
{
Vector3 start = this.transform.position;
Vector3 end= this.transform.position;
//This attempts to place the start & end point just above the cube
//This of course assumes the cube isn't rolling around. If that's the case
//then these calculations get quite a bit more complicated
//Additionally the 0.01 might need adjusting if it's too high up off the cube
start.y += this.renderer.bounds.y/2 + 0.01f;
end.y += this.renderer.bounds.y/2 + 0.01f;
start.x -= this.renderer.bounds.x/2;
end.x += this.renderer.bounds.x/2;
Ray ray = new Ray(start, end);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, start.x-end.x) && hit.name == "mySphere")
{
//Theoretically, the sphere hit the top of the box!
}
}