265 lines
9.4 KiB
C#
265 lines
9.4 KiB
C#
|
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
|