1
\$\begingroup\$

I use this script to build buildings on my terrain, and it works with the collider somehow. But I don't understand what it is that the raycast does to find the right place to put my building.

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
    farmhide.transform.position = hitInfo.point;

    farmhide.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
}

What is it that this code is doing?

\$\endgroup\$
  • \$\begingroup\$ A Raycast will cast the ray. the hit will be the object that the ray contacts. you can retrieve the point in space where that hit intersects by getting the hit.point. the collider is the collider that is attached to the object you hit with the ray and can be retrieved with hit.collider check out the Unity documentation for Raycasthit.collider \$\endgroup\$ – Justin Markwell Aug 10 at 17:54
  • \$\begingroup\$ Is there a way to make it work with Tag It works with all Collider in Scene \$\endgroup\$ – NADER LABBAD Aug 10 at 17:57
  • \$\begingroup\$ you can add a check for a tag if need be. it would be something like if(hit.collider.gameObject.tag == "Tag"){//DoStuff} \$\endgroup\$ – Justin Markwell Aug 10 at 18:00
  • \$\begingroup\$ so Anything crouse Touch any GameObject = hit and hit have Collider from GameObject \$\endgroup\$ – NADER LABBAD Aug 10 at 18:01
  • \$\begingroup\$ for the most part that will be true. You can also specify layers that the raycast will not interact with also but otherwise yes the Ray will will hit objects that have a collider attached \$\endgroup\$ – Justin Markwell Aug 10 at 18:07
3
\$\begingroup\$

A raycast is like shining a laser pointer in your scene, to see what the laser hits.

It takes a starting point and a direction as input (together, they make a "ray").

The physics engine takes this point and sweeps it along that direction. As it goes, it searches through all the physics colliders in your scene to check whether the point hits any of them during its travel.

(This is a simplification - in reality the engine has lots of clever acceleration structures and math so it can do this efficiently without looking at every collider or checking every point along the line one by one)

If it finds a collider that's in the path of the travelling point, it returns "true," meaning "yes, I found a hit." If you've provided an out RaycastHit parameter, it will store information about the first hit - the closest object along the ray.

From that RaycastHit, you can learn a lot about the intersection:

  • hitInfo.collider will give you the Collider component that the ray hit. You can use this to get the hit object's GameObject and check its tag with hitInfo.collider.gameObject.CompareTag("someTag"), for example.

  • hitInfo.point will tell you the position in world space where the ray hit the surface of the collider.

  • hitInfo.normal will tell you the direction that the surface of the collider is facing at the point you hit. Your script uses this to orient the buildings to point directly out from the ground, instead of diagonal to the surface.

  • hitInfo.rigidbody will give you the physics Rigidbody that owns the collider you hit, if it was a dynamic or kinematic object.

  • etc.

If you don't want to search every collider in your scene, one of the best ways to control the raycast is to use Physics Layers.

You can expose a public LayerMask raycastLayers; variable in your script, so you can choose in the Inspector which physics layers you're interested in.

Then you can modify your raycast like so:

bool hitSomething = Physics.Raycast(
                     ray,                           // Point + direction to sweep
                     out hitInfo,                   // Destination for hit information
                     float.positiveInfinity,        // Change this to limit the ray length
                     raycastLayers,                 // Only hit colliders on these layers
                     QueryTriggerInteraction.Ignore // Ignore trigger colliders
                   );

if (hitSomething) {...

This is more efficient than checking for specific tags, because it lets you filter out false positives at the source.

\$\endgroup\$
  • \$\begingroup\$ hey, could you edit your answer to explain this line of code? if (Physics.Raycast(ray, out hitInfo)) \$\endgroup\$ – Millard Sep 15 at 0:03
  • \$\begingroup\$ That line fires a ray, stores information about what it hit (if anything) in the hitInfo variable, and then if it did hit something, proceeds into the body of the if. If the raycast did not hit anything, then it skips the if body and continues to any else/else if clauses, or continues executing the code afterward. \$\endgroup\$ – DMGregory Sep 15 at 0:12
  • \$\begingroup\$ Thank you, that's helpful :) \$\endgroup\$ – Millard Sep 15 at 0:34
  • \$\begingroup\$ hey, does a RaycastHit variable return a float or a vector3? \$\endgroup\$ – Millard Sep 15 at 0:48
  • \$\begingroup\$ What does the documentation say about the RaycastHit type? \$\endgroup\$ – DMGregory Sep 15 at 0:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.