Hi all, I have what I thought would be easy to find but is proving to be difficult to find the answer to. I have my player that is being moved from place to place using a tween. Works just fine! But now I need to rotate the player to face the direction they are being moved to, and this is proving a little more difficult. Looking for some help!

var tween = get_tree().create_tween().bind_node(self).set_trans(Tween.TRANS_LINEAR)
tween.tween_property(self, "position", pos, ENUMS.walk_speed)
var target_rotation
tween.tween_property(self, "rotation:y", target_rotation, 0.5)

I need to figure out how to determine the "target_rotation" variable. I have tried a few different methods, but nothing seems to work properly. Anyone know how I figure out this one?

Edit:
My current build has this for its code:
var dir = (target - self.global_position).normalized()
var ang = atan2(dir.x, dir.z) + PI
tween.tween_property(self, "rotation:y", ang, 1.0)
Which works fairly well, except the rotation is always the same direction rather than taking the rotation that is shortest. That'll be the next problem to solve if anyone has any tips!

  • xyz replied to this.

    CorvaNocta Is player rotating on other axes as well (for whatever reason) or are they only moving on a ground plane and rotating around y axis?

      xyz only rotating on the one axis. They will never rotate on X or z.

      • xyz replied to this.

        target_rotation=Vector3(0,degree,0)
        rotation:y-->rotation

          kkkkkkabc How does one get that angle? I'm seeing a few questions on the topic when I search for it, but I am not finding one that works (or is exactly what I need)

          xyz So something more like:

          tween.tween_property(self, "rotation.basis.y", target_rotation, 1)

          • xyz replied to this.

            CorvaNocta So something more like:

            tween.tween_property(self, "rotation.basis.y", target_rotation, 1)

            No, the whole basis. You just need to calculate the target basis, which in your case is pretty simply. The z vector is the velocity direction (assuming it's always horizontal), the y vector is the world y vector i.e. Vector3.UP, and the x vector is the normalized cross product of those two.

            You can't really do this using a single rotation value, without a lot of headache. I mean, maybe you could, using a relative tween and a signed angle between current z basis and the velocity but I'd still go with tweening the whole basis as that way is elegant and bulletproof, and it's how the cool kids do it.

              xyz So I did find this code which seems to work much better for what I am trying to do:

              var dir = (target - self.global_position).normalized()
              var ang = atan2(dir.x, dir.z) + PI
              tween.tween_property(self, "rotation:y", ang, 1.0)

              This seems to work pretty well in all instances except one: The rotation direction is always the same and doesn't pick which of the two directions would be faster/shorter. The code is much easier to understand, but its probably not the "best" way to do it.

              • xyz replied to this.

                xyz Ah dang. Well if I must go with basis, I guess I must go with Basis.

                Can you give an example of what the code might look like for that? Or a helpful link? I've not worked with basis before, so I am unsure of how I would use it to rotate the player.

                • xyz replied to this.

                  CorvaNocta You know those three red, green and blue arrows that you can see all over the engine and also in every other 3d program? Well, those three arrows are the basis. Each basis consists of those three vectors and they define how an object is oriented in 3d space.

                  So if you want to orient the object in a certain way, you just need to calculate those 3 vectors. For instantaneous re-orientation, just assign the newly calculated basis to node's global_basis property. For gradual transition, tween node's global_basis property from its current value to newly calculated basis value.

                    xyz Oh! That makes sense. so in a way, you are just updating the basis of the model as though you were grabbing those arrows. That actually makes a lot more sense than what I have read other places!

                    xyz Ok I got a basic test version to work, but I just need the last little bit of sauce to make it perfect!

                    var target_basis = self.global_transform.basis.rotated(Vector3(0, 1, 0), deg_to_rad(45))
                    tween.tween_property(self, "global_transform:basis", target_basis, 1.0)

                    This works, I get the rotation to a 45 degree angle. which is great! Now I just need to figure out how to get the angle to a target, which I am not sure I am doing properly. How would I go about getting that angle?

                    my test character also scales down and then back up? Is that normal with this?

                    • xyz replied to this.

                      CorvaNocta
                      Put the tween aside for the time being and first make the version that just assigns the correct basis, resulting in immediate alignment. Once you get this to work properly, adding a tween is trivial.

                      When working with 3d orientation you need to make a mental leap and work with direction (basis) vectors instead of angles. In fact it's best to forget angles even exist. It's hard I know, but once you get used to thinking in basis vectors, you'll see how angles are actually inadequate and too clunky to represent orientation in 3d space.

                      I already mentioned how to construct the three basis vectors for your wanted orientation, a couple of posts ago:

                      The z vector is the velocity direction (assuming it's always horizontal), the y vector is the world y vector i.e. Vector3.UP, and the x vector is the normalized cross product of those two.