U3D控制物体移动旋转代码逻辑
鼠标控制3D物体移动旋转
PCMoveAndRotate类
1. 移动
1.1 原理:获取本地坐标的x,y,z轴正方向,利用鼠标偏移量在轴上的分向量的模进行移动,向左为正
1.2 代码实现
Transform[] xyz;//三个移动轴
//初始化,利用LineRenderer生成三个轴
void initXYZPart()
{
GameObject temp;
xyz = new Transform[3];
for (int i = 0; i < 3; ++i)
{
temp = GameObject.CreatePrimitive(PrimitiveType.Quad);
temp.name=i.ToString();
temp.transform.SetParent(transform);
temp.transform.localScale = new Vector3(0.29424f, 0.29424f, 0.29424f);//UI大小
temp.AddComponent<LineRenderer>().startWidth = lineSize;
temp.GetComponent<LineRenderer>().endWidth = lineSize;
temp.GetComponent<LineRenderer>().positionCount=2;
xyz[i] = temp.transform;
}
xyz[0].localPosition = Vector3.right;
xyz[1].localPosition = Vector3.up;
xyz[2].localPosition = Vector3.forward;
xyz[0].GetComponent<MeshRenderer>().material = (Material)Resources.Load("x");
xyz[1].GetComponent<MeshRenderer>().material = (Material)Resources.Load("y");
xyz[2].GetComponent<MeshRenderer>().material = (Material)Resources.Load("z");
xyz[0].GetComponent<LineRenderer>().material = (Material)Resources.Load("x");
xyz[1].GetComponent<LineRenderer>().material = (Material)Resources.Load("y");
xyz[2].GetComponent<LineRenderer>().material = (Material)Resources.Load("z");
}
//沿轴移动
public void MoveWithMouseAlignAxis(Vector2 MouseOffset/*鼠标偏移量*/,short index/*轴的编号*/)
{
Vector2 axis = GetNormalVectorInScreen(transform.position, xyz[index].position);//轴光栅化投影在屏幕上的向量
float offset = GetMouseOffsetCastOnAxis(MouseOffset, axis);//获取鼠标偏移量投影在轴上的值
transform.position += (xyz[index].position-transform.position).normalized * offset*0.001f ;//沿轴改变物体的位置
}
//LineRenderer的更新
void UpdateXYZ()
{
//Matrix4x4 re = Matrix4x4.Rotate(transform.rotation);
for(int i = 0; i < 3; ++i)
{
xyz[i].GetComponent<LineRenderer>().SetPosition(0, transform.position);
xyz[i].GetComponent<LineRenderer>().SetPosition(1, xyz[i].position);
}
}
2. 旋转
2.1 原理:获取根据世界坐标轴x,y,z轴旋转的圆面,利用鼠标偏移量在旋转圆上切向量的分向量的模进行旋转
2.2 代码实现
Transform[] RotateXZXYYZ;//三个旋转面
Vector3[][] positions;//碰撞体位置
short count = 30;//每个旋转圆面的碰撞体个数
//初始化,利用LineRenderer生成三个面和计算碰撞体位置
void initRotatePart()
{
positions = new Vector3[3][];
for (int j =0;j<3; ++j)
{
positions[j] = new Vector3[count + 1];
}
RotateXZXYYZ = new Transform[3];
GameObject temp;
LineRenderer templinerender;
for(int i = 3; i < 6; ++i)
{
temp = new GameObject(i.ToString());
temp.transform.SetParent(transform);
temp.transform.localPosition = Vector3.zero;
temp.transform.localScale = Vector3.one;
temp.AddComponent<LineRenderer>().SetWidth(lineSize,lineSize);
templinerender = temp.GetComponent<LineRenderer>();
templinerender.SetVertexCount(count+1);
for(int j = 0; j < count+1; ++j)
{
if(i==3)
positions[0][j] = new Vector3(Mathf.Cos(j * Mathf.PI / (count * 0.5f)), 0, -Mathf.Sin(j * Mathf.PI / (count * 0.5f))) * transform.localScale.x ;
else if(i==4)
positions[1][j] = new Vector3(Mathf.Cos(j * Mathf.PI / (count * 0.5f)), Mathf.Sin(j * Mathf.PI / (count * 0.5f)), 0) * transform.localScale.x ;
else
positions[2][j] = new Vector3(0, Mathf.Cos(j * Mathf.PI / (count * 0.5f)), Mathf.Sin(j * Mathf.PI / (count * 0.5f))) * transform.localScale.x ;
temp.AddComponent<SphereCollider>().radius=0.1f;
}
RotateXZXYYZ[i - 3] = temp.transform;
}
RotateXZXYYZ[0].GetComponent<LineRenderer>().material = (Material)Resources.Load("z");
RotateXZXYYZ[1].GetComponent<LineRenderer>().material = (Material)Resources.Load("x");
RotateXZXYYZ[2].GetComponent<LineRenderer>().material = (Material)Resources.Load("y");
}
//更新LineRenderer和碰撞体的位置
void UpadteRotatePart()
{
Matrix4x4 re= Matrix4x4.Rotate(transform.rotation);
for (int i=0;i<3;++i)
for (int j = 0; j < count + 1; ++j)
{
RotateXZXYYZ[i].GetComponent<LineRenderer>().SetPosition(j, positions[i][j] + transform.position);
/*碰撞体反本地旋转*/
RotateXZXYYZ[i].GetComponents<SphereCollider>()[j].center =re.inverse.MultiplyPoint(positions[i][j] / transform.localScale.x); ;
}
}
//绕某一轴旋转
public void RotateByAxis(Vector2 MouseOffset/*鼠标偏移量*/,Vector3 point/*旋转点*/, short index/*旋转轴的编号*/)
{
float x0 = transform.position.x, y0 = transform.position.y, z0 = transform.position.z;
float x1 = point.x, y1 = point.y, z1 = point.z;
Vector3 vector;/*切向量*/
switch (index)/*获取在旋转点的切向量*/
{
case 3:
vector = new Vector3(-(z1 - z0), 0, x1 - x0);
break;
case 4:
vector = new Vector3(-(y1 - y0), x1 - x0, 0);
break;
case 5:
vector = new Vector3(0, -(z1 - z0), y1 - y0);
break;
default:
vector=Vector3.zero;
break;
}
Vector2 axis = GetNormalVectorInScreen(point, point+vector);//转换为屏幕坐标向量
float offset = GetMouseOffsetCastOnAxis(MouseOffset, axis);
switch (index)
{
case 3:
transform.Rotate(Vector3.up, -offset,Space.World);
break;
case 4:
transform.Rotate(Vector3.forward, offset, Space.World);
break;
case 5:
transform.Rotate(Vector3.right, offset, Space.World);
break;
}
}
PS:加了rigidbody就不能直接拖动物体,所以额外生成一个空物体生成控制球
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具