Gizmos.matrix的用法示例及理解

下面代码演示了Gizmos.matrix的用法,分别在第74行和第188行。通过这两行代码来理解Gizmos.matrix设置的作用就是为其后面的绘制设定基准。(本代码来自HongLiu的DigitalTwin项目中设置全局视角功能)

using UnityEngine;

public class SetGlobalViewCtrl : MonoBehaviour
{
	[SerializeField]
	[Range(0, 360)]
	[Header("水平起点")]
	float rotHStart = 0;

	[SerializeField]
	[Header("水平范围")]
	[Range(0, 360)]
	float rotHRang = 90;

	[SerializeField]
	[Range(0, 1)]
	[Header("水平插值")]
	float processH = 0.5f;

	[SerializeField]
	[Header("垂直起点")]
	[Range(-90, 90)]
	float rotVStart = 0;

	[SerializeField]
	[Range(0, 180)]
	[Header("垂直范围")]
	float rotVRang = 75;

	[SerializeField]
	[Range(0, 1)]
	[Header("垂直插值")]
	float processV = 0.5f;

	[SerializeField]
	[Range(1, 100)]
	[Header("推拉起始")]
	float zoomStart = 15;

	[SerializeField]
	[Range(5, 200)]
	[Header("推拉范围")]
	float zoomRange = 20;

	[SerializeField]
	[Range(0,1)]
	[Header("推拉插值")]
	float zoomProcess = 0.3f;

	[SerializeField]
	[Header("预览")]
	bool preview = true;

	void Start()
	{
		GlobalViewCtrl.instance.Set(transform.position, rotHStart, rotHRang, processH, rotVStart, rotVRang, processV, zoomStart, zoomRange);
	}

