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就不能直接拖动物体,所以额外生成一个空物体生成控制球

3. 实现效果

请添加图片描述

posted @   zytstanly  阅读(156)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示