Squashed commit of the following:

commit 173bbb165c
Author: henjkey <henjkey@gmail.com>
Date:   Fri Aug 14 18:51:23 2026 +0500

    Mappp

commit d559ab338a
Author: henjkey <henjkey@gmail.com>
Date:   Thu Aug 13 18:42:41 2026 +0500

    Map

    Controller
    Coordinates
    Target System
    Crosshair System
    Radar System
This commit is contained in:
2026-08-18 16:16:19 +03:00
parent 63d2836dc9
commit c01ff800f6
56 changed files with 4108 additions and 789 deletions
@@ -0,0 +1,147 @@
using UnityEngine;
[DisallowMultipleComponent]
public sealed class MapCoordinateSystem : MonoBehaviour
{
public const float CoordinateMaximum = 10f;
[Header("Coordinate Bounds")]
[SerializeField] private Transform bottomLeft = null;
[SerializeField] private Transform bottomRight = null;
[SerializeField] private Transform topLeft = null;
[SerializeField] private Transform topRight = null;
[Header("Square Bounds")]
[SerializeField, Min(0.001f)] private float squareSize = 5.14925f;
[Header("Scene View Visualization")]
[SerializeField] private bool showSceneVisualization = true;
[SerializeField, Range(1, 20)] private int gridDivisions = 10;
[SerializeField] private bool showCoordinateLabels = true;
[SerializeField] private Color boundaryColor = new(0f, 0.85f, 1f, 1f);
[SerializeField] private Color gridColor = new(0f, 0.85f, 1f, 0.3f);
[SerializeField, Min(0.001f)] private float markerSize = 0.06f;
public Vector2 MaximumCoordinates => new(CoordinateMaximum, CoordinateMaximum);
public float SquareSize => Mathf.Max(0.001f, squareSize);
public bool ShowSceneVisualization => showSceneVisualization;
public int GridDivisions => Mathf.Max(1, gridDivisions);
public bool ShowCoordinateLabels => showCoordinateLabels;
public Color BoundaryColor => boundaryColor;
public Color GridColor => gridColor;
public float MarkerSize => Mathf.Max(0.001f, markerSize);
public Transform BottomLeft => bottomLeft;
public Transform BottomRight => bottomRight;
public Transform TopLeft => topLeft;
public Transform TopRight => topRight;
private void OnValidate()
{
squareSize = Mathf.Max(0.001f, squareSize);
ApplySquareBounds();
}
public void ApplySquareBounds()
{
if (!HasValidCorners())
return;
Vector3 origin = bottomLeft.position;
Vector3 rightDirection = bottomRight.position - origin;
Vector3 upDirection = topLeft.position - origin;
if (rightDirection.sqrMagnitude <= Mathf.Epsilon || upDirection.sqrMagnitude <= Mathf.Epsilon)
return;
rightDirection.Normalize();
upDirection = Vector3.ProjectOnPlane(upDirection, rightDirection);
if (upDirection.sqrMagnitude <= Mathf.Epsilon)
return;
upDirection.Normalize();
float size = SquareSize;
bottomRight.position = origin + rightDirection * size;
topLeft.position = origin + upDirection * size;
topRight.position = origin + (rightDirection + upDirection) * size;
}
public Vector2 ClampCoordinates(Vector2 coordinates)
{
return new Vector2(
Mathf.Clamp(coordinates.x, 0f, CoordinateMaximum),
Mathf.Clamp(coordinates.y, 0f, CoordinateMaximum));
}
public Vector3 CoordinatesToWorldPosition(Vector2 coordinates)
{
if (!HasValidCorners())
return transform.position;
Vector2 clamped = ClampCoordinates(coordinates);
float horizontal = clamped.x / CoordinateMaximum;
float vertical = clamped.y / CoordinateMaximum;
Vector3 bottom = Vector3.Lerp(bottomLeft.position, bottomRight.position, horizontal);
Vector3 top = Vector3.Lerp(topLeft.position, topRight.position, horizontal);
return Vector3.Lerp(bottom, top, vertical);
}
public Vector2 WorldPositionToCoordinates(Vector3 worldPosition)
{
if (!HasValidCorners())
return Vector2.zero;
Vector3 horizontalEdge = bottomRight.position - bottomLeft.position;
Vector3 verticalEdge = topLeft.position - bottomLeft.position;
Vector3 fromBottomLeft = worldPosition - bottomLeft.position;
float horizontal = horizontalEdge.sqrMagnitude > Mathf.Epsilon
? Vector3.Dot(fromBottomLeft, horizontalEdge) / horizontalEdge.sqrMagnitude
: 0f;
float vertical = verticalEdge.sqrMagnitude > Mathf.Epsilon
? Vector3.Dot(fromBottomLeft, verticalEdge) / verticalEdge.sqrMagnitude
: 0f;
for (int iteration = 0; iteration < 6; iteration++)
{
Vector3 current = BilinearPosition(horizontal, vertical);
Vector3 error = worldPosition - current;
Vector3 horizontalDerivative = Vector3.Lerp(
bottomRight.position - bottomLeft.position,
topRight.position - topLeft.position,
vertical);
Vector3 verticalDerivative = Vector3.Lerp(
topLeft.position - bottomLeft.position,
topRight.position - bottomRight.position,
horizontal);
float horizontalLength = Vector3.Dot(horizontalDerivative, horizontalDerivative);
float mixedLength = Vector3.Dot(horizontalDerivative, verticalDerivative);
float verticalLength = Vector3.Dot(verticalDerivative, verticalDerivative);
float determinant = horizontalLength * verticalLength - mixedLength * mixedLength;
if (Mathf.Abs(determinant) <= Mathf.Epsilon)
break;
float horizontalError = Vector3.Dot(horizontalDerivative, error);
float verticalError = Vector3.Dot(verticalDerivative, error);
horizontal += (horizontalError * verticalLength - verticalError * mixedLength) / determinant;
vertical += (verticalError * horizontalLength - horizontalError * mixedLength) / determinant;
}
Vector2 coordinates = new(
horizontal * CoordinateMaximum,
vertical * CoordinateMaximum);
return ClampCoordinates(coordinates);
}
private Vector3 BilinearPosition(float horizontal, float vertical)
{
Vector3 bottom = Vector3.LerpUnclamped(bottomLeft.position, bottomRight.position, horizontal);
Vector3 top = Vector3.LerpUnclamped(topLeft.position, topRight.position, horizontal);
return Vector3.LerpUnclamped(bottom, top, vertical);
}
public bool HasValidCorners()
{
return bottomLeft != null && bottomRight != null && topLeft != null && topRight != null;
}
}