Map
Controller Coordinates Target System Crosshair System Radar System
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user