что такое raycast unity
Physics2D.Raycast
Успех!
Благодарим вас за то, что вы помогаете нам улучшить качество документации по Unity. Однако, мы не можем принять любой перевод. Мы проверяем каждый предложенный вами вариант перевода и принимаем его только если он соответствует оригиналу.
Ошибка внесения изменений
По определённым причинам предложенный вами перевод не может быть принят. Пожалуйста попробуйте снова через пару минут. И выражаем вам свою благодарность за то, что вы уделяете время, чтобы улучшить документацию по Unity.
Параметры
origin | @param origin Стартовая точка фигуры в 2D пространстве. |
direction | @param direction Вектор, представляющий направление фигуры. |
distance | Maximum distance over which to cast the ray. |
layerMask | @param layerMask Фильтр для обнаружения коллайдеров только на определённых слоях. |
minDepth | @param minDepth Включает только объекты с координатой Z (глубиной) выше, чем это значение. |
maxDepth | @param maxDepth Включает только объекты с координатой Z (глубиной) меньше, чем это значение. |
Возврат значений
RaycastHit2D The cast results returned.
Описание
Casts a ray against colliders in the scene.
BoxCast, концептуально, это как протягивание коробки сквозь сцену в определенном направлении. Любой объект, вступающий в контакт с коробкой, может быть обнаружен и зарегистрирован.
This function returns a RaycastHit object with a reference to the collider that is hit by the ray (the collider property of the result will be NULL if nothing was hit). The layerMask can be used to detect objects selectively only on certain layers (this allows you to apply the detection only to enemy characters, for example).
Raycasts are useful for determining lines of sight, targets hit by gunfire and for many other purposes in gameplay.
Additionally, this will also detect Collider(s) at the start of the ray. In this case the ray is starting inside the Collider and doesn’t intersect the Collider surface. This means that the collision normal cannot be calculated in which case the collision normal returned is set to the inverse of the ray vector being tested. This can easily be detected because such results are always at a RaycastHit2D fraction of zero.
Physics.Raycast
Успех!
Благодарим вас за то, что вы помогаете нам улучшить качество документации по Unity. Однако, мы не можем принять любой перевод. Мы проверяем каждый предложенный вами вариант перевода и принимаем его только если он соответствует оригиналу.
Ошибка внесения изменений
По определённым причинам предложенный вами перевод не может быть принят. Пожалуйста попробуйте снова через пару минут. И выражаем вам свою благодарность за то, что вы уделяете время, чтобы улучшить документацию по Unity.
Параметры
origin | The starting point of the ray in world coordinates. |
direction | @param ray Начальная точка и направление луча. |
maxDistance | The max distance the ray should check for collisions. |
layerMask | A Layer mask that is used to selectively ignore Colliders when casting a ray. |
queryTriggerInteraction | Specifies whether this query should hit Triggers. |
Возврат значений
Описание
You may optionally provide a LayerMask, to filter out any Colliders you aren’t interested in generating collisions with.
Specifying queryTriggerInteraction allows you to control whether or not Trigger colliders generate a hit, or whether to use the global Physics.queriesHitTriggers setting.
This example creates a simple Raycast, projecting forwards from the position of the object’s current position, extending for 10 units.
Notes: Raycasts will not detect Colliders for which the Raycast origin is inside the Collider.
If you move Colliders from scripting or by animation, you need to allow at least one FixedUpdate to be executed so that the physics library can update before a Raycast will hit the Collider at its new position.
Параметры
origin | The starting point of the ray in world coordinates. |
direction | @param ray Начальная точка и направление луча. |
hitInfo | If true is returned, hitInfo will contain more information about where the collider was hit (See Also: RaycastHit). |
maxDistance | The max distance the ray should check for collisions. |
layerMask | A Layer mask that is used to selectively ignore colliders when casting a ray. |
queryTriggerInteraction | Specifies whether this query should hit Triggers. |
Возврат значений
Описание
Casts a ray against all colliders in the scene and returns detailed information on what was hit.
This example reports the distance between the current object and the reported Collider:
This example re-introduces the maxDistance parameter to limit how far ahead to cast the Ray:
Параметры
ray | @param ray Начальная точка и направление луча. |
maxDistance | The max distance the ray should check for collisions. |
layerMask | A Layer mask that is used to selectively ignore colliders when casting a ray. |
queryTriggerInteraction | Specifies whether this query should hit Triggers. |
Возврат значений
Описание
Параметры
ray | @param ray Начальная точка и направление луча. |
hitInfo | If true is returned, hitInfo will contain more information about where the collider was hit (See Also: RaycastHit). |
maxDistance | The max distance the ray should check for collisions. |
layerMask | A Layer mask that is used to selectively ignore colliders when casting a ray. |
queryTriggerInteraction | Specifies whether this query should hit Triggers. |
Возврат значений
Описание
This example draws a line along the length of the Ray whenever a collision is detected:
Упрощённые рейкасты в Unity
На данный момент я в основном занимаюсь визуализациями данных, работой с дополненной реальностью, AR/VR и интерактивными стендами на выставках. В одной из задач было необходимо визуализировать огромный граф с данными в виртуальной реальности, который состоял из порядка 10000 тысяч объектов. И классическая физика в Юнити оказалась слишком медленной. Но прежде чем “писать своё с блекджеком и куртизанками”, давайте пройдёмся по тому, о чём нужно знать и что нужно делать при работе с физикой Unity.
Советы и нюансы по работе с встроенной физикой
На самом деле большую часть про это можно прочесть в этом материале https://learn.unity.com/tutorial/physics-best-practices#5c7f8528edbc2a002053b5b4 Не хочется особо сильно повторяться про “простые коллайдеры лучше”, кроме самого важного совета, который я не устану повторять. Если объект подвижен и на нём есть коллайдер или триггер, то на нём должно быть Rigidbody. А вот из того, что тут не сказано в Unity есть возможность управлять обсчётом физики в ручную. В классе Physics во-первых, есть bool переменная autoSimulate (так же есть в настройках) и метод Simulate, чтобы посчитать кадр физики. В целом у этого есть две основные проблемы: это всё работает только в главном потоке и оно посчитает всё. Вот вообще всё. Коллизии, что там с джоинтами и т.п. И это не очень удобно как раз в случае описанном выше.
В общем в AR/VR задачах часто встречается такое, что сами по себе коллизии тебе не особо нужны. В первую очередь интересны рейкасты, и недостаток встроенной физики юнити (то есть интеграции PhysX) что нельзя пользоваться рейкастами просто отключив коллизии. Даже елси вы выключите всю матрицу со слоями коллизий система всё равно производит расчёты для коллизий. И это не позволяет решать какие-то задачи. В плюс к тому ресурсы в AR на мобильных телефонах или в VR на standalone системах (типа Oculus Quest) довольно ограничены. Поэтому экономить приходится на всём.
Собственно в задаче с графом, мне нужны были только рейкасты для того, чтобы отображать информацию по вершинам и перемещаться по графу.
Пишем своё или зачем нужно знать математику
Сферический коллайдер
Сферический коллайдер на самом деле покрывает большую часть необходимого в данной задаче. Считается он довольно просто, даже с получением позиции пересечения луча и коллайдера.
В контексте Unity проверка пересечения будет выглядеть вот так:
А теперь посмотрим, как выглядит математика сферического коллайдера. Из аналитической геометрии мы знаем, что если у нас есть сфера с центром (x0, y0, z0) и радиус r, то все точки (x, y, z) находящиеся на этой сфере можно описать, как:
запись в векторной форме этого выражения будет выглядеть
Уравнение же прямой выглядит, как
При существовании пересечения окружности и луча. P = p(t). И подставив всё в исходное уравнение окружности и раскрыв все скобки мы получим уравнение вида.
что в свою очередь является стандартным квадратным уравнением вида:
или если записать чуть более читаемо
и мы приходим к старому доброму школьному дискриминанту, что t так же равно
Мы знаем из математики, что если:
Дискриминант меньше нуля, то луч не пересекает сферу (так как не существует решений уравнения)
Дискриминант равен 0, то луч касается сферы в одной точке (касательная, ровно одно решение)
Дискриминант больше 0, луч пересекает сферу в двух точках (два решения)
Это уже спокойно превращается в код выше.
Для кубического коллайдера код можно посмотреть в репозитории и разобрать самостоятельно. Опирался на эту статью, но на данный момент там есть проблема с поворотами, так как куб описывается, как 2 точки угла куба. https://www.researchgate.net/publication/220494140_An_Efficient_and_Robust_Ray-Box_Intersection_Algorithm
Хватит бороться с Unity
Итак, коллайдеры есть. А что по лучам? На самом деле для меня самое странное во многих плагинах и библиотеках под Unity, что многие не используют фишки Unity, а пишут своё поверх Unity. Мы так делать конечно же не будем. В юнити есть замечательная вещь под названием EventSystem, про примеры использования которой я писал в этой статье. Но из важного для нашей системы она позволяет вешать на камеру рейкастеры, которые работают с интерфейсами IPointerDownHadler и т.п. на объектах. И ничего не мешает создать новый рейкастер под нашу систему рейкастов.
Мы просто наследуемся от класса BaseRaycaster реализуем метод Raycast, заполняя правильно List resultAppendList и всё, наша физика работает с EventSystem.
Метод ComputeRayAndDistance формирования луча и расчёта индекса дисплея нужен для поддержки нескольких экранов. В целом в Unity много крутых систем, и я очень рекомендую изучить то, как они кастомизируются.
А что по производительности?
Я сделал несколько тестов для демонстрации работы данного подхода.
Выигрыш на большом числе объектов (учитывая что в видео ещё на перфоманс влияет Unity Recorder) довольно ощутимый. Самостоятельно можно посмотреть и протестировать в репозитории на своём железе. Но конечно же система даже на CPU работает быстрее, чем PhysX в подобном случае.
А можно ли сделать быстрее?
Да, это довольно простая система, которая была написана за несколько часов, в которой на данный момент даже не весь функционал поддерживается. Но путей к улучшению здесь ещё много. В первую очередь конечно же логика обхода коллайдеров. Сейчас система работает на линейной скорости, что неплохо, но можно в разы лучше. Для этого нужно интегрировать технику под названием “двоичное разбиение пространства” (Binary Space Partitioning или BSP). Построение BSP-дерева по сути позволяет нам в случае огромного числа объектов увеличить скорость обсчёта коллизий за счёт лучшего разбиения пространства. Но тут уже в ход идут нюансы. Чтобы оно работало действительно быстрее нужно либо формировать дерево в ручную, когда объекты (в случае графа актуально) нашли точку равновесия и больше не перемещаются. Либо же писать алгоритм динамического изменения дерева, что в общем добавит нагрузки на систему и в этом случае уже нужно искать некий баланс между алгоритмом обновления BSP дерева и поиском рейкастов. В целом BSP это довольно полезная штука. Она используется для occlusion culling и других вещей в трёхмерной графике.
В заключении
Полное решение вы можете найти по ссылке. Может кому-то пригодится и будет полезно, если вдруг нужно будет визуализировать огромный массив данных. Надеюсь появится время написать ещё про интересную укладку графов в трёхмерном пространстве и компьют шейдеры, если кому-это данная тема интересна.
Game Dev Beginner
Raycasts in Unity, made easy
In Unity by John French June 18, 2021 8 Comments
The Raycast function is extremely useful for creating connections between objects in Unity.
For example, if you want to select an object just by looking at it or clicking on it.
Or if you want to shoot an object with a weapon or obstruct a line of sight.
Or perhaps if you need to check how high the player is from the ground, or what it is they’re standing on.
That’s where Raycasts can help.
So… what is the Raycast function and how does it work?
Raycast in Unity is a Physics function that projects a Ray into the scene, returning a boolean value if a target was successfully hit. When this happens, information about the hit, such as the distance, position or a reference to the object’s Transform, can be stored in a Raycast Hit variable for further use.
This makes Raycast extremely useful for getting information about other objects, performing ground checks or, generally, doing anything that involves a line of sight connection between two objects.
While Raycast can be very straightforward to use, it can be a little unintuitive at first.
And if you’re new to Unity, the large number of features available, not to mention the many different versions of Raycast, each with their own quirks, can make it daunting to use at first.
But don’t worry, because, in this article, I’ll show you everything you need to know about using Raycast in Unity, step by step,
Here’s what you’ll find on this page:
How to use Raycast in Unity
The basic version of Raycast is made up of three different parts:
Here’s how each of them work…
How to create a Ray
A Ray is simply a data struct in Unity that represents a point of origin and a direction for the Ray to travel.
In its most basic form a Ray is an origin and a direction.
The origin is the position in the world that the Ray will start from and takes a Vector 3 value.
While the direction property takes a trajectory in the form of a normalised Vector 3.
Normalising a vector limits its magnitude, which is the length of the Vector, to 1, which is useful for representing a consistent direction.
There are a few ways you can create a new Ray.
You can create a Ray manually,
Like this:
Or, alternatively, you can use one of the helper functions to create a Ray automatically, such as a Ray that starts at the center of the camera’s viewport,
Like this:
In the above example, the 0.5f values represent the middle of the viewport in both dimensions.
Or from the Mouse Position on the screen,
Like this:
These helper functions make it easy to create a Ray from an existing point in the world.
However, while you can cache a reference to the Ray you create, you’ll still need to update it every time you use it.
So, for example, if your Ray’s origin and direction are going to be different every frame, you’ll need to update the Ray every frame too.
Like this:
Otherwise, when you come to use the Ray, it won’t be in the right position.
How to visualise Raycast in the scene
Using Debug.DrawRay, you can check if your Rays are going where they’re meant to.
Did you know you can visualise Rays in the game world?
The Debug Class includes a function, Draw Ray, that allows you to render a Ray in the world.
Like this:
This function can be useful for making sure your Ray is going where you want it to.
For example, I could define a Ray variable for use in Raycast functions.
Like this:
And then, render a visible line using Draw Ray, passing in the same values as I used to create my Ray.
Like this:
Notice that I’ve multiplied the direction value by 10.
This is because the Vector 3 that’s used for direction in Ray variables is normalised (meaning that it will have a magnitude, the length, of 1).
Multiplying the direction value by the distance of the Ray, in this case by 10, means I can match the length of the Ray I actually use with the length of the drawn line.
Once you’ve decided where your Ray will start from and which direction it’ll go in, you’ll need a place to store the data you get from it.
That can be done with a Raycast Hit variable.
How to use the Raycast Hit variable
The Raycast Hit variable is a data struct that stores information about Ray’s collision.
It records information like where the hit happened in the world, what object did the Ray collide with and how far away it was from the origin of the Ray.
To use it, all you need to do is declare it:
Then, later, when you use Raycast to fire a Ray into the scene, you’ll have a place to store any information retrieved from the hit.
For example, you can get the position of the hit in the world using RaycastHit.point:
Or the distance from the Ray’s origin to the point of impact using RaycastHit.distance:
You can also get information about the Collider that was hit, such as its Tag.
Or, you could even use Raycast Hit to get a reference to an object’s Transform:
How to get the first object hit by a Raycast
Using a Raycast Hit variable with Raycast will store information about the first object that is hit by the Ray.
This is the default behaviour and is typically how you’d expect the Raycast functionality to work.
This means that, if it’s not working how you expect it to, it’s likely that there’s a different issue that’s causing the problem.
While the Ray and Raycast Hit variables define where a Ray will go and how information from hits will be stored, they don’t do anything on their own.
So, to actually fire Rays into the scene, and check if they hit anything, you’ll need to use the Raycast function.
Here’s how to do it.
How to use the Raycast function
The Raycast function in Unity allows you to check if a Ray collides with another object in the scene, saving the hit data to a Raycast Hit variable if it does.
There are several different versions of Raycast, each from different classes, that can be used in different ways, however, one of the most common ways to use Raycast is using the Physics Class, which returns a boolean true or false, depending on if the Ray hit anything.
Like this:
This will fire the ray that you’ve created into the scene and save information about anything that’s hit to the Raycast Hit variable you declared.
This works because of the Out Keyword in the function.
What is the Out Keyword in Unity?
The out keyword in Unity is used to return extra information from a function.
Normally, when calling a function, you pass data into it via its parameters and get information back via its return type.
It’s likely that you’ll have already written functions with a void return type, meaning they don’t return any information.
Other functions, on the other hand, may specify what type of data is returned from the function when it runs.
For example a bool:
In this example, Is Above Ten returns a true or false condition depending on the number that’s passed into it.
Meaning you can set a boolean variable just by calling the function.
Like this:
What has this got to do with Raycasts?
I’m getting to that…
A function can only have one return type.
However… the out keyword allows you to return extra information from a function.
For example… I could make the function return a bool, but also store a string based on the result.
Like this:
The out keyword means that, instead of passing information into the method via that parameter, extra data will be returned back from it and will need a place to be stored.
With Raycast, you’ll commonly see the out keyword used to store the Raycast Hit data, if there is any.
Raycast takes an out Raycast Hit argument, meaning that a Raycast Hit variable will need to be specified when you call it.
Then when the function runs, Raycast Hit data will be stored in the variable you specified, allowing you to access it.
The out keyword allows you to save information in addition to the return type of Raycast.
So what is the return type?
Physics.Raycast has a bool return type, which returns true if the Ray hits a target.
This means that you can place the Raycast function in an if condition.
Like this:
Using Raycast in this way means that code inside the if condition will only run if the Ray actually hits something.
This is useful because it means that you can limit your code to only use Raycast Hit data when it actually exists.
Or to only perform an action if the Raycast was successful.
Whether a Raycast was successful or not typically depends on if it hit something, however, because of the additional features of the Raycast function it’s possible to limit what counts as a successful hit in other ways as well.
Such as limiting the distance the Ray can travel, excluding certain layers or choosing if trigger colliders should be ignored.
Which of these settings are available to you depends on which overload method of the Raycast function you decide to use.
The different features of the Raycast function
There are many different versions of the standard Raycast function and each one offers slightly different functionality.
For example, some versions of Raycast only take a few parameters and perform a simple function in return, while others accept more complex sets of data and do more with it.
These different versions are Raycast’s overload methods.
What’s an overload method in Unity?
An overload method is simply an alternative version of a method that takes a different set of parameters and that may return a different type of value.
For example, the most basic version of Physics.Raycast takes only one parameter, a Ray:
While using a different overload method allows you to specify a Ray, a Raycast Hit variable, a Max Distance, a Layer Mask (to include or exclude certain layers from being hit) and a Query Trigger Interaction setting, which determines if Trigger Colliders can be hit or not.
Like this:
Overload methods allow you to pass different information into a function to achieve different results.
How do you select an overload method in Unity?
A specific overload is defined by the parameters that are passed into it and their order.
So, to select a certain overload, simply pass in the set of parameters that match the overload you want to use.
How can you tell which parameters you need to enter?
Depending on your text editor, you may be able to preview what other functionality a method can support, as you’re writing it.
Like in Visual Studio, using the up and down arrow keys:
Each overload method is made unique by the parameters it accepts, and no two overloads can accept the same parameters in the same order.
Because of this, to use an overload method, you’ll need to enter the exact set of parameters it requires, in the right order.
Otherwise, it won’t work.
This can sometimes mean that, to use a specific overload, you may need to pass in parameters for functionality you don’t actually need.
Raycast supports a large number of overload methods (16 at the time of writing this) so chances are good that one of them will offer the functionality you want with minimal extra fuss.
So what can you do with different Raycast overload methods?
Limit the Raycast range by entering a max distance
Most of the overload methods available for Physics.Raycast also allow you to specify a max distance as a float value.
Like this:
Setting a max distance can be useful for creating distance-limited functionality, such as weapons that can only shoot so far, or simply to avoid complications from Rays that extend infinitely across your scene. Not only is it useful, it’s also good for performance to limit the extent of a Ray, which is why it’s no surprise that many of Raycast’s overload methods (12 to be precise) accept a parameter for max distance.
While setting a distance can be useful for limiting the reach of a Ray, there will often be times when Raycasts intersect with many different types of collider.
How you distinguish between the different types of objects in your game is entirely up to you.
However, one option that works particularly well with Raycasts, is to use layers.
How to use Layer Masks with Raycasts
One of the most helpful features of the Raycast function is the ability to filter out colliders depending on their layer.
This allows you to completely ignore objects on layers that aren’t intended to collide with Raycasts.
As you can imagine, this can be extremely useful when you’re working with a large scene, with many different types of objects and colliders and you only want to check for collisions against some of them.
So how does it work?
For example, let’s say that all of the environment objects in my scene are on the same layer, the world layer, and that I only want to detect collisions on that layer.
All I need to do is declare a public Layer Mask variable…
Like this:
Set it in the Inspector to match the world layer:
And then, in my script, pass the Layer Mask variable into the Raycast function.
Like this:
In this case, I’m using an overload method that accepts a Ray, a Max Distance and a Layer Mask variable.
In order to use this version of Raycast I have to add all of those parameters in the correct order.
Otherwise, it won’t work correctly.
How to enter the layer number directly when using Layer Masks with Raycasts in Unity
Using a public Layer Mask variable is the easiest way to use Layer Masks with Raycasts.
However, if you want to do it all in scripting, and pass in the value of the Layer Mask directly, here’s how to do it.
If you’re anything like me, and because the Layer Mask parameter takes an int value, you might assume that you can just enter the number of the layer, for example, layer 9, in the Raycast function and that will work.
This is because, while the Layer Mask value is an int, Unity uses the binary representation of the integer to decide which layers will be checked and which will not.
Imagine all of Unity’s 32 possible Layers as a row of zeroes, starting with the first layer (layer 0) on the right.
Now, let’s say that I want to check Raycasts against one of those layers.
For example, layer 9.
Layer 9 is tenth in the list, so if I change the tenth zero from the right to a 1, like this:
Changing the tenth digit from the right to a 1 represents the 9th layer.
Unity now knows that I only want to check Raycasts against layer 9.
Except that this is still a binary value. It’s still not the integer number that the Raycast function requires.
So how do you convert it?
Binary numbers work by counting, from left to right, which multiples make up a number.
For example, the number 8, in binary, is 1000. Because it is made up, from right to left, of no ones, no twos, no fours and one eight:
Whereas Nine, would look like this:
The binary value I’m using, when converted to an integer, is 512.
The decimal value for the 9th layer is 512.
Which I can add directly to the Raycast function to indicate that I want to check collisions on layer 9.
Like this:
I could even use the binary value to indicate multiple layers.
For example, layer 9 and layer 4:
The decimal value for the 9th and 4th layers is 528.
Which works out to be 528.
How to convert an Int to a Layer Mask value
While converting a binary value to an integer works, it isn’t the most convenient method.
Especially if all you want to be able to do is enter the integer value of the layer you want.
Luckily there’s an easy way to directly add layer numbers in scripting.
The bitwise left shift operator.
The bitwise left shift operator ( Physics.Spherecast
Spherecast works a lot like the standard Raycast except that, instead of projecting a thin line, it projects a sphere into the Scene.
Basically, this works like a thicker version of Raycast, where the sphere’s radius determines how thick, in units, the Ray is.
Spherecast is useful for determining if a specific sized object will fit into a space or for projecting a wider, shaped Ray into the world.
For example, a large laser beam, with a wide radius, that might be difficult to create with colliders or a standard Ray, could be easily created with Spherecast.
Functions that work in a similar way, but that use different shapes, include CapsuleCast and BoxCast.
Plane.Raycast
Plane.Raycast works by detecting a hit against an invisible plane in the Scene.
This method is incredibly useful for calculating an intersecting position against an infinitely large flat surface (such as a wall or floor).
It’s also very lightweight and simple to use, as it doesn’t need a Collider or even another Game Object to work.
You might use Plane.Raycast to create cursor interactions in world space. For example, by firing a ray from the mouse position and measuring where it intersects with the plane.
For more on Plane Raycast, try my article on getting the mouse position in world space in Unity.
Should you use Raycast in Fixed Update or Update?
In many cases, it’s better to use Raycast in Update, however, this largely depends on what you’re trying to do.
Typically, because Raycast is a Physics function, you might think to put Raycast in Fixed Update, which is called every physics step, instead of Update, which is called every frame.
Fixed Update is designed to perform actions in sync with the physics system, which will often run at a different frequency to Update.
If the game’s framerate is low, then Fixed Update may run faster than Update, being called several times during a frame. However, if the game’s framerate is high, Fixed Update may not be called at all during a frame.
A typical use of Fixed Update is for continuous physics functions. For example, when applying force to a Rigidbody, doing it in Fixed Update means that the force is applied in sync with the physics system that is reacting to it.
While Raycast is a physics function, what you’re doing with it may actually be more suited to Update.
A lot of the time, you’ll be using Raycast as a check.
For example, was something in the line of fire when I clicked the mouse button?
Was the player close enough to the ground when the jump button was pressed?
Is the player looking at the object they just tried to pickup?
All of these examples are dependent on a player input condition that’s designed to be used Update, and trying to put functions like that in Fixed Update is going to cause problems.
For example, in extreme circumstances where the framerate of the game is slower than the physics system, a click that’s measured on a per-frame basis will be true every time Fixed Update is called during that frame. This would mean that even though you clicked once, the action could be called multiple times.
Whereas, if the physics system is running much slower than the framerate, Fixed Update might not be called while the button is pressed, and the click may not be recognised at all.
Instead, even though Raycast is Physics-based, placing the mouse click condition in Update, where it would normally be, solves this problem:
This works because the Raycast is a one-time event, that’s simply reporting the state of the Physics system at the time of the check.
But what about continuous checks?
There may be times when you’re making constant Raycast calls to check for colliders.
So should they be made from Update, or Fixed Update?
Again, it depends on what you’re trying to do as a result of the Raycast check.
If the resulting action of the continuous check is something you would normally put in Update, then use Update.
This will keep the action in sync with the game’s framerate.
If the resulting action is something you would normally place in Fixed Update, then it’s a good idea to use Fixed Update for the Raycast check and the resulting action.
For example, making an object hover by applying force to a Rigidbody when it gets close to the ground.
Like this:
Both the Raycast check and the hover action are designed to work with Physics steps so, in this scenario, you’ll get more consistent results by using Fixed Update.
How to use Raycast in Unity in 2D
Raycast is a physics-based function, meaning that, depending on which version you use, it derives from either the Physics Class or a related class, such as the Collider Class.
In Unity, the 3D and 2D physics engines are separate, meaning that, if you want to use Raycast in 2D, you’ll need to use a different version of Raycast that derives from the 2D physics engine and its classes. For example, Physics2D.Raycast or Collider2D.Raycast.
Otherwise, it won’t work.
Like this:
Raycasts in 3D vs Raycasts in 2D
Generally, the 2D versions of Raycast work in a similar way to the standard, 3D versions, but with a few key differences.
For example, while many versions of Raycast return a boolean value (which returns true if the Ray hits something and false if it doesn’t), this isn’t the case with the 2D versions of Raycast.
Instead of returning a boolean, Physics2D.Raycast returns a Raycast Hit 2D value.
If the Raycast hits a collider, the function will return Raycast Hit 2D information. If it doesn’t hit anything, it returns null, which is why it’s still possible to use Physics2D.Raycast in an if condition, even though it doesn’t return a boolean value.
However, this does mean that, unlike the 3D version, where you would normally save hit data using the out keyword, if you want to access information about what was hit, you’ll need to declare a Raycast Hit 2D variable first.
Like this:
Collider 2D Raycast ignores its own collider
Just like the 2D version of the standard Raycast function, the 2D version of Collider.Raycast works differently to its 3D counterpart.
Unlike the 3D version of Collider.Raycast, which takes a Ray parameter and looks specifically for the one collider that it’s called from, Collider2D.Raycast fires a ray from the collider it’s called from and looks for other colliders to hit (while ignoring its own).
Collider2D.Raycast has an integer return type, which is equal to the number of colliders that were intersected by the Raycast, storing the results in an array.
Which means, to use Collider2D.Raycast, you’ll need to declare and initialise an array to hold the results.
To create a Raycast Hit 2D array, you’ll need to declare and initialise it in your script. This is because the Raycast Hit 2D data type won’t appear in the Inspector so, unlike other arrays, you won’t be able to set the length of the array manually.
Like this:
This will create a new Array with a length of Ten.
The length of the array determines how many Colliders can be counted by the Raycast function.
So, for example, if you initialise the array at ten, even if the ray intersects 12 colliders, the integer value that you get back will be capped at ten.
Like this:
Collider2D.Raycast works in a similar way to the Non-allocating version of Raycast All. Except that, in 2D, Raycast All Non-Alloc will also detect colliders that overlap the ray’s origin.
Which can be inconvenient if you’re calling the function from an object with a collider that you want to ignore.
Instead, Collider2D.Raycast ignores its own collider and looks for others, without generating any garbage.
This is because it reuses the same fixed array instead of making a new one each time.
There’s also an alternative version of Collider2D.Raycast that stores its results in a List instead of an array:
This is useful when you want to limit the garbage allocation of the Raycast function but you don’t want to place a limit on the number of objects that can be detected, as the List will be resized, but only as needed when the function is called.
The 2D version of Raycast All sorts its results
Unlike the 3D version of Raycast All, which stores results in an undefined order, the 2D version of Raycast All sorts its results by distance from the origin.
This is useful if you want to, for example, destroy objects in a line or affect multiple objects based on their distance from the Ray’s origin, without needing to sort the array.
Use Contact Filters for advanced filtering in 2D
Unlike the 3D version of Raycast, which relies on manually setting a Layer Mask or trigger settings in the function’s parameters, Raycast in 2D allows you to use a Contact Filter 2D parameter to easily include or exclude certain objects from being hit.
It can also be declared publicly, meaning that you can apply the settings you want directly in the Inspector.
Like this:
Contact Filters allow you to set multiple filtering options.
It can then passed into any overload methods of Raycast that support using Contact Filters.
Such as this one:
If, however, you want to use an overload method of Raycast that requires a Contact Filter, but you don’t actually want to use a Contact Filter, you can do that too.
Simply declare a Contact Filter variable and use the No Filter function to prevent the filter from excluding any results.
Like this:
Now it’s your turn.
Now I want to hear from you…
How are you using Raycasts in Unity?
What’s your best Raycast tip that you know others will find useful?
And how will you use the information on this page in your own project?
Let me know by leaving a comment below.
by John Leonard French
Game audio professional and a keen amateur developer.
Get Game Development Tips, Straight to Your inbox
Get helpful tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.
My favourite time-saving Unity assets
Rewired (the best input management system)
Rewired is an input management asset that extends Unity’s default input system, the Input Manager, adding much needed improvements and support for modern devices. Put simply, it’s much more advanced than the default Input Manager and more reliable than Unity’s new Input System. When I tested both systems, I found Rewired to be surprisingly easy to use and fully featured, so I can understand why everyone loves it.
DOTween Pro (should be built into Unity)
An asset so useful, it should already be built into Unity. Except it’s not. DOTween Pro is an animation and timing tool that allows you to animate anything in Unity. You can move, fade, scale, rotate without writing Coroutines or Lerp functions.
Easy Save (there’s no reason not to use it)
Easy Save makes managing game saves and file serialization extremely easy in Unity. So much so that, for the time it would take to build a save system, vs the cost of buying Easy Save, I don’t recommend making your own save system since Easy Save already exists.
Comments
Taking the intermediate 3D Unity course from Udemy for RPG, the instructor just tells us to use the raycast method for point & click to move a character to a location or to fight with the enemy. His explanation of the raycast method I found rather cursory and thus a bit confusing. I very much enjoyed reading your comprehensive explanation that I can now use in many other ways than I was taught in the Udemy course. You explain things very plainly and I am not confused. However, I don’t like all of the advertising. That is what makes reading your explanations very irritating to my eyes and I constantly lose focus.
Thanks Mark! And thank you for your feedback regarding the ads. They make this free for everyone, so they’re important, but user experience is very important to me too so I appreciate the feedback and I’ll review my placement settings.
WHy is it that when using multiple raycasts the rays don’t rotate correctly with the object. Code below.
public class RaycastForCollisions : MonoBehaviour
<
public float sensorLength = 5f;
public float sensorPosOffset = 5.639f; // this is half of the collider length when it’s facing world forward
public float frontSidePosOffset = 1.5f;
public float frontSensorAngle = 30f;
void Update()
<
CheckForCollisions();
>
private void CheckForCollisions()
<
Vector3 startPos = transform.position + (transform.forward) + transform.up;
Vector3 direction = transform.forward;
Ray ray = new Ray(startPos, direction);
RaycastHit hit;
// origin, direction, hit info, maxdistance
// center raycast
if (Physics.Raycast(ray, out hit, sensorLength))
<
//Debug.Log(“Center HIT”);
Debug.DrawRay(startPos, direction, Color.red);
>
else
Debug.DrawRay(startPos, direction, Color.green);
// right side raycast
startPos.x += frontSidePosOffset;
if (Physics.Raycast(ray, out hit, sensorLength))
<
Debug.Log(“Right HIT”);
Debug.DrawRay(startPos, direction, Color.red);
>
else
Debug.DrawRay(startPos, direction, Color.green);
// right side angular raycast
//Vector3 angularDirection = Quaternion.AngleAxis(frontSensorAngle, ds.rb.transform.up) * ds.rb.transform.forward;
//if (Physics.Raycast(origin, angularDirection, out hit, sensorLength))
// <
// Debug.Log(“HIT”);
// Debug.DrawRay(origin, direction * sensorLength, Color.red);
//>
//else
// Debug.DrawRay(origin, direction * sensorLength, Color.green);
//left side angular raycast
//angularDirection = Quaternion.AngleAxis(-frontSensorAngle, ds.rb.transform.up) * ds.rb.transform.forward;
//if (Physics.Raycast(origin, angularDirection, out hit, sensorLength))
// <
// Debug.Log(“HIT”);
// Debug.DrawRay(origin, direction * sensorLength, Color.red);
//>
//else
// Debug.DrawRay(origin, direction * sensorLength, Color.green);
>
>
Hi, what are you trying to do and what’s going wrong with it? At first glance, it looks to me like you’re checking for one raycast? Ray, which doesn’t appear to change throughout?
Hi John, thanks for taking the time to unpack this area and explain it so clearly! As a Unity beginner, this was exactly the level of detail I needed to get a confident start. Thanks! : )
Hi John, fantastic post. IT is the ultimate guide for the raycast on Intenet. Now I am struggling with a question:
I am showing up a text UI when the raycast detects a specific object by tag. How do I trigger to hide the text UI when I am not looking at that object.
Currently, I am using an “else” to call the hide text UI function. But sometimes, it won’t be triggered.
if (Physics.Raycast(ray, out hitInfo, maxDistance:3))
<
ShowUI();
>
else
<
HideUI();
>
I kind of understand why this code won’t work. Since the distance is 3, when I suddenly move my view away from the target object to somewhere else, say sky, it may not trigger the ray at out. It won’t get into the “else” block.
Is there any appropriate approach for this?
Hi Aaron, the Raycast function usually returns a bool, so you should get to the else block if there’s nothing to hit, or what you hit doesn’t match the parameters of the Raycast function. So, if I’m remembering this right, this should work. Where are you checking the tag? The hitinfo variable probably doesn’t clear to null, so you will probably want to check for the tag inside the Raycast if statement. That way IF there’s a valid target, also check if it’s got the right tag. Hope that helps.
Leave a Comment Cancel reply
Welcome to my blog
I’m John, a professional game composer and audio designer. I’m also a keen amateur developer and love learning how to make games. More about me
Latest Posts
Thanks for Your Support
Some of my posts include affiliate links, meaning I may earn a commission on purchases you make, at no cost to you, which supports my blog.
For more information view my Affiliate Policy.