Hello Unity использует drone + gis для управления точкой обзора камеры.
Дрон нормально движется в основной камере (вид от третьего лица) с точки зрения камеры, но не работает нормальнов дополнительной камере (вид от первого лица).Это требует дополнительной настройки с использованием библиотеки широты и долготы.
Как заставить камеру найти заднюю часть дрона, я не могу помочь, но не стесняюсь помочь.
using Common.Engine.Cameras;
using Common.GIS.Geometry;
using Common.GIS.Util;
using Common.Util;
using B2G.App;
using RuntimeGizmos;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
namespace Common.CCTVs
{
public class CCTVTransform : MonoBehaviour
{
public Camera MainCamera;
//public CameraCtrl2 MainCameraCtrl;
public PlayerManager PlayerManager;
public CCTVManager CCTVManager;
public TransformType type = TransformType.Move;
public TransformSpace space = TransformSpace.Global;
private Axis selectedAxis = Axis.None;
float minSelectedDistanceCheck = .04f;
private bool isTransforming;
private float totalScaleAmount;
private AxisInfo axisInfo;
public Transform target;
private float handleLength = .25f;
private float triangleSize = .03f;
int circleDetail = 40;
float boxSize = .01f;
private float moveSpeedMultiplier = 1f;
private AxisVectors selectedLinesBuffer = new AxisVectors();
private AxisVectors handleLines = new AxisVectors();
private AxisVectors handleTriangles = new AxisVectors();
private AxisVectors handleSquares = new AxisVectors();
private Color xColor = new Color(1, 0, 0, 0.8f);
private Color yColor = new Color(0, 1, 0, 0.8f);
private Color zColor = new Color(0, 0, 1, 0.8f);
private Color allColor = new Color(.7f, .7f, .7f, 0.8f);
private Color selectedColor = new Color(1, 1, 0, 0.8f);
static Material lineMaterial;
RaycastHit hitTemp;
//인풋 필드 입력 받는 오브젝트
public InputField inputLatitude;
public InputField inputLongitude;
//위,경도 표시
public Text TextLatitude;
public Text TextLongitude;
//위,경도 값을 숫자로 받아주기 위한 변수들
private double latitude;
private double longitude;
//이동시킬 물체
//public GameObject drone;
public DroneMove dronemove;
private void Awake()
{
setMaterial();
}
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
//tr = GetComponent<Transform>();
SelectAxis();
getTarget();
}
private void OnPostRender()
{
if (target == null) return;
if (lineMaterial != null)
{
lineMaterial.SetPass(0);
Color xColor = (selectedAxis == Axis.X) ? selectedColor : this.xColor;
Color yColor = (selectedAxis == Axis.Y) ? selectedColor : this.yColor;
Color zColor = (selectedAxis == Axis.Z) ? selectedColor : this.zColor;
Color allColor = (selectedAxis == Axis.Any) ? selectedColor : this.allColor;
DrawLines(handleLines.x, xColor);
DrawLines(handleLines.y, yColor);
DrawLines(handleLines.z, zColor);
DrawTriangles(handleTriangles.x, xColor);
DrawTriangles(handleTriangles.y, yColor);
DrawTriangles(handleTriangles.z, zColor);
DrawSquares(handleSquares.x, xColor);
DrawSquares(handleSquares.y, yColor);
DrawSquares(handleSquares.z, zColor);
DrawSquares(handleSquares.all, allColor);
}
}
void LateUpdate()
{
if (target == null) return;
//We run this in lateupdate since coroutines run after update and we want our gizmos to have the updated target transform position after TransformSelected()
SetAxisInfo();
SetLines();
}
private void TransformSelected()
{
if (selectedAxis != Axis.None && Input.GetMouseButtonDown(0))
{
StartCoroutine(TransformSelected(type));
}
}
private IEnumerator TransformSelected(TransformType type)
{
isTransforming = true;
// MainCameraCtrl.CameraRotate = false;
// PlayerManager.CameraRotatable = false;
totalScaleAmount = 0;
//totalRotationAmount = Quaternion.identity;
Vector3 originalTargetPosition = target.position;
Vector3 planeNormal = (transform.position - target.position).normalized;
Vector3 axis = GetSelectedAxisDirection();
Vector3 projectedAxis = Vector3.ProjectOnPlane(axis, planeNormal).normalized;
Vector3 previousMousePosition = Vector3.zero;
while (!Input.GetMouseButtonUp(0))
{
Ray mouseRay = MainCamera.ScreenPointToRay(Input.mousePosition);
Vector3 mousePosition = Geometry.LinePlaneIntersect(mouseRay.origin, mouseRay.direction, originalTargetPosition, planeNormal);
if (previousMousePosition != Vector3.zero && mousePosition != Vector3.zero)
{
if (type == TransformType.Move)
{
float moveAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projectedAxis) * moveSpeedMultiplier;
target.Translate(axis * moveAmount, Space.World);
// CCTVManager.updateSelectedCCTVPosition();
}
}
previousMousePosition = mousePosition;
yield return null;
}
//totalRotationAmount = Quaternion.identity;
totalScaleAmount = 0;
// MainCameraCtrl.CameraRotate = true;
// PlayerManager.CameraRotatable = true;
isTransforming = false;
}
private Vector3 GetSelectedAxisDirection()
{
if (selectedAxis != Axis.None)
{
if (selectedAxis == Axis.X) return axisInfo.xDirection;
if (selectedAxis == Axis.Y) return axisInfo.yDirection;
if (selectedAxis == Axis.Z) return axisInfo.zDirection;
if (selectedAxis == Axis.Any) return Vector3.one;
}
return Vector3.zero;
}
public void setTarget(GameObject cctv)
{
if (cctv.tag != "CCTV") return;
target = cctv.transform;
//targetObj = cctv;
}
public void clearTarget()
{
target = null;
//targetObj = null;
}
public void getTarget()
{
// 마우스가 지도위에 존재하는지 검사
Vector2 mousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
//var worldPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -Camera.main.transform.position.z));
//Debug.Log("m_InputField = " + m_InputField.text);
if (mousePosition.x < (0 + Refs.OffsetLeft) || mousePosition.x > (Screen.width - Refs.OffsetRight)
|| mousePosition.y < (0 + Refs.OffsetBottom) || mousePosition.y > (Screen.height - Refs.OffsetTop))
{
return;
}
if (selectedAxis == Axis.None && Input.GetMouseButtonDown(0))
{
RaycastHit hitInfo;
if (Physics.Raycast(MainCamera.ScreenPointToRay(Input.mousePosition), out hitInfo))
{
GameObject hitobj = hitInfo.collider.gameObject;
//Debug.Log("hit: " + hitobj.tag);
if (hitobj.tag == "CCTV")
{
//target = hitInfo.transform;
//target = hitobj.transform;
//targetObj = hitobj;
CCTVManager.setSeletedCCTV(hitobj);
}
else if (hitobj.tag == "Bilboard")
{
GameObject obj = hitobj.transform.parent.gameObject;
if (obj.tag == "CCTV")
{
CCTVManager.setSeletedCCTV(obj);
}
}
else if (hitobj.tag == "CCTV_MODEL")
{
GameObject obj = hitobj.transform.parent.gameObject;
if (obj.tag == "CCTV")
{
CCTVManager.setSeletedCCTV(obj);
}
}
else
{
// dronemove.rcvLonLat(hitInfo); //Point(좌표계)값으로 Drone 이동 함수
// float height = Terrain.activeTerrain.SampleHeight(new Vector3((int)transform.position.x,0,(int)transform.position.y));
// Debug.Log("height = " + height);
//Point p = new Point((mousePosition.x * 10) + Refs.OriX, (mousePosition.y * 10) + Refs.OriY);
Point p = new Point((hitInfo.point.x * 10) + Refs.OriX, (hitInfo.point.z * 10) + Refs.OriY);
LonLat ll = CoordRefer.EPSG5186ToLonLat(p);
try
{
TextLatitude.text = "[위도]:" + ll.Lat.ToString();
TextLongitude.text = "[경도]:" + ll.Lon.ToString();
}
catch(NullReferenceException ex)
{
Debug.Log("ScriptTxt was not set in the inspector");
}
Point p1 = CoordRefer.LonLatToEPSG5186(ll);
// Debug.Log("p1.x = "+ p1.X);
// Debug.Log("p1.z = " + p1.Y);
double x = (p1.X - Refs.OriX) / 10;
double z = (p1.Y - Refs.OriY) / 10;
//Debug.Log("before x = " + x);
//Debug.Log("before y = " + y);
//Debug.Log("before z = " + z);
try
{
Debug.Log("before rcvLonLat2");
dronemove.rcvLonLat2(x, z); // 위경도 값으로 Drone 이동
}
catch (NullReferenceException ex)
{
Debug.Log("dronemove.rcvLonLat2(x, z) was not set in the inspector");
}
return;
//target = null;
//CCTVManager.clearSelectedCCTV();
}
}
else
{
//target = null;
CCTVManager.clearSelectedCCTV();
}
}
}
private void SelectAxis()
{
if (!Input.GetMouseButtonDown(0))
{
//MainCameraCtrl.CameraDragging = true;
//MainCameraCtrl.CameraRotate = true;
try
{
PlayerManager.CameraDraggable = true;
}
catch(NullReferenceException ex)
{
Debug.Log("PlayerManager.CameraDraggable was not set in the inspector");
}
try
{
PlayerManager.CameraRotatable = true;
}
catch(NullReferenceException ex)
{
Debug.Log("PlayerManager.CameraRotatable was not set in the inspector");
}
return;
}
//MainCameraCtrl.CameraDragging = false;
//MainCameraCtrl.CameraRotate = false;
//PlayerManager.CameraDraggable = false;
//PlayerManager.CameraRotatable = false;
selectedAxis = Axis.None;
float xClosestDistance = float.MaxValue;
float yClosestDistance = float.MaxValue;
float zClosestDistance = float.MaxValue;
float allClosestDistance = float.MaxValue;
float minSelectedDistanceCheck = this.minSelectedDistanceCheck * GetDistanceMultiplier();
if (type == TransformType.Move || type == TransformType.Scale)
{
selectedLinesBuffer.Clear();
selectedLinesBuffer.Add(handleLines);
if (type == TransformType.Move) selectedLinesBuffer.Add(handleTriangles);
xClosestDistance = ClosestDistanceFromMouseToLines(selectedLinesBuffer.x);
yClosestDistance = ClosestDistanceFromMouseToLines(selectedLinesBuffer.y);
zClosestDistance = ClosestDistanceFromMouseToLines(selectedLinesBuffer.z);
allClosestDistance = ClosestDistanceFromMouseToLines(selectedLinesBuffer.all);
}
if (type == TransformType.Scale && allClosestDistance <= minSelectedDistanceCheck) selectedAxis = Axis.Any;
else if (xClosestDistance <= minSelectedDistanceCheck && xClosestDistance <= yClosestDistance && xClosestDistance <= zClosestDistance) selectedAxis = Axis.X;
else if (yClosestDistance <= minSelectedDistanceCheck && yClosestDistance <= xClosestDistance && yClosestDistance <= zClosestDistance) selectedAxis = Axis.Y;
else if (zClosestDistance <= minSelectedDistanceCheck && zClosestDistance <= xClosestDistance && zClosestDistance <= yClosestDistance) selectedAxis = Axis.Z;
if (selectedAxis != Axis.None)
{
PlayerManager.CameraDraggable = false;
PlayerManager.CameraRotatable = false;
}
else
{
PlayerManager.CameraDraggable = true;
PlayerManager.CameraRotatable = true;
}
}
private float ClosestDistanceFromMouseToLines(List<Vector3> lines)
{
Ray mouseRay = MainCamera.ScreenPointToRay(Input.mousePosition);
float closestDistance = float.MaxValue;
for (int i = 0; i < lines.Count; i += 2)
{
IntersectPoints points = Geometry.ClosestPointsOnSegmentToLine(lines[i], lines[i + 1], mouseRay.origin, mouseRay.direction);
float distance = Vector3.Distance(points.first, points.second);
if (distance < closestDistance)
{
closestDistance = distance;
}
}
return closestDistance;
}
private float GetDistanceMultiplier()
{
if (target == null) return 0f;
return Mathf.Max(.01f, Mathf.Abs(ExtVector3.MagnitudeInDirection(target.position - transform.position, MainCamera.transform.forward)));
}
private void setMaterial()
{
if (lineMaterial == null)
{
lineMaterial = new Material(Shader.Find("Custom/Lines"));
}
}
void DrawLines(List<Vector3> lines, Color color)
{
GL.Begin(GL.LINES);
GL.Color(color);
for (int i = 0; i < lines.Count; i += 2)
{
GL.Vertex(lines[i]);
GL.Vertex(lines[i + 1]);
}
GL.End();
}
void DrawTriangles(List<Vector3> lines, Color color)
{
GL.Begin(GL.TRIANGLES);
GL.Color(color);
for (int i = 0; i < lines.Count; i += 3)
{
GL.Vertex(lines[i]);
GL.Vertex(lines[i + 1]);
GL.Vertex(lines[i + 2]);
}
GL.End();
}
void DrawSquares(List<Vector3> lines, Color color)
{
GL.Begin(GL.QUADS);
GL.Color(color);
for (int i = 0; i < lines.Count; i += 4)
{
GL.Vertex(lines[i]);
GL.Vertex(lines[i + 1]);
GL.Vertex(lines[i + 2]);
GL.Vertex(lines[i + 3]);
}
GL.End();
}
void DrawCircles(List<Vector3> lines, Color color)
{
GL.Begin(GL.LINES);
GL.Color(color);
for (int i = 0; i < lines.Count; i += 2)
{
GL.Vertex(lines[i]);
GL.Vertex(lines[i + 1]);
}
GL.End();
}
void SetAxisInfo()
{
float size = handleLength * GetDistanceMultiplier();
axisInfo.Set(target, size, space);
if (isTransforming && type == TransformType.Scale)
{
if (selectedAxis == Axis.Any) axisInfo.Set(target, size + totalScaleAmount, space);
if (selectedAxis == Axis.X) axisInfo.xAxisEnd += (axisInfo.xDirection * totalScaleAmount);
if (selectedAxis == Axis.Y) axisInfo.yAxisEnd += (axisInfo.yDirection * totalScaleAmount);
if (selectedAxis == Axis.Z) axisInfo.zAxisEnd += (axisInfo.zDirection * totalScaleAmount);
}
}
void SetLines()
{
SetHandleLines();
SetHandleTriangles();
SetHandleSquares();
//SetCircles(axisInfo, circlesLines);
}
void SetHandleLines()
{
handleLines.Clear();
if (type == TransformType.Move || type == TransformType.Scale)
{
handleLines.x.Add(target.position);
handleLines.x.Add(axisInfo.xAxisEnd);
handleLines.y.Add(target.position);
handleLines.y.Add(axisInfo.yAxisEnd);
handleLines.z.Add(target.position);
handleLines.z.Add(axisInfo.zAxisEnd);
}
}
void SetHandleTriangles()
{
handleTriangles.Clear();
if (type == TransformType.Move)
{
float triangleLength = triangleSize * GetDistanceMultiplier();
AddTriangles(axisInfo.xAxisEnd, axisInfo.xDirection, axisInfo.yDirection, axisInfo.zDirection, triangleLength, handleTriangles.x);
AddTriangles(axisInfo.yAxisEnd, axisInfo.yDirection, axisInfo.xDirection, axisInfo.zDirection, triangleLength, handleTriangles.y);
AddTriangles(axisInfo.zAxisEnd, axisInfo.zDirection, axisInfo.yDirection, axisInfo.xDirection, triangleLength, handleTriangles.z);
}
}
void AddTriangles(Vector3 axisEnd, Vector3 axisDirection, Vector3 axisOtherDirection1, Vector3 axisOtherDirection2, float size, List<Vector3> resultsBuffer)
{
Vector3 endPoint = axisEnd + (axisDirection * (size * 2f));
Square baseSquare = GetBaseSquare(axisEnd, axisOtherDirection1, axisOtherDirection2, size / 2f);
resultsBuffer.Add(baseSquare.bottomLeft);
resultsBuffer.Add(baseSquare.topLeft);
resultsBuffer.Add(baseSquare.topRight);
resultsBuffer.Add(baseSquare.topLeft);
resultsBuffer.Add(baseSquare.bottomRight);
resultsBuffer.Add(baseSquare.topRight);
for (int i = 0; i < 4; i++)
{
resultsBuffer.Add(baseSquare[i]);
resultsBuffer.Add(baseSquare[i + 1]);
resultsBuffer.Add(endPoint);
}
}
void SetHandleSquares()
{
handleSquares.Clear();
if (type == TransformType.Scale)
{
float boxLength = boxSize * GetDistanceMultiplier();
AddSquares(axisInfo.xAxisEnd, axisInfo.xDirection, axisInfo.yDirection, axisInfo.zDirection, boxLength, handleSquares.x);
AddSquares(axisInfo.yAxisEnd, axisInfo.yDirection, axisInfo.xDirection, axisInfo.zDirection, boxLength, handleSquares.y);
AddSquares(axisInfo.zAxisEnd, axisInfo.zDirection, axisInfo.xDirection, axisInfo.yDirection, boxLength, handleSquares.z);
AddSquares(target.position - (axisInfo.xDirection * boxLength), axisInfo.xDirection, axisInfo.yDirection, axisInfo.zDirection, boxLength, handleSquares.all);
}
}
void AddSquares(Vector3 axisEnd, Vector3 axisDirection, Vector3 axisOtherDirection1, Vector3 axisOtherDirection2, float size, List<Vector3> resultsBuffer)
{
Square baseSquare = GetBaseSquare(axisEnd, axisOtherDirection1, axisOtherDirection2, size);
Square baseSquareEnd = GetBaseSquare(axisEnd + (axisDirection * (size * 2f)), axisOtherDirection1, axisOtherDirection2, size);
resultsBuffer.Add(baseSquare.bottomLeft);
resultsBuffer.Add(baseSquare.topLeft);
resultsBuffer.Add(baseSquare.bottomRight);
resultsBuffer.Add(baseSquare.topRight);
resultsBuffer.Add(baseSquareEnd.bottomLeft);
resultsBuffer.Add(baseSquareEnd.topLeft);
resultsBuffer.Add(baseSquareEnd.bottomRight);
resultsBuffer.Add(baseSquareEnd.topRight);
for (int i = 0; i < 4; i++)
{
resultsBuffer.Add(baseSquare[i]);
resultsBuffer.Add(baseSquare[i + 1]);
resultsBuffer.Add(baseSquareEnd[i + 1]);
resultsBuffer.Add(baseSquareEnd[i]);
}
}
Square GetBaseSquare(Vector3 axisEnd, Vector3 axisOtherDirection1, Vector3 axisOtherDirection2, float size)
{
Square square;
Vector3 offsetUp = ((axisOtherDirection1 * size) + (axisOtherDirection2 * size));
Vector3 offsetDown = ((axisOtherDirection1 * size) - (axisOtherDirection2 * size));
//These arent really the proper directions, as in the bottomLeft isnt really at the bottom left...
square.bottomLeft = axisEnd + offsetDown;
square.topLeft = axisEnd + offsetUp;
square.bottomRight = axisEnd - offsetDown;
square.topRight = axisEnd - offsetUp;
return square;
}
void SetCircles(AxisInfo axisInfo, AxisVectors axisVectors)
{
axisVectors.Clear();
if (type == TransformType.Rotate)
{
float circleLength = handleLength * GetDistanceMultiplier();
AddCircle(target.position, axisInfo.xDirection, circleLength, axisVectors.x);
AddCircle(target.position, axisInfo.yDirection, circleLength, axisVectors.y);
AddCircle(target.position, axisInfo.zDirection, circleLength, axisVectors.z);
AddCircle(target.position, (target.position - transform.position).normalized, circleLength, axisVectors.all, false);
}
}
void AddCircle(Vector3 origin, Vector3 axisDirection, float size, List<Vector3> resultsBuffer, bool depthTest = true)
{
Vector3 up = axisDirection.normalized * size;
Vector3 forward = Vector3.Slerp(up, -up, .5f);
Vector3 right = Vector3.Cross(up, forward).normalized * size;
Matrix4x4 matrix = new Matrix4x4();
matrix[0] = right.x;
matrix[1] = right.y;
matrix[2] = right.z;
matrix[4] = up.x;
matrix[5] = up.y;
matrix[6] = up.z;
matrix[8] = forward.x;
matrix[9] = forward.y;
matrix[10] = forward.z;
Vector3 lastPoint = origin + matrix.MultiplyPoint3x4(new Vector3(Mathf.Cos(0), 0, Mathf.Sin(0)));
Vector3 nextPoint = Vector3.zero;
float multiplier = 360f / circleDetail;
Plane plane = new Plane((transform.position - target.position).normalized, target.position);
for (var i = 0; i < circleDetail + 1; i++)
{
nextPoint.x = Mathf.Cos((i * multiplier) * Mathf.Deg2Rad);
nextPoint.z = Mathf.Sin((i * multiplier) * Mathf.Deg2Rad);
nextPoint.y = 0;
nextPoint = origin + matrix.MultiplyPoint3x4(nextPoint);
if (!depthTest || plane.GetSide(lastPoint))
{
resultsBuffer.Add(lastPoint);
resultsBuffer.Add(nextPoint);
}
lastPoint = nextPoint;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using B2G.App;
using Common.GIS.Geometry;
using Common.GIS.Util;
using RuntimeGizmos;
public class UISubCamera : MonoBehaviour
{
public Camera subCamera;
private Axis selectedAxis = Axis.None;
public DroneMove dronemove;
public GameObject player;
private Vector3 offset;
float distance;
Vector3 playerPrevPos, playerMoveDir;
// Use this for initialization
void Start()
{
offset = transform.position - player.transform.position;
distance = offset.magnitude;
playerPrevPos = player.transform.position;
}
void LateUpdate()
{
playerMoveDir = player.transform.position - playerPrevPos;
if (playerMoveDir != Vector3.zero)
{
playerMoveDir.Normalize();
transform.position = player.transform.position - playerMoveDir * distance;
//transform.position.y += 5f; // required height
float yy = transform.position.y;
yy += 10f;
//transform.position = new Vector3(transform.position.x, yy, transform.position.z)
//transform.LookAt(player.transform.position);
//playerPrevPos = player.transform.position;
transform.position = new Vector3(transform.position.x + 45f, transform.position.y + 10f, transform.position.z + 80f);
transform.LookAt(player.transform.forward);
playerPrevPos = player.transform.forward;
}
}
public void SubGetTarget()
{
// 마우스가 지도위에 존재하는지 검사
Vector2 mousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
if (mousePosition.x < (0 + Refs.OffsetLeft) || mousePosition.x > (Screen.width - Refs.OffsetRight)
|| mousePosition.y < (0 + Refs.OffsetBottom) || mousePosition.y > (Screen.height - Refs.OffsetTop))
{
return;
}
if (selectedAxis == Axis.None && Input.GetMouseButtonDown(0))
{
RaycastHit hitInfo;
if (Physics.Raycast(subCamera.ScreenPointToRay(Input.mousePosition), out hitInfo))
{
GameObject hitobj = hitInfo.collider.gameObject;
//Debug.Log("hit: " + hitobj.tag);
// dronemove.rcvLonLat(hitInfo); //Point(좌표계)값으로 Drone 이동 함수
// float height = Terrain.activeTerrain.SampleHeight(new Vector3((int)transform.position.x,0,(int)transform.position.y));
// Debug.Log("height = " + height);
//Point p = new Point((mousePosition.x * 10) + Refs.OriX, (mousePosition.y * 10) + Refs.OriY);
Point p = new Point((hitInfo.point.x * 10) + Refs.OriX, (hitInfo.point.z * 10) + Refs.OriY);
LonLat ll = CoordRefer.EPSG5186ToLonLat(p);
Point p1 = CoordRefer.LonLatToEPSG5186(ll);
// Debug.Log("p1.x = "+ p1.X);
// Debug.Log("p1.z = " + p1.Y);
double x = (p1.X - Refs.OriX) / 10;
double z = (p1.Y - Refs.OriY) / 10;
//Debug.Log("before x = " + x);
//Debug.Log("before y = " + y);
//Debug.Log("before z = " + z);
dronemove.rcvLonLat2(x, z); // 위경도 값으로 Drone 이동
}
}