【问题标题】:How to rotate an object along all 3 axes with finger swipe?如何通过手指滑动沿所有 3 个轴旋转对象?
【发布时间】:2018-10-27 23:08:58
【问题描述】:

我正在开发一个简单的 AR Vuforia 应用程序。如何通过一根手指滑动实现对象沿所有三个轴的旋转?

我当前使用的代码有一个错误:对象的旋转取决于其局部轴。例如,如果我从正面看对象,一切正常,但如果我从背面看对象,手指向上滑动会使其向下旋转,反之亦然。

这是这个脚本:

public float rotSpeed = 30f;

void OnMouseDrag()
{
float rotX = Input.GetAxis("Mouse X")*rotSpeed*Mathf.Deg2Rad;
float rotY = Input.GetAxis("Mouse Y")*rotSpeed*Mathf.Deg2Rad;

transform.Rotate(Vector3.up, -rotX);
transform.Rotate(Vector3.right, -rotY);
} 

这不是我需要的,我怎样才能根据手指滑动方向旋转对象,而不管我从哪个角度看它?

更新

一个简单的非AR示例,可以帮助您理解我需要的是iOS游戏“Space Frontier 2”。火箭成功发射后,它降落在星球上,您可以用手指滑动来旋转星球。

这里是视频演示:https://youtu.be/OiNPP1WNIAI

【问题讨论】:

  • 所以这就是我想到的——你想如何通过作用在物体上的单一力来实现力?要在多个轴上完成运动 - 我们需要多个力,例如,1 个模拟力(可能使用设备的旋转/倾斜/方向/罗盘方向?)和单指滑动。想想物理对象——如果我抓住我现在放在桌子上的手机,并沿着 X 轴移动它(例如,平行于我的桌子,甚至对角线)——在我开始扭动我的手机之前,它永远不会使用第三轴手腕;为它添加额外的动作。
  • @KasemO 感谢您提出一个有趣的想法,尽管我还不能说完全理解它。我不需要移动手机来旋转屏幕上的对象,因为这是一个 AR 应用程序,用户将在标记上方查看 3D 模型。我在视频演示中添加了一个小的 UPD,它可能会帮助您理解我的意思。再次感谢你们!
  • 你试过我的答案了吗?它结构紧凑,适用于所有情况。
  • @ThomasHilbert 非常感谢,它运行良好!

标签: c# unity3d augmented-reality vuforia


【解决方案1】:

无论您的对象旋转如何,也无论您的相机相对于对象的位置如何,这都能很好地工作:

public float rotSpeed = 30f;

void OnMouseDrag()
{
    float rotX = Input.GetAxis("Mouse X") * rotSpeed;
    float rotY = Input.GetAxis("Mouse Y") * rotSpeed;

    Camera camera = Camera.main;

    Vector3 right = Vector3.Cross(camera.transform.up, transform.position - camera.transform.position);
    Vector3 up = Vector3.Cross(transform.position - camera.transform.position, right);

    transform.rotation = Quaternion.AngleAxis(-rotX, up) * transform.rotation;
    transform.rotation = Quaternion.AngleAxis(rotY, right) * transform.rotation;
}

确保您的相机具有“MainCamera”标签,或在必要时将相机分配到外部。

【讨论】:

  • 非常感谢,这段代码真的很棒!我将能够在 21 小时内颁发赏金。
【解决方案2】:

我现在没有确切的代码。

但是如果你没有更新你的视点坐标,这应该是预期的结果。

考虑一个真实的球,它有两种颜色,蓝色和红色,垂直分开。 当你在它面前时,只看到蓝色的一面,向上抚摸它会使蓝色的一面向上,红色的一面从底部出现。 现在移到它后面,只看到红色的一面,然后再次向上抚摸它。 蓝色的脸会往下走,从底部出现。 Unity 将物理应用于虚拟对象,就像我们与真实对象交互一样。

因此,当您向其应用移动时,您需要考虑您的相机位置和对象方向。 您需要根据与对象原点方向相关的相机位置,将变换矩阵应用于您的运动。

我希望这足够清楚,可以让您找到解决问题的方法。

【讨论】:

  • 这听起来像是我需要的,谢谢!如果您可以将代码添加到您的答案中以便我进行测试,我将不胜感激。另外,我在问题描述中添加了一个小的 UPD,作为示例也可能会有所帮助。
  • 我还添加了一个视频演示作为插图。
  • 在此链接中查看 DMGregory 的非常好的答案/解释gamedev.stackexchange.com/questions/136174/…
【解决方案3】:

我认为您必须以某种方式限制旋转以获得所需的行为。我最近写了一个脚本来做到这一点。不过我做了一点修改。

public float rotSpeed = 30f;

float ClampAngle(float _angle, float _min, float _max)
{
    if (_angle < 0f) _angle = 360 + _angle;
    if (_angle > 180f) Mathf.Max(_angle, 360 + _min);
    return Mathf.Min(_angle, _max);
}

用法:

void RotateGameObject()
{
    float h = Input.GetTouch(0).deltaPosition.x * Time.deltaTime * rotSpeed*Mathf.Deg2Rad;
    float v = Input.GetTouch(0).deltaPosition.y * Time.deltaTime * rotSpeed*Mathf.Deg2Rad;

    Vector3 rot = transform.rotation.eulerAngles + new Vector3(-v, h, 0f);
    //Change the y & z values to match your expected behaviour.
    rot.x = ClampAngle(rot.x, -5f, 20f);
    //Clamp rotation on the y-axis
    rot.y = ClampAngle(rot.y, -20f, 20f);
    transform.eulerAngles = rot;
}

看看这是否有效,当然,尝试使用这些值。

【讨论】:

  • 感谢一个有趣的例子,我尝试调用 RotateGameObject() 函数 OnMouseDrag(),它的工作方式有点奇怪 - 对象的旋转在过程中多次“跳转”到默认状态手指轻扫。如果我用错了,请告诉我。还是很有趣的代码,我可以从中学到很多,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多