Files
ZHGD_Web/Assets/CameraControllerTest/CameraControllerTest.cs

265 lines
9.4 KiB
C#
Raw Permalink Normal View History

2025-07-13 23:16:20 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
public class CameraControllerTest : MonoBehaviour
{
public float PointVerticalSpeed; // <20><><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6>ٶ<EFBFBD>
public float PointHorizontalSpeed; // <20><><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6>ٶ<EFBFBD>
public float CameraToPointSpeed; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ƶ<EFBFBD><C6B6>ٶ<EFBFBD>
public Scpoe CameraToPointScpoe; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD>
public float PointVerticalRotationSpeed; // <20><><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>ٶ<EFBFBD>
public float PointHorizontalRotationSpeed; // <20><><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>ٶ<EFBFBD>
public Scpoe PointVerticalRotationScpoe; // <20><><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
public Scpoe PointHorizontalRotationScpoe; // <20><><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
public Transform PointScpoePlane; // <20><><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD>
public List<Vector3> PointScpoeData; // <20><><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>Ʒ<EFBFBD>Χ
public bool IsPosition; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>
public bool IsRotation; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת
public bool IsScale; // <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5>ƶ<EFBFBD>
public float CameraToPointInit; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>ֵ
public float PointRotationInit; // <20><>ת<EFBFBD><D7AA>ֵ
private Vector3 Point; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
private Vector3 Point_Temp; // <20><><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>ʱλ<CAB1><CEBB>
private Vector3 CameraToPoint; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ㵥λ<E3B5A5><CEBB><EFBFBD><EFBFBD>
private Vector2 MouseLValue; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private Vector2 MouseRValue; // <20><><EFBFBD><EFBFBD><EFBFBD>Ҽ<EFBFBD><D2BC><EFBFBD><EFBFBD><EFBFBD>
private float MouseCValue; // <20><><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD>
void Start()
{
Init();
}
/// <summary>
/// <20><>ʼ<EFBFBD><CABC>
/// </summary>
void Init()
{
Point = PointScpoePlane.transform.position;
CameraToPoint = transform.position - Point;
}
/// <summary>
/// <20><><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
void PointOperation()
{
Point_Temp = Point - Vector3.ProjectOnPlane(transform.right, Vector3.up
).normalized * PointHorizontalSpeed * MouseLValue.x - Vector3.ProjectOnPlane(transform.forward, Vector3.up
).normalized * PointVerticalSpeed * MouseLValue.y;
Point = IsPointInPolygon(PointOnPlane(Point_Temp, PointScpoePlane.right, PointScpoePlane.forward, PointScpoePlane.position), PointScpoeData) ? Point_Temp : PointNotInScpoe(Point_Temp,PointScpoeData);
CameraToPointInit += MouseCValue * CameraToPointSpeed;
CameraToPointInit = Mathf.Clamp01(CameraToPointInit);
transform.position = Point + CameraToPoint.normalized * Mathf.Lerp(CameraToPointScpoe.Min, CameraToPointScpoe.Max, CameraToPointInit);
}
/// <summary>
/// <20><>ȡָ<C8A1><D6B8><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>ָ<EFBFBD><D6B8>ƽ<EFBFBD><C6BD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <param name="pos">ָ<><D6B8><EFBFBD><EFBFBD>λ</param>
/// <param name="plane">ָ<><D6B8>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD></param>
/// <returns>ָ<><D6B8><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>ָ<EFBFBD><D6B8>ƽ<EFBFBD><C6BD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD></returns>
public static Vector3 PointOnPlane(Vector3 pos, Vector3 right, Vector3 forward, Vector3 plane)
{
Vector3 normal = Vector3.Cross(right, forward).normalized;
Vector3 onPlane = Vector3.ProjectOnPlane(pos - plane, normal);
Vector3 projectX = Vector3.Project(onPlane, right);
float dirX = Vector3.Angle(projectX, right) - 90;
Vector3 projectZ = Vector3.Project(onPlane, forward);
float dirZ = Vector3.Angle(projectZ, forward) - 90;
return new Vector3(projectX.magnitude * -Mathf.Sign(dirX), plane.y, projectZ.magnitude * -Mathf.Sign(dirZ));
}
/// <summary>
/// <20>жϵ<D0B6><CFB5>Ƿ<EFBFBD><C7B7><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>
/// </summary>
/// <param name="point"></param>
/// <param name="polygon"></param>
/// <returns></returns>
public static bool IsPointInPolygon(Vector3 point, List<Vector3> polygon)
{
int polygonLength = polygon.Count, i = 0;
bool inside = false;
float pointX = point.x, pointZ = point.z;
float startX, startZ, endX, endZ;
Vector3 endPoint = polygon[polygonLength - 1];
endX = endPoint.x;
endZ = endPoint.z;
while (i < polygonLength)
{
startX = endX; startZ = endZ;
endPoint = polygon[i++];
endX = endPoint.x; endZ = endPoint.z;
inside ^= (endZ > pointZ ^ startZ > pointZ) && ((pointX - endX) < (pointZ - endZ) * (startX - endX) / (startZ - endZ));
}
return inside;
}
Vector3 PointNotInScpoe(Vector3 outsidePoint, List<Vector3> polygon)
{
// <20><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1>ϵ<EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD>, <20><>ֱ<EFBFBD><D6B1>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B3AC><EFBFBD>߶η<DFB6>Χ, <20><>ʹ<EFBFBD>õ㵽<C3B5><E3B5BD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD>Сֵ<D0A1><D6B5>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5>߾<EFBFBD><DFBE><EFBFBD>, <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>߾<EFBFBD><DFBE><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>, <20><>ʹ<EFBFBD>ø<EFBFBD><C3B8>߶<EFBFBD><DFB6>ϵĵ<CFB5><C4B5><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float[] distances = new float[polygon.Count];
Vector3[] closestPoints = new Vector3[polygon.Count];
for (int i = 0; i < polygon.Count; i++)
{
Vector3 a = polygon[i];
Vector3 b = polygon[(i + 1) % polygon.Count];
Vector3 projectPoint = a + Vector3.Project(outsidePoint - a, b - a);
distances[i] = Vector3.Distance(projectPoint, outsidePoint);
closestPoints[i] = projectPoint;
float angle = Vector3.Angle(projectPoint - a, b - a);
if (angle > 90)
{
distances[i] = Vector3.Distance(outsidePoint, a);
closestPoints[i] = a;
}
angle = Vector3.Angle(projectPoint - b, a - b);
if (angle > 90)
{
distances[i] = Vector3.Distance(outsidePoint, b);
closestPoints[i] = b;
}
}
float minDistance = float.MaxValue;
Vector3 closestPoint = Vector3.zero;
for (int i = 0; i < polygon.Count; i++)
{
if (distances[i] < minDistance)
{
minDistance = distances[i];
closestPoint = closestPoints[i];
}
}
return closestPoint;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
void MouseValueUpdate()
{
if (Input.GetMouseButton(0))
MouseLValue = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")) * Time.deltaTime;
MouseLValue = Vector2.Lerp(MouseLValue, Vector2.zero, Time.deltaTime);
if (Input.GetMouseButton(1))
MouseRValue = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")) * Time.deltaTime;
MouseRValue = Vector2.Lerp(MouseRValue, Vector2.zero, Time.deltaTime);
MouseCValue = -Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime;
MouseCValue = Mathf.Lerp(MouseCValue, 0, Time.deltaTime);
}
/// <summary>
/// <20><>ת
/// </summary>
void RotationController() {
Vector3 X = Vector3.Cross(CameraToPoint, Vector3.up).normalized;
Vector3 Z = Vector3.Cross(Vector3.up, X).normalized;
Vector3 Y = Vector3.Cross(X, Z).normalized;
Debug.DrawLine(Point, Point + X * 10, Color.red);
Debug.DrawLine(Point, Point + Z * 10, Color.blue);
Debug.DrawLine(Point, Point + Y * 10, Color.green);
float Lenght = CameraToPoint.magnitude;
PointRotationInit -= MouseRValue.y;
PointRotationInit = Mathf.Clamp01(PointRotationInit);
Vector3 DirNext = Vector3.Lerp(Vector3.Lerp(Z, Y, PointVerticalRotationScpoe.Min / 90), Vector3.Lerp(Z, Y, PointVerticalRotationScpoe.Max / 90), PointRotationInit).normalized;
transform.position = Point + DirNext * Lenght;
transform.RotateAround(Point, Y, MouseRValue.x * PointHorizontalRotationSpeed);
transform.LookAt(Point);
CameraToPoint = transform.position - Point;
}
private void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
for (int i = 0; i < PointScpoeData.Count; i++) {
Vector3 S = PointScpoeData[i];
S = PointScpoePlane.position + PointScpoePlane.right * S.x + PointScpoePlane.forward * S.z;
Vector3 E = PointScpoeData[(i + 1) % PointScpoeData.Count];
E = PointScpoePlane.position + PointScpoePlane.right * E.x + PointScpoePlane.forward * E.z;
Gizmos.DrawLine(S,E);
}
}
void Update()
{
MouseValueUpdate();
RotationController();
PointOperation();
}
}
[Serializable]
public struct Scpoe
{
public float Min;
public float Max;
}
#if UNITY_EDITOR
[CustomEditor(typeof(CameraControllerTest))]
public class CameraControllerTestEditor : Editor
{
private CameraControllerTest cameraControllerTest;
private void OnEnable()
{
cameraControllerTest = target as CameraControllerTest;
SceneView.duringSceneGui += SceneGUI;
}
private void OnDisable()
{
SceneView.duringSceneGui -= SceneGUI;
}
private void SceneGUI(SceneView sceneView)
{
var plane = serializedObject.FindProperty("PointScpoePlane").objectReferenceValue as Transform;
if (plane == null)
return;
var data = serializedObject.FindProperty("PointScpoeData");
GUIStyle style = new GUIStyle();
style.normal.textColor = Color.yellow;
for (int i = 0; i < data.arraySize; i++)
{
var v3 = data.GetArrayElementAtIndex(i);
Vector3 vector = v3.vector3Value;
Vector3 point = plane.position + plane.right * vector.x + plane.forward * vector.z;
Handles.Label(point, i.ToString(), style);
Vector3 pointGUI = Handles.PositionHandle(point, plane.rotation);
v3.vector3Value = CameraControllerTest.PointOnPlane(pointGUI, plane.right,plane.forward,plane.position);
}
// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ֵ<EFBFBD><D6B5>ʵʱ<CAB5><CAB1><EFBFBD><EFBFBD>Undo, <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD>ų<EFBFBD>
serializedObject.ApplyModifiedPropertiesWithoutUndo();
}
}
#endif