	Transform trCam;
	void OnDrawGizmos()
	{
		if (!preview) return;
		//
		rotHStart = Mathf.Clamp(rotHStart, 0, 360);
		rotHRang = Mathf.Clamp(rotHRang, 0, 360);
		processH = Mathf.Clamp01(processH);
		rotVStart = Mathf.Clamp(rotVStart, -90, 90);
		rotVRang = Mathf.Clamp(rotVRang, 0, 180);
		processV = Mathf.Clamp01(processV);
		zoomStart = Mathf.Clamp(zoomStart, 1, 100);
		zoomRange = Mathf.Clamp(zoomRange, 5, 200);
		transform.rotation = Quaternion.identity;
		//
		Gizmos.matrix = transform.localToWorldMatrix;
		Vector3 vHStartVStart = Quaternion.Euler(-rotVStart, -rotHStart, 0) * Vector3.forward;
		Vector3 vHEndVStart = Quaternion.Euler(-rotVStart, -rotHStart - rotHRang, 0) * Vector3.forward;
		Vector3 vHStartVEnd = Quaternion.Euler(-rotVStart - rotVRang, -rotHStart, 0) * Vector3.forward;
		Vector3 vHEndVEnd = Quaternion.Euler(-rotVStart - rotVRang, -rotHStart - rotHRang, 0) * Vector3.forward;
		//
		Gizmos.color = new Color(0, 0, 1, 0.2f);
		Gizmos.DrawLine(Vector3.zero, vHStartVStart * zoomStart);
		Gizmos.DrawLine(Vector3.zero, vHEndVStart * zoomStart);

		Gizmos.DrawLine(Vector3.zero, vHStartVEnd * zoomStart);
		Gizmos.DrawLine(Vector3.zero, vHEndVEnd * zoomStart);

		Gizmos.color = new Color(0, 1, 0, 0.3f);
		float zoomEnd = zoomStart + zoomRange;
		Gizmos.DrawLine(vHStartVStart * zoomStart, vHStartVStart * zoomEnd);
		Gizmos.DrawLine(vHEndVStart * zoomStart, vHEndVStart * zoomEnd);
		Gizmos.DrawLine(vHStartVEnd * zoomStart, vHStartVEnd * zoomEnd);
		Gizmos.DrawLine(vHEndVEnd * zoomStart, vHEndVEnd * zoomEnd);
		//------------------------------------------------------------------------------------------------------------------------
		int countSegment = (int)(rotHRang / 10) + 1;
		Vector3[] rangePoints = new Vector3[countSegment + 1];
		float deltaAngle = rotHRang / countSegment;
		for (int i = 0; i <= countSegment; i++)
		{
			rangePoints[i] = Quaternion.Euler(-rotVStart, -rotHStart - deltaAngle * i, 0) * Vector3.forward;
		}

		for (int i = 0; i < rangePoints.Length - 1; i++)
		{
			Gizmos.DrawLine(rangePoints[i] * zoomStart, rangePoints[i + 1] * zoomStart);
			Gizmos.DrawLine(rangePoints[i] * zoomEnd, rangePoints[i + 1] * zoomEnd);
		}

		for (int i = 0; i <= countSegment; i++)
		{
			rangePoints[i] = Quaternion.Euler(-rotVStart - rotVRang, -rotHStart - deltaAngle * i, 0) * Vector3.forward;
		}

		for (int i = 0; i < rangePoints.Length - 1; i++)
		{
			Gizmos.DrawLine(rangePoints[i] * zoomStart, rangePoints[i + 1] * zoomStart);
			Gizmos.DrawLine(rangePoints[i] * zoomEnd, rangePoints[i + 1] * zoomEnd);
		}
		//------------------------------------------------------------------------------------------------------------------------
		countSegment = (int)(rotVRang / 10) + 1;
		rangePoints = new Vector3[countSegment + 1];
		deltaAngle = rotVRang / countSegment;
		for (int i = 0; i <= countSegment; i++)
		{
			rangePoints[i] = Quaternion.Euler(-rotVStart - deltaAngle * i, -rotHStart, 0) * Vector3.forward;
		}

		for (int i = 0; i < rangePoints.Length - 1; i++)
		{
			Gizmos.DrawLine(rangePoints[i] * zoomStart, rangePoints[i + 1] * zoomStart);
			Gizmos.DrawLine(rangePoints[i] * zoomEnd, rangePoints[i + 1] * zoomEnd);
		}

		for (int i = 0; i <= countSegment; i++)
		{
			rangePoints[i] = Quaternion.Euler(-rotVStart - deltaAngle * i, -rotHStart - rotHRang, 0) * Vector3.forward;
		}

		for (int i = 0; i < rangePoints.Length - 1; i++)
		{
			Gizmos.DrawLine(rangePoints[i] * zoomStart, rangePoints[i + 1] * zoomStart);
			Gizmos.DrawLine(rangePoints[i] * zoomEnd, rangePoints[i + 1] * zoomEnd);
		}
		//------------------------------------------------------------------------------------------------------------------------
		Gizmos.color = Color.cyan;
		Vector3 vHProcess = Quaternion.Euler(-rotVStart - rotVRang * processV, -rotHStart - rotHRang * processH, 0) * Vector3.forward;
		Gizmos.DrawLine(vHProcess * zoomStart, vHProcess * zoomEnd);
		//
		Gizmos.color = new Color(0, 1, 1, 0.2f);
		Vector3 vHL = Quaternion.Euler(-rotVStart - rotVRang * processV, -rotHStart, 0) * Vector3.forward;
		Vector3 vHR = Quaternion.Euler(-rotVStart - rotVRang * processV, -rotHStart - rotHRang, 0) * Vector3.forward;
		Vector3 vVB = Quaternion.Euler(-rotVStart, -rotHStart - rotHRang * processH, 0) * Vector3.forward;
		Vector3 vVT = Quaternion.Euler(-rotVStart - rotVRang, -rotHStart - rotHRang * processH, 0) * Vector3.forward;
		Gizmos.DrawLine(vHL * zoomStart, vHL * zoomEnd);
		Gizmos.DrawLine(vHR * zoomStart, vHR * zoomEnd);
		Gizmos.DrawLine(vVB * zoomStart, vVB * zoomEnd);
		Gizmos.DrawLine(vVT * zoomStart, vVT * zoomEnd);

		countSegment = (int)(rotHRang / 10) + 1;
		rangePoints = new Vector3[countSegment + 1];
		deltaAngle = rotHRang / countSegment;
		for (int i = 0; i <= countSegment; i++)
		{
			rangePoints[i] = Quaternion.Euler(-rotVStart - rotVRang * processV, -rotHStart - deltaAngle * i, 0) * Vector3.forward;
		}

		for (int i = 0; i < rangePoints.Length - 1; i++)
		{
			Gizmos.DrawLine(rangePoints[i] * zoomStart, rangePoints[i + 1] * zoomStart);
			Gizmos.DrawLine(rangePoints[i] * zoomEnd, rangePoints[i + 1] * zoomEnd);
		}

		countSegment = (int)(rotVRang / 10) + 1;
		rangePoints = new Vector3[countSegment + 1];
		deltaAngle = rotVRang / countSegment;
		for (int i = 0; i <= countSegment; i++)
		{
			rangePoints[i] = Quaternion.Euler(-rotVStart - deltaAngle * i, -rotHStart - rotHRang * processH, 0) * Vector3.forward;
		}

		for (int i = 0; i < rangePoints.Length - 1; i++)
		{
			Gizmos.DrawLine(rangePoints[i] * zoomStart, rangePoints[i + 1] * zoomStart);
			Gizmos.DrawLine(rangePoints[i] * zoomEnd, rangePoints[i + 1] * zoomEnd);
		}
		//
		Vector3 position = vHProcess * (zoomStart +zoomRange* zoomProcess);
		Quaternion rotation = Quaternion.LookRotation(-vHProcess);
		Gizmos.matrix = Matrix4x4.TRS(position, rotation, Vector3.one);
		Gizmos.color = Color.blue;
		Gizmos.DrawFrustum(Vector3.zero, 60, 5, 0.1f, 1.77f);
	}
}

