Как правильно отразить лазер от коллайдера в Unity 2D?

Я пытаюсь создать игру, в которой нужно стрелять лазером по объектам и отражать его от объектов, но кажется, что иногда лазер проходит сквозь объекты. Я заметил, что второй луч будет заканчиваться в начале сцены, а не отражаться от объекта, даже если это означает прохождение через объект.
Вот изображение того, что я имею в виду:Иногда он отражается от объекта, но все равно проходит через начало координат.

Это мой код для размышлений:

if (hit.collider.gameObject.tag == "Reflect"){ 
    hit2 = Physics2D.Raycast(hit.point, -hit.point); //The problem is probably here 
    Debug.DrawLine(hit.point, hit2.point); 
    lineRenderer.SetPosition(2, hit2.point);

    }

Я пробовал использовать метод Vector2.Reflect, но он делает то же самое. Я пробовал использовать hit.normal, но это тоже не работает. Я также пробовал использовать луч и устанавливать направление, противоположное направлению луча, но это не сработало.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
103
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

определенно есть более совершенный способ, но я бы это сделал вот как. вам нужно знать, как нарисовать луч. Точка отражения и угол отражения. вы можете снять два других рейкаста с небольшим изменением угла от вашего источника и получить угол по этим точкам.

так по шагам

1- сделайте рейкаст, получите позицию точки попадания и назовите ее P

2- сделайте еще два рейкаста с отклонением примерно на один градус в обоих направлениях и назовите точки попадания A и B.

3- вычислите угол вектора между A и B (используйте Vector2.angle) и выполните лучевой анализ по этому углу из точки P.

Ответ принят как подходящий

Я не уверен, что понимаю, что вы пытаетесь сделать с помощью «hit2». Насколько я понимаю, вы хотите, чтобы ваш лазер отражался от объекта следующим образом:

По сути, вам нужно получить точку попадания и использовать hit.normal, чтобы получить направление отражения луча. Это делается путем передачи их в Vector2.Reflect().

Чтобы получить очки для рендеринга линий, вы назначаете им hit.point и проходите по нему столько раз, сколько вы хотите, чтобы ваш лазер отражал. Я создал его для вас, но рекомендую вам потратить некоторое время на понимание того, что он делает, прежде чем использовать его. Убедитесь, что Line Renderer является дочерним объектом объекта, содержащего скрипт:

[SerializeField] private LineRenderer lineRenderer;
[SerializeField] private float laserMaxLength = 2f; 
[SerializeField] private int laserMaxHits = 5;

private void Start()
{
    //This is to stop a raycast from inside a collider from hitting said collider 
    //(risk of happening with the "reflected" raycasts):
    Physics2D.queriesStartInColliders = false;
}

void Update()
{
    RaycastHit2D[] hits = new RaycastHit2D[laserMaxHits];
    Vector3[] linePoints = new Vector3[hits.Length + 1];
    float laserLength = laserMaxLength;
    Vector2 laserDirection = transform.right;
    hits[0] = Physics2D.Raycast(transform.position, laserDirection, laserLength);
    linePoints[0] = Vector2.zero;

    for (int i = 0; i < hits.Length; i++)
    {
        if (hits[i])
        {
            if (hits[i].collider.gameObject.tag == "Reflect")
            {
                //Part of the max length of the laser is used:
                laserLength -= hits[i].distance;
                //Get the reflect direction from the hit normal:
                laserDirection = Vector2.Reflect(laserDirection, hits[i].normal);
                //Assign a point on the linerenderer where the ray hit:
                linePoints[i + 1] = transform.InverseTransformPoint(hits[i].point);
                //New raycast for evey bounce, except for the last hit
                //possible (to avoid running out of array):
                if (i != hits.Length-1)
                {
                    hits[i + 1] = Physics2D.Raycast(hits[i].point, laserDirection , laserLength);
                }
                Debug.DrawRay(hits[i].point, laserDirection, Color.blue);
            } else
            {
                //Hit a collider that is non non-reflective
                linePoints[i + 1] = transform.InverseTransformPoint(hits[i].point);
                //Make sure the lineRenderer has enough points to draw the entire laser:
                lineRenderer.positionCount = i + 2;
                break;
            }
        } else
        {
            //End of laser did not hit anything
            linePoints[i + 1] = (Vector2)linePoints[i] + laserDirection * laserLength;
            //Make sure the lineRenderer has enough points to draw the entire laser:
            lineRenderer.positionCount = i + 2;
            break;
        }
    }

    //Assign the found point to the line renderer:
    lineRenderer.SetPositions(linePoints);
}

Удачи, пиу пиу!

Функция Debug.DrawLine работает так, как я хочу, но как мне заставить средство рендеринга линий соответствовать этому?

Martin Anderson 10.06.2024 02:02

@MartinAnderson работать с указаниями - это головная боль. Я изучил это немного больше и обнаружил, что идеальная функция для отражений уже существует, она называется Vector2.Reflect() ! Я отредактировал сообщение выше, приведя пример того, как отображать точки, полученные лучом, и отражать их с помощью средства рендеринга линий.

azelito 10.06.2024 18:31

Мне удалось использовать это в своем сценарии и заставить его работать, установив для параметра lineRenderer.useWorldSpace значение false. Спасибо.

Martin Anderson 10.06.2024 22:52

Другие вопросы по теме