Unity基于屏幕空间的鼠标拖动,拖动物体旋转

代码的核心在于,鼠标的屏幕偏移映射到物体的旋转角度,代码中是使用射线去检测的,检测帧间隔鼠标的位置对应物体上的旋转

未解决的问题:旋转都是相对的,怎么去处理,鼠标拖动物体,物体不动,相机去做围绕物体旋转,由于射线是相机空间发出的,同时相机也在移动和旋转,导致预期的效果不一样,希望有思路的同学可以分享一下

//下面是核心的api调用和计算

//两种情况,第一种是物体基于自身的坐标系旋转,第二种是物体基于相机的坐标系旋转

//关键点就是,需要计算出 旋转四元数,然后把四元数应用到物体的坐标系,相当于旋转物体的坐标系(坐标轴)

//GetRayPoint:像物体发射线,返回物体上的点

//initRayPoint:鼠标按下,发送的射线返回的点

//currentMousePosition:鼠标偏移的过程中发送的射线返回的点(变量名懒得改了)

//基于目标坐标系下,屏幕空间的拖动物体旋转

//if (GetRayPoint(out currentMousePosition))

//{

// Quaternion rot = Quaternion.FromToRotation(initRayPoint,currentMousePosition);

// Debug.DrawLine( Vector3.zero, initRayPoint, Color.yellow, 2.0f);

// Debug.DrawLine(Vector3.zero, currentMousePosition, Color.green, 2.0f);

// _endRotation = rot *currentRotate ;

// sphere.rotation = _endRotation;

//}

//基于相机坐标系下,屏幕空间的拖动物体旋转

//if (GetRayPoint(out currentMousePosition))

//{

// Quaternion yQua = Quaternion.FromToRotation(Vector3.ProjectOnPlane(initRayPoint, transform.right), Vector3.ProjectOnPlane(currentMousePosition, transform.right));

// Quaternion xQua = Quaternion.FromToRotation(Vector3.ProjectOnPlane(initRayPoint, transform.up), Vector3.ProjectOnPlane(currentMousePosition, transform.up));

// Quaternion quat = yQua * xQua;

// _endRotation = quat * currentRotate;

// sphere.rotation = _endRotation;

//}

//基于相机坐标系下,屏幕空间中鼠标拖拽物体,相机绕着物体旋转,主要用在拖动地球,相机绕着地球旋转,slg游戏拖动地图,地图是平面,使用移动相机的方式

cs 复制代码
Vector2 _mouseCurrentPosition = Mouse.current.position.ReadValue();
        Vector2 _mouseDelta = _lookAction.action.ReadValue<Vector2>();
        Debug.Log(_mouseDelta+"::"+(_mouseCurrentPosition-_mouseInitPosition));
        Vector3 currentWorldPosition;
       bool b1=  GetRayPoint(_mouseCurrentPosition, out currentWorldPosition);
        Vector3 previousWorldPosition;
       bool b2 = GetRayPoint(_mouseInitPosition, out previousWorldPosition);

        if (b1 && b2)
        {
            // 计算投影向量(修正参数顺序)
            Vector3 initProjRight = Vector3.ProjectOnPlane(previousWorldPosition, transform.right);
            Vector3 currProjRight = Vector3.ProjectOnPlane(currentWorldPosition, transform.right);
            Vector3 initProjUp = Vector3.ProjectOnPlane(previousWorldPosition, transform.up);
            Vector3 currProjUp = Vector3.ProjectOnPlane(currentWorldPosition, transform.up);

            // 生成绕 X 轴和 Y 轴的独立旋转(修正旋转方向)
            int dirX = _mouseInitPosition.y > _mouseCurrentPosition.y? 1:-1;
            int dirY = _mouseInitPosition.x > _mouseCurrentPosition.x ? -1 : 1;

            float angleX = Vector3.Angle(initProjRight, currProjRight) *dirX;
            float angleY = Vector3.Angle(initProjUp, currProjUp)* dirY;

            Quaternion xQua = Quaternion.AngleAxis(angleX,transform.right);
            Quaternion yQua = Quaternion.AngleAxis(angleY, transform.up);
          
            Quaternion quat = xQua   * yQua   ;

            // 始终基于初始状态计算旋转(避免累积误差)
            _endRotation = quat * _initialRotation;
            cube.rotation = _endRotation;

            // 计算位置偏移(保持相对中心点旋转)
            Vector3 center = Vector3.zero; // 可替换为实际旋转中心
            Vector3 dir = _initialPosition - center;
            Vector3 endMovePosition = center + quat * dir;

            // 更新物体位置
            cube.position = endMovePosition;
            
            _initialRotation = _endRotation;
            _initialPosition = endMovePosition;
            _mouseInitPosition = _mouseCurrentPosition;
        }
      
    }

不好理解的是:向量或者四元数,有的时候不好理解他是代表的点还是方向,最近碰到一个坑点,就是创建旋转四元数的两个api:

例如需要计算向量A,到向量B的旋转向量?

1.第一种使用 Quaternion.FromToRotation

q = Quaternion.FromToRotation(A,B);

2.第二种使用 角度+坐标轴的形式

float angle = Vector.angle(A,B);

q = Quaternion.AngleAxis(angle,axisDir);

上面两种方式有很大的区别,即便是在一个坐标系下,创建的旋转四元数也不一样,个人推荐使用第二种方式,至少可以直观的看见创建是旋转四元数是基于什么轴的

相关推荐
星夜泊客43 分钟前
Unity 游戏开发中的防御性编程与空值处理实践
unity·设计模式·游戏引擎
min9701191 小时前
键盘鼠标做一份CE\FCC证书需要多少钱?
计算机外设
mit6.8246 小时前
[无人机sdk] Open Protocol | 协议包构造&验证
游戏引擎·无人机·cocos2d
tealcwu6 小时前
【Unity踩坑】Unity测试用例命名空间错误解决方案
unity·游戏引擎·测试用例
AA陈超9 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-28 构建属性菜单小部件控制器
c++·游戏·ue5·游戏引擎·虚幻
地狱为王10 小时前
Unity使用PP-MattingV2实现人像分割
unity·游戏引擎
在路上看风景12 小时前
7.1 阴影贴图
unity
lrh302512 小时前
Unity 高效 ListView GridView
unity·高效·复用·uilistview·uigridview
星夜泊客15 小时前
[特殊字符] Unity 对象判空机制混乱原因总结(上篇)
unity·游戏引擎
应用市场1 天前
Godot C++开发指南:正确获取节点的Forward/Up/Right方向向量
c++·游戏引擎·godot