157 lines
6.0 KiB
C#
157 lines
6.0 KiB
C#
using UnityEngine;
|
||
|
||
public class RadarOrigin : MonoBehaviour
|
||
{
|
||
public float Radius = 500f;
|
||
|
||
[Header("Gizmos Settings")]
|
||
[SerializeField] private bool showCenterPoint = true;
|
||
[SerializeField] private bool showCircle = true;
|
||
[SerializeField] private bool showRadialLines = true;
|
||
[SerializeField] private bool showRadiusLabel = true;
|
||
|
||
[SerializeField] private Color centerColor = Color.red;
|
||
[SerializeField] private Color circleColor = Color.green;
|
||
[SerializeField] private Color radialLinesColor = new Color(0, 1, 0, 0.3f);
|
||
[SerializeField] private Color labelColor = Color.white;
|
||
|
||
[SerializeField] private float centerPointSize = 5f;
|
||
[SerializeField][Range(8, 128)] private int circleSegments = 64;
|
||
[SerializeField][Range(1, 8)] private int radialLinesCount = 4;
|
||
|
||
public bool TransformInFOV(Transform target, float searchAngleOffset, float leftAngleZoneDeg = 5, float rightAngleZoneDeg = 0)
|
||
{
|
||
if (target == null) return false;
|
||
|
||
Vector3 directionToTarget = target.position - transform.position;
|
||
|
||
float angleToTarget = Vector3.SignedAngle(transform.forward, directionToTarget, Vector3.up);
|
||
|
||
float minAngle = searchAngleOffset - leftAngleZoneDeg;
|
||
float maxAngle = searchAngleOffset + rightAngleZoneDeg;
|
||
|
||
// Отсекаем по углу
|
||
if (angleToTarget < minAngle || angleToTarget > maxAngle)
|
||
return false;
|
||
|
||
//Отсекаем по дистанции
|
||
float sqrDistance = (target.position - transform.position).sqrMagnitude;
|
||
if (sqrDistance > Radius * Radius)
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
public Vector3 TransformOnRadar(Transform target)
|
||
{
|
||
if (target == null) return Vector3.zero;
|
||
|
||
// Получаем направление до цели
|
||
Vector3 directionToTarget = target.position - transform.position;
|
||
|
||
// Вычисляем расстояние и нормализуем его в диапазон [0, 1]
|
||
float distance = directionToTarget.magnitude;
|
||
float normalizedDistance = Mathf.Clamp01(distance / Radius);
|
||
|
||
// Вычисляем угол относительно forward (в градусах)
|
||
float angle = Vector3.SignedAngle(transform.forward, directionToTarget, Vector3.up);
|
||
|
||
// Преобразуем угол в радианы для тригонометрических функций
|
||
float angleRad = angle * Mathf.Deg2Rad;
|
||
|
||
// Вычисляем координаты на радаре (XZ плоскость -> XY плоскость радара)
|
||
float x = Mathf.Sin(angleRad) * normalizedDistance;
|
||
float y = Mathf.Cos(angleRad) * normalizedDistance;
|
||
|
||
// МАППИНГ: Yaw объекта (поворот по Y) -> поворот иконки по Z
|
||
// Получаем угол поворота цели в горизонтальной плоскости
|
||
float targetYaw = target.eulerAngles.y;
|
||
float originYaw = transform.eulerAngles.y;
|
||
|
||
// Вычисляем относительный поворот
|
||
float relativeYaw = targetYaw - originYaw;
|
||
|
||
// Нормализуем угол в диапазон [-180, 180]
|
||
relativeYaw = NormalizeAngle(relativeYaw);
|
||
|
||
// Возвращаем: x, y - позиция на радаре, z - поворот иконки (маппинг Yaw -> Z)
|
||
return new Vector3(x, y, relativeYaw);
|
||
}
|
||
|
||
private float NormalizeAngle(float angle)
|
||
{
|
||
angle = angle % 360;
|
||
if (angle > 180) angle -= 360;
|
||
if (angle < -180) angle += 360;
|
||
return angle;
|
||
}
|
||
|
||
private void OnDrawGizmosSelected()
|
||
{
|
||
if (!enabled) return;
|
||
|
||
Vector3 center = transform.position;
|
||
Vector3 circleCenter = new Vector3(center.x, center.y, center.z);
|
||
|
||
// Рисуем центральную точку
|
||
if (showCenterPoint)
|
||
{
|
||
Gizmos.color = centerColor;
|
||
Gizmos.DrawSphere(center, centerPointSize);
|
||
}
|
||
|
||
// Рисуем окружность
|
||
if (showCircle)
|
||
{
|
||
Gizmos.color = circleColor;
|
||
DrawCircleXZ(circleCenter, Radius, circleSegments);
|
||
}
|
||
|
||
// Рисуем радиальные линии
|
||
if (showRadialLines)
|
||
{
|
||
Gizmos.color = radialLinesColor;
|
||
for (int i = 0; i < radialLinesCount; i++)
|
||
{
|
||
float angle = i * Mathf.PI * 2f / radialLinesCount + Mathf.PI / 2;
|
||
float x = Mathf.Cos(angle) * Radius;
|
||
float z = Mathf.Sin(angle) * Radius;
|
||
Vector3 point = circleCenter + new Vector3(x, 0, z);
|
||
Gizmos.DrawLine(center, point);
|
||
}
|
||
}
|
||
|
||
// Рисуем текст с радиусом
|
||
if (showRadiusLabel)
|
||
{
|
||
#if UNITY_EDITOR
|
||
UnityEditor.Handles.BeginGUI();
|
||
Vector3 labelPosition = circleCenter + new Vector3(0, 2, Radius + 10);
|
||
Vector3 screenPos = UnityEditor.HandleUtility.WorldToGUIPoint(labelPosition);
|
||
|
||
GUIStyle style = new GUIStyle();
|
||
style.normal.textColor = labelColor;
|
||
style.fontSize = 12;
|
||
style.fontStyle = FontStyle.Bold;
|
||
|
||
GUI.Label(new Rect(screenPos.x, screenPos.y, 100, 20), $"Radius: {Radius:F1}", style);
|
||
UnityEditor.Handles.EndGUI();
|
||
#endif
|
||
}
|
||
void DrawCircleXZ(Vector3 center, float radius, int segments)
|
||
{
|
||
Vector3 previousPoint = center + new Vector3(radius, 0, 0);
|
||
|
||
for (int i = 1; i <= segments; i++)
|
||
{
|
||
float angle = i * Mathf.PI * 2f / segments;
|
||
float x = Mathf.Cos(angle) * radius;
|
||
float z = Mathf.Sin(angle) * radius;
|
||
|
||
Vector3 currentPoint = center + new Vector3(x, 0, z);
|
||
Gizmos.DrawLine(previousPoint, currentPoint);
|
||
previousPoint = currentPoint;
|
||
}
|
||
}
|
||
}
|
||
} |