Camera.current为当前视图正在渲染的摄像机,对于Scene视图来说,这个摄像机的名字是"SceneCamera",当然这个摄像机是看不到的,不过可以依据这个摄像机的朝向构建Maxtrix来绘制Gizmos,实现始终朝向视图摄像机的图形,参考代码如下:

using UnityEngine;
using UnityEngine.Events;

public class SelectableObject : MonoBehaviour
{
	[SerializeField]
	[Header("编号")]
	int _id = -1;
	public int id { get { return _id; } }

	[SerializeField]
	[Header("显示名称")]
	string _showName;
	public string showName { get { return _showName; } }

	[SerializeField]
	[Header("注视焦点偏移")]
	Vector3 focusOffset;

	[SerializeField]
	[Header("注视初始距离")]
	float focusDist = 1;

	[SerializeField]
	[Header("注视水平角度")]
	float focusRotH = 30;

	[SerializeField]
	[Header("注视垂直角度")]
	float focusRotV = 45;

	void Start()
	{

	}

	bool _selected = false;
	public bool selected { get { return _selected; } }
	UnityAction<bool> onSelected;
	public void AddActSelected(UnityAction<bool> act) { onSelected -= act; onSelected += act; }
	public void RemoveActSelected(UnityAction<bool> act) { onSelected -= act; }
	public void Selected(bool selected)
	{
		_selected = selected;
		onSelected?.Invoke(_selected);
	}

	public void SetID(int id) { _id = id; }
	public void SetShowName(string showName) { _showName = showName; }

	bool _inCamera;
	public bool inCamera { get { return _inCamera; } }
	void OnBecameVisible() { _inCamera = true; }
	void OnBecameInvisible() { _inCamera = false; }

	void OnDrawGizmosSelected()
	{
		//-------------------------------------------------------------------------------------------------------------------
		float size = 1;
		MeshRenderer[] renders = GetComponentsInChildren<MeshRenderer>();
		if (renders == null || renders.Length == 0)
		{
			size = (Camera.current.transform.position - transform.TransformPoint(focusOffset)).magnitude * 0.1f;
			Debug.Log(size);
		}
		else
		{
			float sum = 0;
			foreach (MeshRenderer render in renders)
			{
				sum += render.bounds.size.x;
				sum += render.bounds.size.y;
				sum += render.bounds.size.z;
			}
			size = sum / renders.Length * 0.2f;
		}

		Collider[] cols = GetComponentsInChildren<Collider>();
		if (cols == null || cols.Length == 0)
		{
			Gizmos.matrix = Matrix4x4.TRS(transform.position, Camera.current.transform.rotation, Vector3.one);
			Gizmos.color = Color.red;
			//
			Vector3 p0 = new Vector3(-size, size, 0);
			Vector3 p1 = new Vector3(size, size, 0);
			Vector3 p2 = new Vector3(size, -size, 0);
			Vector3 p3 = new Vector3(-size, -size, 0);
			Gizmos.DrawLine(p0, p1);
			Gizmos.DrawLine(p1, p2);
			Gizmos.DrawLine(p2, p3);
			Gizmos.DrawLine(p3, p0);
			Gizmos.DrawLine(p0, p2);
			Gizmos.DrawLine(p1, p3);
		}
		//-------------------------------------------------------------------------------------------------------------------
		focusDist = Mathf.Clamp(focusDist, 0.1f, 10000);
		focusRotH = Mathf.Clamp(focusRotH, 0, 360);
		focusRotV = Mathf.Clamp(focusRotV, 0, 90);
		//-------------------------------------------------------------------------------------------------------------------
		Gizmos.matrix = transform.localToWorldMatrix;
		Gizmos.color = Color.green;
		Vector3 vector = Quaternion.Euler(-focusRotV, -focusRotH, 0) * Vector3.forward;
		Vector3 posCam = vector * focusDist + focusOffset;
		float radius = focusDist * 0.02f;
		if (radius > size * 0.2f) radius = size * 0.2f;
		Gizmos.DrawWireSphere(focusOffset, radius);
		Gizmos.DrawLine(focusOffset, posCam);
		Vector3 pos = transform.TransformPoint(posCam);
		Quaternion rot = Quaternion.LookRotation(-vector);
		//-------------------------------------------------------------------------------------------------------------------
		Gizmos.matrix = Matrix4x4.TRS(pos, rot, Vector3.one);
		Gizmos.color = Color.white;
		Gizmos.DrawFrustum(Vector3.zero, 60, focusDist * 0.3f, 0.01f, 1.78f);
	}
}

猜你喜欢

转载自blog.csdn.net/ttod/article/details/129906491