197 lines
6.3 KiB
C#
197 lines
6.3 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using DG.Tweening;
|
||
using Ichni;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.InputSystem;
|
||
|
||
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
|
||
public class SimpleGridController : MonoBehaviour
|
||
{
|
||
public Camera targetCamera => EditorManager.instance.cameraManager.currentCamera;
|
||
|
||
[Header("Settings")]
|
||
public Material gridMaterial;
|
||
public GameObject textPrefab; // 预制体需要挂载 TextMeshPro
|
||
public Transform textParent;
|
||
|
||
[Header("Grid Logic")]
|
||
public bool showCoordinates = true;
|
||
public float baseGridSize = 1.0f;
|
||
[Range(10f, 1000f)] public float drawDistance = 100f;
|
||
|
||
|
||
// --- 内部状态 ---
|
||
private MeshRenderer _renderer;
|
||
private Material _instancedMat;
|
||
private float _currentSpacing = 1.0f;
|
||
|
||
void Start()
|
||
{
|
||
|
||
InitMesh();
|
||
|
||
_renderer = GetComponent<MeshRenderer>();
|
||
if (gridMaterial)
|
||
{
|
||
_instancedMat = new Material(gridMaterial);
|
||
_renderer.material = _instancedMat;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
public Color MainColor = new Color(0.8f, 0.8f, 0.8f, 0.5f);
|
||
public Color SubColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);
|
||
void Update()
|
||
{
|
||
if (Mouse.current.middleButton.wasPressedThisFrame)
|
||
{
|
||
StartCoroutine(Pressing());
|
||
}
|
||
}
|
||
GameObject coordTextObj = null;
|
||
IEnumerator Pressing()
|
||
{
|
||
if (coordTextObj != null)
|
||
{
|
||
coordTextObj.transform.DOComplete();
|
||
}
|
||
TextMeshPro coordText = null;
|
||
float targetScale = 1f;
|
||
Tweener scaleTween = null;
|
||
while (Mouse.current.middleButton.isPressed)
|
||
{
|
||
Ray ray = targetCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||
Plane plane = new Plane(Vector3.up, Vector3.zero);
|
||
if (plane.Raycast(ray, out float enter))
|
||
{
|
||
Vector3 hitPoint = ray.GetPoint(enter);
|
||
Vector2 xz = new Vector2(hitPoint.x, hitPoint.z);
|
||
// 创建或复用文字对象
|
||
if (coordTextObj == null)
|
||
{
|
||
coordTextObj = Instantiate(textPrefab, textParent);
|
||
coordText = coordTextObj.GetComponent<TextMeshPro>();
|
||
coordTextObj.transform.localScale = Vector3.zero;
|
||
targetScale = Mathf.Clamp(Vector3.Distance(targetCamera.transform.position, hitPoint) * 0.05f, 0.1f, 1000f);
|
||
scaleTween = coordTextObj.transform.DOScale(Vector3.one * targetScale, 0.2f).SetEase(Ease.OutBack);
|
||
}
|
||
else
|
||
{
|
||
// 动态融合:用DOTween的ChangeEndValue实时调整目标scale
|
||
targetScale = Mathf.Clamp(Vector3.Distance(targetCamera.transform.position, hitPoint) * 0.05f, 0.1f, 1000f);
|
||
if (scaleTween != null && scaleTween.IsActive())
|
||
{
|
||
scaleTween.ChangeEndValue(Vector3.one * targetScale, true);
|
||
}
|
||
else
|
||
{
|
||
coordTextObj.transform.localScale = Vector3.one * targetScale;
|
||
}
|
||
}
|
||
coordTextObj.transform.position = hitPoint + Vector3.up * targetScale;
|
||
coordTextObj.transform.rotation = Quaternion.LookRotation(coordTextObj.transform.position - targetCamera.transform.position, Vector3.up);
|
||
if (coordText == null) coordText = coordTextObj.GetComponent<TextMeshPro>();
|
||
coordText.text = $"({xz.x:F2}, {xz.y:F2})\n({Mathf.Round(xz.x):F2}, {Mathf.Round(xz.y):F2})";
|
||
coordText.fontSize = 8;
|
||
coordText.enableWordWrapping = false;
|
||
coordText.color = Color.yellow;
|
||
}
|
||
yield return null;
|
||
}
|
||
// 释放文字对象
|
||
if (coordTextObj != null)
|
||
{
|
||
coordTextObj.transform.DOScale(0, 0.3f).SetEase(Ease.OutExpo).OnComplete(() =>
|
||
{
|
||
Destroy(coordTextObj);
|
||
coordTextObj = null;
|
||
});
|
||
}
|
||
}
|
||
void LateUpdate()
|
||
{
|
||
if (!targetCamera) return;
|
||
|
||
Vector3 camPos = targetCamera.transform.position;
|
||
|
||
// 1. 网格跟随相机 (无限大地板)
|
||
transform.position = new Vector3(camPos.x, 0, camPos.z);
|
||
|
||
// 2. 计算层级 (1m / 10m / 100m)
|
||
float absH = Mathf.Abs(camPos.y);
|
||
float step = baseGridSize;
|
||
Color Mcolor = MainColor;
|
||
Color Scolor = SubColor;
|
||
// 简单的自适应逻辑:根据高度决定网格密度
|
||
if (absH > 150f)//>150
|
||
{
|
||
step *= 10f;
|
||
Scolor = Lerp(SubColor, Color.clear, (absH - 150f) / 150f);
|
||
}
|
||
else if (absH > 15f)//15-150
|
||
{
|
||
step *= 10f;
|
||
Mcolor = Lerp(MainColor, SubColor, (absH - 15f) / (150f - 15f));
|
||
Scolor = Lerp(SubColor, Color.clear, (absH - 15f) / (150f - 15f));
|
||
}
|
||
else//0-15
|
||
{
|
||
Mcolor = Lerp(MainColor, SubColor, absH / 15f);
|
||
Scolor = Lerp(SubColor, Color.clear, absH / 15f);
|
||
}
|
||
|
||
|
||
_currentSpacing = step;
|
||
|
||
// 3. 更新 Shader
|
||
if (_instancedMat)
|
||
{
|
||
_instancedMat.SetColor("_MainColor", Scolor);
|
||
_instancedMat.SetColor("_AxisColor", Mcolor);
|
||
_instancedMat.SetFloat("_GridSpacing", _currentSpacing);
|
||
_instancedMat.SetFloat("_FadeDist", drawDistance);
|
||
}
|
||
|
||
|
||
}
|
||
private Color Lerp(Color a, Color b, float t)
|
||
{
|
||
return new Color(
|
||
Mathf.Lerp(a.r, b.r, t),
|
||
Mathf.Lerp(a.g, b.g, t),
|
||
Mathf.Lerp(a.b, b.b, t),
|
||
Mathf.Lerp(a.a, b.a, t)
|
||
);
|
||
}
|
||
|
||
|
||
private void InitMesh()
|
||
{
|
||
MeshFilter mf = GetComponent<MeshFilter>();
|
||
Mesh mesh = new Mesh();
|
||
// 覆盖视野的大 Quad
|
||
float size = 2000f;
|
||
Vector3[] vertices = new Vector3[4]
|
||
{
|
||
new Vector3(-size, 0, -size), new Vector3(size, 0, -size),
|
||
new Vector3(-size, 0, size), new Vector3(size, 0, size)
|
||
};
|
||
mesh.vertices = vertices;
|
||
mesh.triangles = new int[6] { 0, 2, 1, 2, 3, 1 };
|
||
mesh.uv = new Vector2[4] { Vector2.zero, Vector2.right, Vector2.up, Vector2.one };
|
||
mesh.RecalculateBounds();
|
||
mf.mesh = mesh;
|
||
}
|
||
} |