简体   繁体   English

如何在 Unity (ECS) 中旋转量子数并计算方向向量

[英]How to rotate a quanternion and calculate direction vector in Unity (ECS)

I started to work with ECS and I have a Rotation component (quaternion) and a Translation component (float3).我开始使用 ECS 并且我有一个旋转组件(四元数)和一个平移组件(float3)。 I am writing a System that will handle user input and rotate and/or move forward the player.我正在编写一个系统来处理用户输入和旋转和/或向前移动播放器。

The problem is I don't know how to do it.问题是我不知道该怎么做。 The existing API is lacking in my opinion.我认为缺乏现有的 API。

// Before it was easy
if (Input.GetKey(KeyCode.W))
    var newPostion = new Vector3(player.Position.x, player.Position.y, 0.3f)
                    + _playerTransform.up * Time.deltaTime * PlayerSpeed;

if (Input.GetKey(KeyCode.A))
    _playerTransform.Rotate(new Vector3(0, 0, PlayerRotationFactor));

// now it is not - that's part of the system's code
Entities.With(query).ForEach((Entity entity, ref Translation translation, ref Rotation rotation) =>
{
    float3 tmpTranslation = translation.Value;
    quaternion tmpRotation = rotation.Value;

    if (Input.GetKey(KeyCode.W))
        // how to retrieve forward vector from the quaternion
        tmpTranslation.y += Time.deltaTime * PlayerSpeed; 

    if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
        // this always set the same angle
        tmpRotation = quaternion.RotateZ(PlayerRotationFactor); 

    // ECS need this
    var newTranslation = new Translation { Value = tmpTranslation };
    PostUpdateCommands.SetComponent(entity, newTranslation);
    var newRotation = new Rotation { Value = tmpRotation };
    PostUpdateCommands.SetComponent(entity, newRotation);
});

To get the vector from a quaternion you can simply multiply it with a forward vector, example: 要从四元数中获取向量,您可以将其与正向向量相乘,例如:

if (Input.GetKey(KeyCode.W))
{
    Vector forward = tmpRotation * float3(0,0,1);
    tmpTranslation += forward * Time.deltaTime * PlayerSpeed;
}

For the rotation part, as you say // this always set the same angle . 对于旋转部分,正如您所说的// this always set the same angle Looks like you're creating a new angle of static degree. 看起来您正在创建一个新的静态角度。 Try change to multiply with the current angle, as with quaternions you multiply to combine. 尝试更改以当前角度相乘,就像四元数相乘以合并一样。 Example: 例:

if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
    tmpRotation = mul(tmpRotation, quaternion.RotateZ(PlayerRotationFactor));
}

Sidenote: I'm also a bit new to Unity ECS, and I've not tested above codes. 旁注:我还是Unity ECS的新手,我还没有测试以上代码。

// correct forward
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
    float3 forwardVector = math.mul(rotation.Value, new float3(0, 1, 0));
    newTranslation += forwardVector * Time.deltaTime * PlayerSpeed;
}
// correct rotation
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
    quaternion newRotation = math.mul(rotation.Value, quaternion.RotateZ(PlayerRotationFactor * Time.deltaTime));
    // insert new value to the component
    PostUpdateCommands.SetComponent(entity, new Rotation { Value = newRotation });
}
// thx akaJag

NOTICE to other viewers.其他观众须知。

That code does not use the delegate variable references as they should be.该代码没有使用应有的委托变量引用。

Setting the component in PostUpdateCommands (or EntityManager , or any other CommandBufferSystem ) is utterly unnecessary as the translation / rotation is directly present - in the delegate function - to be manipulated by ref.PostUpdateCommands (或EntityManager或任何其他CommandBufferSystem )中设置组件是完全没有必要的,因为平移/旋转是直接存在的 - 在委托函数中 - 由 ref 操作。

AKA:又名:

rotation.Value = newRotation
translation.Value = newTranslation

NOT不是

EntityManager(CommandBuffer).SetComponentData(entity, new Rotation{ Value = newRotation})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM