182 lines
5.5 KiB
C#
182 lines
5.5 KiB
C#
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
|
|
[DisallowMultipleComponent]
|
|
public sealed class MapCrosshairController : MonoBehaviour
|
|
{
|
|
[Header("Nearest Target (Runtime)")]
|
|
[SerializeField] private MapTarget nearestTarget = null;
|
|
[SerializeField] private float distanceToNearestTarget = -1f;
|
|
|
|
private MapCoordinateSystem coordinateSystem;
|
|
private MapTargetController targetController;
|
|
private Transform relayX;
|
|
private Transform relayY;
|
|
private Transform crosshairVisual;
|
|
private float movementSpeed;
|
|
private bool useKeyboardInput;
|
|
private float horizontalAxis;
|
|
private float verticalAxis;
|
|
private Vector2 crosshairCoordinates;
|
|
private Vector3 relayXOffset;
|
|
private Vector3 relayYOffset;
|
|
private bool isConfigured;
|
|
|
|
public MapCoordinateSystem CoordinateSystem => coordinateSystem;
|
|
|
|
public void Configure(
|
|
MapCoordinateSystem newCoordinateSystem,
|
|
Transform newRelayX,
|
|
Transform newRelayY,
|
|
Transform newCrosshairVisual,
|
|
float newMovementSpeed,
|
|
bool enableKeyboardInput,
|
|
MapTargetController newTargetController)
|
|
{
|
|
coordinateSystem = newCoordinateSystem;
|
|
relayX = newRelayX;
|
|
relayY = newRelayY;
|
|
crosshairVisual = newCrosshairVisual;
|
|
movementSpeed = Mathf.Max(0f, newMovementSpeed);
|
|
useKeyboardInput = enableKeyboardInput;
|
|
targetController = newTargetController;
|
|
crosshairCoordinates = Vector2.zero;
|
|
isConfigured = CalibrateObjects();
|
|
|
|
if (isConfigured)
|
|
ApplyCoordinates();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!isConfigured)
|
|
return;
|
|
|
|
if (useKeyboardInput)
|
|
ReadKeyboardInput();
|
|
|
|
Vector2 movement = new(horizontalAxis, verticalAxis);
|
|
crosshairCoordinates += movement * (movementSpeed * Time.deltaTime);
|
|
crosshairCoordinates = coordinateSystem.ClampCoordinates(crosshairCoordinates);
|
|
ApplyCoordinates();
|
|
UpdateNearestTarget();
|
|
}
|
|
|
|
public void SetHorizontalAxis(float value)
|
|
{
|
|
horizontalAxis = Mathf.Clamp(value, -1f, 1f);
|
|
}
|
|
|
|
public void SetVerticalAxis(float value)
|
|
{
|
|
verticalAxis = Mathf.Clamp(value, -1f, 1f);
|
|
}
|
|
|
|
public Vector2 GetCrosshairCoordinates()
|
|
{
|
|
return crosshairCoordinates;
|
|
}
|
|
|
|
public MapTarget GetNearestTarget()
|
|
{
|
|
return nearestTarget;
|
|
}
|
|
|
|
public float GetDistanceToNearestTarget()
|
|
{
|
|
return distanceToNearestTarget;
|
|
}
|
|
|
|
public bool TryGetNearestTarget(out MapTarget target, out float distance)
|
|
{
|
|
target = nearestTarget;
|
|
distance = distanceToNearestTarget;
|
|
return target != null;
|
|
}
|
|
|
|
private void ReadKeyboardInput()
|
|
{
|
|
Keyboard keyboard = Keyboard.current;
|
|
if (keyboard == null)
|
|
{
|
|
SetHorizontalAxis(0f);
|
|
SetVerticalAxis(0f);
|
|
return;
|
|
}
|
|
|
|
SetHorizontalAxis(
|
|
(keyboard.lKey.isPressed ? 1f : 0f) - (keyboard.jKey.isPressed ? 1f : 0f));
|
|
SetVerticalAxis(
|
|
(keyboard.iKey.isPressed ? 1f : 0f) - (keyboard.kKey.isPressed ? 1f : 0f));
|
|
}
|
|
|
|
private void ApplyCoordinates()
|
|
{
|
|
Vector3 targetWorldPosition = coordinateSystem.CoordinatesToWorldPosition(crosshairCoordinates);
|
|
crosshairVisual.position = targetWorldPosition;
|
|
|
|
if (relayX != null)
|
|
relayX.position = coordinateSystem.CoordinatesToWorldPosition(
|
|
new Vector2(crosshairCoordinates.x, 0f)) + relayXOffset;
|
|
|
|
if (relayY != null)
|
|
relayY.position = coordinateSystem.CoordinatesToWorldPosition(
|
|
new Vector2(0f, crosshairCoordinates.y)) + relayYOffset;
|
|
}
|
|
|
|
private bool CalibrateObjects()
|
|
{
|
|
if (coordinateSystem == null || crosshairVisual == null || !coordinateSystem.HasValidCorners())
|
|
return false;
|
|
|
|
Vector3 origin = coordinateSystem.CoordinatesToWorldPosition(Vector2.zero);
|
|
Vector3 horizontalDirection =
|
|
coordinateSystem.CoordinatesToWorldPosition(new Vector2(MapCoordinateSystem.CoordinateMaximum, 0f)) -
|
|
origin;
|
|
Vector3 verticalDirection =
|
|
coordinateSystem.CoordinatesToWorldPosition(new Vector2(0f, MapCoordinateSystem.CoordinateMaximum)) -
|
|
origin;
|
|
|
|
if (horizontalDirection.sqrMagnitude <= Mathf.Epsilon ||
|
|
verticalDirection.sqrMagnitude <= Mathf.Epsilon)
|
|
return false;
|
|
|
|
horizontalDirection.Normalize();
|
|
verticalDirection.Normalize();
|
|
|
|
if (relayX != null)
|
|
relayXOffset = Vector3.ProjectOnPlane(relayX.position - origin, horizontalDirection);
|
|
|
|
if (relayY != null)
|
|
relayYOffset = Vector3.ProjectOnPlane(relayY.position - origin, verticalDirection);
|
|
|
|
return true;
|
|
}
|
|
|
|
private void UpdateNearestTarget()
|
|
{
|
|
nearestTarget = null;
|
|
distanceToNearestTarget = -1f;
|
|
|
|
if (targetController == null)
|
|
return;
|
|
|
|
float nearestSqrDistance = float.PositiveInfinity;
|
|
foreach (MapTarget target in targetController.Targets)
|
|
{
|
|
if (target == null)
|
|
continue;
|
|
|
|
float sqrDistance = (target.MapCoordinates - crosshairCoordinates).sqrMagnitude;
|
|
if (sqrDistance >= nearestSqrDistance)
|
|
continue;
|
|
|
|
nearestSqrDistance = sqrDistance;
|
|
nearestTarget = target;
|
|
}
|
|
|
|
if (nearestTarget != null)
|
|
distanceToNearestTarget = Mathf.Sqrt(nearestSqrDistance);
|
|
}
|
|
}
|