Move and Rotate separately?

I’m experimenting with rotation and movement combinations and wonder if it is possible to have a smooth movement separately from a simultaneous rotation?
My current understanding is that we only have MoveTo and TeleportTo, both of which require both parameters to be specified simultaneously.
For a test, I wanted to make a floating droid that looks in the same direction as the player does. The movement needs to be smooth so I would use MoveTo with a 0.5 second period and a blocking sync to join multiple moves together.
The turning should be immediate or very fast, so on the other side of the sync I want to use something like TeleportTo but for rotation only (if I just use TeleportTo it will interrupt the MoveTo).
This attempt (use TeleportTo with the current Translation while MoveTo updates on a separate thread) doesn’t work:

    OnBegin<override>()<suspends>:void=
        Print("Start rotation_test")
        spawn{ TurnToFace() }
        spawn{ MoveTowards() }


    TurnToFace()<suspends>:void=
        Print("TurnToFace started")
        loop:
            if (Player := PlayerManager.GetCharacter[0]):

                PropTransform := Prop.GetTransform()
                PropPosition := PropTransform.Translation

                PlayTransform := Player.GetTransform()
                PlayRotation := PlayTransform.Rotation

                # turn immediately, don't alter Translation
                if (Prop.TeleportTo[PropPosition, PlayRotation]) {}
            Sleep(0.0)


    MoveTowards()<suspends>:void=
        Print("MoveTowards started")
        loop:
            if (Player := PlayerManager.GetCharacter[0]):

                PropTransform := Prop.GetTransform()
                PropPosition := PropTransform.Translation

                PlayTransform := Player.GetTransform()
                PlayPosition := PlayTransform.Translation
                PlayRotation := PlayTransform.Rotation

                OffsetPosition := PlayPosition + PlayRotation.RotateVector(vector3{ X:=100.0, Y:=0.0, Z:=100.0 })

                # move smoothly
                SpawnTask := spawn{ Prop.MoveTo(OffsetPosition, PlayRotation, 0.5) }
                # block until move is complete
                SpawnTask.Await()
            Sleep(0.0)

I expected it to fail to turn (MoveTo is presumably overwriting the Rotation every frame while it moves smoothly) but instead it fails to move except very rarely and extremely slowly. I’m guessing the TeleportTo is cancelling the MoveTo in progress.

An alternative approach would be to use only MoveTo to perform a combined Rotation and Movement over time, but in order for the rotation to be very responsive I’d need to decrease the MoveTo duration… which would make the movement jerky.

1 Like

I discovered this last week. It looks like if there is a moveto in operation, a second moveto get’s cancelled most of the time. I expect they just didn’t want to have two threads fighting over a prop, for the reasons you mentioned.

1 Like

If you want to separate location and rotation updates you will habe to operate on two props. Just tripple nest them.

Root Prop ← Rotation Prop ← Visual Prop

Then you can start use different operations on both. However keep in mind that in verse script the updated transform is not relative to the parent prop. You’d need to overcome this problem differently. The root prop could be animated while rotation prop teleported.

Alternative you could opt into using additive transform update using a cinematic sequence device if you have fixed rotation angles.

2 Likes

Nice Solution!