Исправление кода на C# для Unity. Physics Raycasting
У меня есть скрипт в Юнити, который служит для открытия двери при помощи анимаций. Проблема такая: луч, при помощи которого я открываю дверь проходит сквозь объекты. Подскажите пожалуйста, как это можно исправить.
Код:
using System.Collections;
using UnityEngine;
public class Opener : MonoBehaviour
{
[SerializeField] private Animator anim;
[SerializeField] private LayerMask Layer;
[SerializeField] private float distance;
[SerializeField] private GameObject cam;
bool open=false;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
RaycastHit hit;
Ray ray = new Ray(cam.transform.position, cam.transform.forward);
if (Physics.Raycast(ray, out hit, distance, Layer))
{
if(Input.GetMouseButtonDown(0) && open==false)
{
anim.SetBool("is_open",true);
open = true;
}
else if(Input.GetMouseButtonDown(0) && open==true)
{
anim.SetBool("is_open",false);
open = false;
}
}
}
}
Проблема в том, что ты не проверяешь, что именно попало под луч.
if (Physics.Raycast(ray, out hit, distance, Layer))
{
// Проверь, что hit.collider принадлежит нужному объекту
if (hit.collider.gameObject == gameObject) // или более сложное условие
{
// Дальше твой код с анимацией
}
}
Еще вариант - используй Physics.RaycastAll и перебирай все попавшие объекты, выбирая ближайший с нужным Layer.
вот чо выдал передовой ии: Проблема в том, что ваш луч проходит сквозь другие объекты из-за неправильной настройки LayerMask. Вот исправленный код с пояснениями:
using UnityEngine;
public class Opener : MonoBehaviour
{
[SerializeField] private Animator anim;
[SerializeField] private LayerMask interactableLayer; // Переименовал для ясности
[SerializeField] private float distance = 3f; // Добавил значение по умолчанию
[SerializeField] private Camera cam; // Лучше использовать тип Camera
private bool isOpen = false;
void Update()
{
Ray ray = new Ray(cam.transform.position, cam.transform.forward);
if (Physics.Raycast(ray, out RaycastHit hit, distance, interactableLayer))
{
// Проверяем, что попали именно в этот объект
if (hit.collider.gameObject == gameObject)
{
if (Input.GetMouseButtonDown(0))
{
isOpen = !isOpen;
anim.SetBool("is_open", isOpen);
}
}
}
}
}
Ключевые исправления:
Проверка hit.collider.gameObject == gameObject - убеждаемся, что луч попал именно в нашу дверь
interactableLayer должен включать только слой, на котором находится дверь
Упрощена логика открытия/закрытия (используется переключение состояния)
Настройки в Unity:
Выделите дверь в сцене
В инспекторе задайте ей отдельный слой (например, "Door")
В компоненте скрипта выберите этот слой в поле interactableLayer
Теперь луч будет реагировать только на саму дверь и не будет проходить сквозь другие объекты.