Есть line renderer и функция с рекурсивным отражением. Есть пара вопросов:
1)Как можно обновлять, т.е. перерисовывать линию в режиме реального времени с учётом того, что transform может менять position и rotation, и с учётом того, что другие объекты с тегом и коллайдером тоже могут двигаться, т.е. как появляться, так и исчезать с направления исходного и(или) отражённого луча/лучей?
2)Как можно с учётом изменения количества отражений нормально формировать список координат точек попаданий? (добавлять и удалять с учётом того, что кол-во отражений и их места могут изменятся)
Схема кода:
using UnityEngine;
using System.Collections.Generic;
[RequireComponent(typeof(LineRenderer))]
public class Irradiator : MonoBehaviour
{
LineRenderer m_Line;
public List<Vector3> HitPoints = new List<Vector3>();
///<summary>
///Максимальная длина распространения волны (в юнитах).
///</summary>
[Range(0, 255)] public float maxSL = 100;//maxSpreadLength.
///<summary>
///Текущая длина распространения волны (в юнитах). В случае попадания луча в плоскость коллайдера равна модулю расстояния от начала луча до точки попадания луча.
///</summary>
public float curSL = 0;//curSpreadLength.
///<summary>
///Плотность точек на 1 юнит.
///</summary>
[Range(1, 50)] public byte density = 20;
///<summary>
///Амплитуда.
///</summary>
public float ampl = 1;
///<summary>
///Коэффициент затухания волны.
///</summary>
public float dampC = 0.1f;
///<summary>
///Скорость распространения волны.
///</summary>
public float sprdSpeed = 20;
///<summary>
///Частота.
///</summary>
public float freq = 200;
///<summary>
///Шаг (расстояние) между каждой точкой.
///</summary>
public float step;
///<summary>
///Количество точек для максимальной длины распространения волны.
///</summary>
public int maxPointsCount;
///<summary>
///Количество точек для текущей длины распространения волны.
///</summary>
public int curPointsCount = 0;
///<summary>
///Координаты точки начала луча.
///</summary>
public Vector3 origin;
///<summary>
///Направляющий вектор луча.
///</summary>
public Vector3 direction;
///<summary>
///Тег объекта, в точке попадания в коллайдер которого волна рассеивается.
///</summary>
public const string dispersingTag = "Surfaces/Dispersing";
///<summary>
///Тег объекта, от поверхности коллайдера которого волна отражается.
///</summary>
public const string reflectingTag = "Surfaces/Reflecting";
public int rayCount = 0;
public float deltaZ = 0;
void Start()
{
m_Line = GetComponent<LineRenderer>();//Получение доступа к компоненту.
step = 1 / (float)density;//Вычисление расстояния между точками на основе текущей плотности точек.
maxPointsCount = Mathf.CeilToInt(maxSL * density);//Вычисление количества точек на основе плотности и максимальной длины распространения волны.
}
/*Процедура FixedUpdate в отличие от Update не зависит от частоты кадров,
поэтому идеально подходит для физических и математических расчётов.*/
void FixedUpdate()
{
origin = transform.position;
direction = transform.forward;
m_Line.positionCount = maxPointsCount;
RenderWave(origin, direction, ref curPointsCount, ref curSL, ref rayCount);
}
void RenderWave(Vector3 orig, Vector3 dir, ref int _curPointsCount, ref float _curSL, ref int rayCount)
{
if (_curSL >= maxSL)
{
Debug.Log("STOPPED");
//Debug.Break();
return;
}
Ray ray = new Ray(orig, dir);//Луч ray из точки orig в направлении dir.
RaycastHit hit;//Информация о попадании луча.
++rayCount;
Debug.Log("RayCount: " + rayCount);
int curRayPoints = 0;
float curRaySL = 0;
bool h;
Vector3 pos = orig;
Vector3 ortReflected;//Vector3.Cross(transform.right, dir);//перпендикуляр к лучу
Vector3 dirReflected = dir;//направление
if (Physics.Raycast(ray, out hit, maxSL - _curSL) && hit.transform.gameObject.tag == reflectingTag)//Если луч попал в какой-либо коллайдер.
{
h = true;
HitPoints.Add(hit.point);
curRaySL = hit.distance;//Запоминаем дистанцию от точки orig до точки попадания в коллайдер.
curRayPoints = Mathf.CeilToInt(curRaySL * density);
ortReflected = Vector3.Cross(hit.transform.right, dir).normalized;
Debug.DrawRay(orig, ortReflected, Color.blue);
Debug.DrawRay(orig, dirReflected, Color.red);
}
else
{
h = false;
curRaySL = maxSL - _curSL;
curRayPoints = maxPointsCount - _curPointsCount;
ortReflected = Vector3.Cross(transform.right, dir).normalized;
}
Debug.Log("curRaySL: " + curRaySL);
Debug.Log("curRayPoints: " + curRayPoints);
Debug.DrawRay(orig, dir * curRaySL, Color.red);
for (int i = _curPointsCount; i < _curPointsCount + curRayPoints; i++)
{
Vector3 p = pos + ampl * Mathf.Exp(-dampC * deltaZ) * Mathf.Sin(Mathf.PI + freq * deltaZ / sprdSpeed) * ortReflected;
Debug.Log("Point [" + i + "] = " + p);
m_Line.SetPosition(i, p);//Заполнение массива точками.
//Приращиваем положение точки.
pos += dirReflected * step;
deltaZ += step;
}
_curSL += curRaySL;
_curPointsCount += curRayPoints;
if (h == true)
{
dirReflected = Vector3.Reflect(dirReflected, hit.normal);//если попадание произошло, то отражаем направление и перпендикуляр
ortReflected = Vector3.Reflect(ortReflected, hit.normal);
Debug.DrawRay(hit.point, dirReflected, Color.magenta);
Debug.DrawRay(hit.point, ortReflected, Color.cyan);
}
Debug.Log("_curPointsCount: " + _curPointsCount);
Debug.Log("_curSL: " + _curSL);
RenderWave(hit.point, dirReflected, ref _curPointsCount, ref _curSL, ref rayCount);
}
}
Обновление позиций точек line renderer
Теги: unity,unity3d,Line renderer 2019,Line renderer