Unity, C# — указатель с помощью мыши

#c# #unity3d

Вопрос:

В настоящее время я работаю над указателем, который будет визуально отображать, куда именно в данный момент указывает плеер. Предполагается, что у этого есть 2 функции:

  1. укажите на середину экрана
  2. позвольте игроку взаимодействовать с тем, на что он указывает (так как у указателя есть коллайдер).

код:

 public class MousePosition3D : MonoBehaviour {
[SerializeField] private Camera mainCamera;

private void Update()
{
    Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
    if (Physics.Raycast(ray, out RaycastHit raycastHit))
    {
        transform.position = raycastHit.point;
    }
}}
 

Что делает приведенный выше код, так это устанавливает преобразование.положение указателя на ближайший объект, на котором находится коллайдер. Это отлично работает, но когда я добавляю коллайдер к своему указателю (чтобы позволить игроку взаимодействовать с другими объектами), он начинает бесконечно зацикливаться на объекте, где находится мой POV, поскольку каждый кадр сталкивается с его собственным коллайдером, постоянно меняющим положение.

Видео для справки: https://vimeo.com/606446838

Кто-нибудь знает, как это исправить? Или, может быть, есть лучшая альтернатива? Моя цель — разместить указатель в середине экрана (перемещение и поворот камеры выполняются отдельно) и позволить игроку взаимодействовать с другими объектами в сцене.

Ответ №1:

Установите свой коллайдер курсоров на выделенный слой

Затем вы можете игнорировать этот конкретный слой при PhysicsRacast использовании, например, a LayerMask .

 // Configure this via the Isnpector and select only layers you want to hit 
[SerializeField] private LayerMask layersToHit;

private void Update()
{
    Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);

    if (Physics.Raycast(ray, out var raycastHit, Mathf.Infinity, layersToHit))
    {
        transform.position = raycastHit.point;
    }
}
 

или, в качестве альтернативы, установите только те слои, которые вы хотите игнорировать и использовать

 // Configure this via the Isnpector and select only layers you want to ignore
[SerializeField] private LayerMask layersToIgnore;

private void Update()
{
    Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);

    // The "~" inverts the bitmask so we hit every layer except the ones selected in the mask
    // see https://docs.microsoft.com/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators#bitwise-complement-operator-
    if (Physics.Raycast(ray, out var raycastHit, Mathf.Infinity, ~layersToIgnore))
    {
        transform.position = raycastHit.point;
    }
}
 

Комментарии:

1. -слоерсТоХит, ты что, собирался писать? Многослойность ?

2. @Лоран нет … Я действительно хотел написать ~layersToHit 😉

3. О, это побитовый оператор, никогда такого раньше не видел.. Спасибо, что просветили меня ! 🙂