效果图:
一、场景布局
1.制作坐标轴
设置图层
2.相机设置
效果:设置坐标模型不被其他物体遮挡
新建空节点作为相机父节点,创建一个新相机(注:空节点下有两个相机 一个Main Camera主相机 一个显示坐标模型相机)如图:
给相机父物体GameObjec添加脚本,用于旋转相机 观察操作Cube
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Transform cameraParent;
private const float MOVE_SPEED = 0.1F;
private const float ROTATE_SPEED = 0.1F;
private Vector3 lastPos = Vector3.zero;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(1))
{
lastPos = Input.mousePosition;
}
if (Input.GetMouseButton(1))//鼠标右键按下 旋转摄影机
{
RotateCamera();
}
MoveCamera();
}
private void MoveCamera()
{
float mouse = Input.GetAxis("Mouse ScrollWheel");
Vector3 pos = cameraParent.Find("Camera").position;
if (mouse < 0)
{
pos.z -= MOVE_SPEED;
}
if (mouse > 0)
{
pos.z += MOVE_SPEED;
}
cameraParent.Find("Main Camera").position = pos;
cameraParent.Find("Camera").position = pos;
}
private void RotateCamera()
{
float dx = Input.mousePosition.x - lastPos.x;
float dy = Input.mousePosition.y - lastPos.y;
Vector3 rotation = cameraParent.rotation.eulerAngles;
rotation.x -= dy * ROTATE_SPEED;
rotation.y += dx * ROTATE_SPEED;
cameraParent.rotation = Quaternion.Euler(rotation);
lastPos = Input.mousePosition;
}
}
3.坐标轴脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveTargetItem : MonoBehaviour
{
public Transform axis; //坐标轴模型
public Transform cube; //要移动的物体
public Camera axisCamera; //只渲染坐标轴的摄像机
public float MOVE_SPEED = 0.03F;
private int currentAxis = 0;//当前要移动的轴 用 1 2 3标识 x y z轴 0表示没有选择坐标轴
private bool choosedAxis = false;//判断是否选择了坐标轴
private Vector3 oldPos; //上一帧鼠标位置
void Start()
{
axis.position = cube.position;
}
void Update()
{
//鼠标按下
if (Input.GetMouseButtonDown(0))
{
//检测相机是否碰撞了坐标轴
Ray ray = axisCamera.GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000, 1 << LayerMask.NameToLayer("Axis"))) //只检测Axis这一层
{
choosedAxis = true;
//碰撞成功后 记录鼠标位置
oldPos = Input.mousePosition;
//判断当前选择的坐标轴
switch (hit.collider.name)
{
case "x":
currentAxis = 1;
break;
case "y":
currentAxis = 2;
break;
case "z":
currentAxis = 3;
break;
default:
break;
}
}
}
//鼠标长按并且在按下鼠标时选中坐标轴
if (Input.GetMouseButton(0) && choosedAxis)
{
//移动物体
UpdateCubePosition();
}
//鼠标抬起后初始化数值
if (Input.GetMouseButtonUp(0))
{
choosedAxis = false;
currentAxis = 0;
}
}
//开始移动物体
private void UpdateCubePosition()
{
Vector3 origin = axisCamera.WorldToScreenPoint(axis.position); //坐标轴原点对应屏幕坐标
Vector3 mouseMovePos = Input.mousePosition - oldPos;
//三个坐标轴的终点对应屏幕坐标
Vector3 axisEnd_x = axisCamera.WorldToScreenPoint(axis.Find("x/x").position);
Vector3 axisEnd_y = axisCamera.WorldToScreenPoint(axis.Find("y/y").position);
Vector3 axisEnd_z = axisCamera.WorldToScreenPoint(axis.Find("z/z").position);
//x、y、z轴与原点在屏幕坐标上的差值
Vector3 vector_x = axisEnd_x - origin;
Vector3 vector_y = axisEnd_y - origin;
Vector3 vector_z = axisEnd_z - origin;
//获取移动物体的世界坐标
Vector3 cubePos = cube.position;
float d = Vector3.Distance(Input.mousePosition, oldPos) * MOVE_SPEED; //鼠标拖动距离
float cos;//获取
switch (currentAxis)
{
case 1:
/*鼠标移动轨迹与X轴夹角的余弦值
* Vector3.Angle(V3,V3) 计算两个向量之间的夹角
* 派(3.141592)/180 等于一角度等于多少弧度
* Mathf.Cos(弧度值)返回以弧度表示的角f的余弦值。
*/
cos = Mathf.Cos(Mathf.PI / 180 * Vector3.Angle(mouseMovePos, vector_x));
//根据余弦值的大小 判断移动物体的前进后退
if (cos < 0) { d = -d; }
cubePos.x += d;
break;
case 2:
cos = Mathf.Cos(Mathf.PI / 180 * Vector3.Angle(mouseMovePos, vector_y));
if (cos < 0) { d = -d; }
cubePos.y += d;
break;
case 3:
cos = Mathf.Cos(Mathf.PI / 180 * Vector3.Angle(mouseMovePos, vector_z));
if (cos < 0) { d = -d; }
cubePos.z += d;
break;
default:
break;
}
cube.position = cubePos;
axis.position = cubePos;
oldPos = Input.mousePosition;
}
}