2d 中的 Bevy 旋转

Bevy rotation in 2d

我正在尝试使用 Bevy 0.3,并且我能够通过 Camera2dComponents::default() 轻松使用内置转换。 这是自上而下的 2d.

问题是试图将玩家的旋转与鼠标同步:

for event in evreader.iter(&cursor_moved_events) {
    println!("{:?}", transform);
    transform.look_at(Vec3::new(event.position.x(), event.position.y(), 0.0), Vec3::new(0.0, 0.0, 1.0));
    println!("{:?}", transform);
}

在这个变换中当然是我的玩家的变换。 输出结果如下:

Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.0, 0.0, 0.0, 1.0), scale: Vec3(1.0, 1.0, 1.0) }
Transform { translation: Vec3(0.0, 0.0, 0.0), rotation: Quat(0.5012898, -0.49870682, -0.49870682, 0.5012898), scale: Vec3(1.0, 1.0, 1.0) }

我对 2d 中 look_at 中的 up 感到有点困惑,但我尝试了几个不同的值,结果总是一样的:一旦 look_at 运行,播放器从视图中消失。 为什么在那之后相机再也看不到玩家了,我做错了什么look_at?

谢谢

当您使用时 Camera2dComponents which is intended for 2D, Transform 不是。 Transform 一般 ,并且还包括 3D 所需的内容。

在你的例子中,它听起来像 look_at() might not do what you think it does. It creates a 3D look at matrix which computes a view matrix which is "at" a position (self.translation) 并且看向 target(第一个参数)。 up 是“world up”的 3D 矢量。以便它可以计算旋转校正。


更新的解决方案:

如果您想旋转自上而下的 2D 播放器,即让播放器的一侧朝向光标。然后你需要计算你的球员的位置和目标之间的角度。您可以使用 Vec2::angle_between().

轻松做到这一点
let pos: Vec2 = ...;
let target: Vec2 = ...;

let angle = (target - pos).angle_between(pos);
transform.rotation = Quat::from_rotation_z(angle);

取决于玩家本身的方向,即如果您使用的是精灵,则默认方向可能是向左或向上“看”。那么您可能需要偏移 angle。你可以通过例如添加 + FRAC_PI_2(或者需要多少。)

假设 transform.translation 是玩家的中心位置,那么它将看起来像这样:

use bevy::math::{Quat, Vec2};

let pos = transform.translation.truncate();
let target = event.position;

let angle = (target - pos).angle_between(pos);
transform.rotation = Quat::from_rotation_z(angle);

旧答案:

因为您想在自上而下的 2D 视图中将相机放置在光标上方。然后你必须使用 from_translation() or simply shift self.translation,这是你的相机的位置。

transform.translation = Vec3::new(event.position.x(), event.position.y(), 0.0);

如果你想让光标位置在屏幕的中心,那么你可能需要减去一半的屏幕尺寸。

对于未来的用户,我在 Bevy v0.5 中遇到了类似的问题(让 2d sprite 面对鼠标点击位置)并且出于某种原因我无法获得可接受的答案。

我通过 Unity 线程中的这个实现解决了它:https://answers.unity.com/questions/650460/rotating-a-2d-sprite-to-face-a-target-on-a-single.html

代码示例:

let diff = targ.translation - pos.translation;
let angle = diff.y.atan2(diff.x); // Add/sub FRAC_PI here optionally
pos.rotation = Quat::from_axis_angle(Vec3::new(0., 0., 1.), angle);