157 lines
4.8 KiB
C#
Executable File
157 lines
4.8 KiB
C#
Executable File
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
// Draws a minimap of the generated road as a 2D overlay in the top-left corner,
|
|
// positioned just below the NN steering/throttle text. Shows white path lines
|
|
// and a red dot for the current car position. Auto-refreshes when the road changes.
|
|
public class MapOverlay : MonoBehaviour
|
|
{
|
|
public PathManager pathManager;
|
|
public Transform carTransform;
|
|
|
|
const int MAP_X = 5;
|
|
const int MAP_Y = 42; // below the one-line NN text (~25px tall + padding)
|
|
const int MAP_SIZE = 160;
|
|
|
|
static Texture2D _whiteTex;
|
|
static Texture2D _bgTex;
|
|
static Texture2D _dotTex;
|
|
|
|
static Texture2D WhiteTex
|
|
{
|
|
get
|
|
{
|
|
if (_whiteTex == null)
|
|
{
|
|
_whiteTex = new Texture2D(1, 1);
|
|
_whiteTex.SetPixel(0, 0, Color.white);
|
|
_whiteTex.Apply();
|
|
}
|
|
return _whiteTex;
|
|
}
|
|
}
|
|
|
|
List<Vector3> _nodes = new List<Vector3>();
|
|
float _minX, _maxX, _minZ, _maxZ;
|
|
int _lastNodeCount = -1;
|
|
float _lastFirstNodeX = float.MaxValue; // catches regen with same node count
|
|
float _lastFirstNodeZ = float.MaxValue;
|
|
bool _hasPath = false;
|
|
|
|
void Awake()
|
|
{
|
|
if (pathManager == null)
|
|
pathManager = FindObjectOfType<PathManager>();
|
|
|
|
_bgTex = new Texture2D(1, 1);
|
|
_bgTex.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.55f));
|
|
_bgTex.Apply();
|
|
|
|
_dotTex = new Texture2D(4, 4);
|
|
for (int y = 0; y < 4; y++)
|
|
for (int x = 0; x < 4; x++)
|
|
_dotTex.SetPixel(x, y, Color.red);
|
|
_dotTex.Apply();
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
// Find car transform once it exists
|
|
if (carTransform == null)
|
|
{
|
|
Car c = FindObjectOfType<Car>();
|
|
if (c != null) carTransform = c.transform;
|
|
}
|
|
|
|
// Re-cache path whenever it changes (road regen).
|
|
// Check both count and the 10th node position — regen always produces the same
|
|
// count (numSpans=100) but different positions for different seeds.
|
|
if (pathManager != null && pathManager.carPath != null)
|
|
{
|
|
var nodes = pathManager.carPath.centerNodes;
|
|
int n = nodes.Count;
|
|
float fx = n > 10 ? nodes[10].pos.x : float.MaxValue;
|
|
float fz = n > 10 ? nodes[10].pos.z : float.MaxValue;
|
|
if (n != _lastNodeCount || fx != _lastFirstNodeX || fz != _lastFirstNodeZ)
|
|
{
|
|
_lastFirstNodeX = fx;
|
|
_lastFirstNodeZ = fz;
|
|
RefreshPath();
|
|
}
|
|
}
|
|
}
|
|
|
|
void RefreshPath()
|
|
{
|
|
_nodes.Clear();
|
|
_minX = float.MaxValue; _maxX = float.MinValue;
|
|
_minZ = float.MaxValue; _maxZ = float.MinValue;
|
|
|
|
foreach (PathNode node in pathManager.carPath.centerNodes)
|
|
{
|
|
_nodes.Add(node.pos);
|
|
if (node.pos.x < _minX) _minX = node.pos.x;
|
|
if (node.pos.x > _maxX) _maxX = node.pos.x;
|
|
if (node.pos.z < _minZ) _minZ = node.pos.z;
|
|
if (node.pos.z > _maxZ) _maxZ = node.pos.z;
|
|
}
|
|
|
|
_lastNodeCount = _nodes.Count;
|
|
_hasPath = _nodes.Count > 1;
|
|
}
|
|
|
|
Vector2 WorldToMap(Vector3 world)
|
|
{
|
|
float rangeX = _maxX - _minX;
|
|
float rangeZ = _maxZ - _minZ;
|
|
float range = Mathf.Max(rangeX, rangeZ, 1f);
|
|
|
|
float pad = 6f;
|
|
float inner = MAP_SIZE - pad * 2f;
|
|
|
|
float px = MAP_X + pad + (world.x - _minX) / range * inner;
|
|
float pz = MAP_Y + pad + (1f - (world.z - _minZ) / range) * inner; // flip Z → screen Y
|
|
return new Vector2(px, pz);
|
|
}
|
|
|
|
static void DrawLine(Vector2 a, Vector2 b, Color color, float thickness = 1.5f)
|
|
{
|
|
Vector2 delta = b - a;
|
|
if (delta.sqrMagnitude < 0.01f) return;
|
|
|
|
float angle = Mathf.Atan2(delta.y, delta.x) * Mathf.Rad2Deg;
|
|
float length = delta.magnitude;
|
|
|
|
Color prev = GUI.color;
|
|
GUI.color = color;
|
|
Matrix4x4 saved = GUI.matrix;
|
|
GUIUtility.RotateAroundPivot(angle, a);
|
|
GUI.DrawTexture(new Rect(a.x, a.y - thickness * 0.5f, length, thickness), WhiteTex);
|
|
GUI.matrix = saved;
|
|
GUI.color = prev;
|
|
}
|
|
|
|
void OnGUI()
|
|
{
|
|
if (!_hasPath) return;
|
|
|
|
// Dark background
|
|
GUI.DrawTexture(new Rect(MAP_X - 1, MAP_Y - 1, MAP_SIZE + 2, MAP_SIZE + 2), _bgTex);
|
|
|
|
// Path lines
|
|
for (int i = 0; i < _nodes.Count - 1; i++)
|
|
{
|
|
Vector2 a = WorldToMap(_nodes[i]);
|
|
Vector2 b = WorldToMap(_nodes[i + 1]);
|
|
DrawLine(a, b, Color.white, 1.5f);
|
|
}
|
|
|
|
// Car dot
|
|
if (carTransform != null)
|
|
{
|
|
Vector2 cp = WorldToMap(carTransform.position);
|
|
GUI.DrawTexture(new Rect(cp.x - 3f, cp.y - 3f, 6f, 6f), _dotTex);
|
|
}
|
|
}
|
|
}
|