Search code examples
godotgdscriptluau

how i can make walking vector3 lerping with rotation?


I'm trying to translate this code from luau in Roblox to GDScript in Godot.

This WalkingOffset is multiplied by weapon CFrame in luau:

local abs=math.abs
local sin=math.sin
local clamp=math.clamp

local tick=100000

--render every frame
tick+=deltaTime
if running then 
  local totalspeed=16


  WalkingOffset=WalkingOffset:Lerp(
    CFrame.Angles(
            .045*abs(sin(tick*totalspeed*.6)),
        -.02*sin(tick*totalspeed*.6),
            clamp(r(pos.X*15),-.08,.08)
    )
       *CFrame.new(
           035*abs(sin(tick*totalspeed*.55)),
           .01*sin(tick*totalspeed*.6),
           0)
       ,.3)
else
   WalkingOffset=WalkingOffset:Lerp(CFrame.new(),.1)
end

in roblox this looks like this https://i.sstatic.net/U9Fa5.jpg

I tried this code in Godot:

WalkingOffset=WalkingOffset.lerp(
    Basis(Vector3(
        .045*abs(sin(tick*my_speed*.6)),
        -.02*sin(tick*my_speed*.6),
        clamp(pos.x*15,-.08,.08)),
    10)
        *Vector3(
            .035*abs(sin(tick*my_speed*.55)),
            .01*sin(tick*my_speed*.6)-abs(pos.x/1.75),
            0
        )
    ,.3)

This WalkingOffset is multiplied by weapon global_position. But it looks bad and almost nothing moves.


Solution

  • So, screw math, screw luau. Let's do this the Godot way. Please notice that this is not what you asked.

    You are going to add an AnimationPlayer. I'll assume you add it as a child of the node where you are writing the script. And we want to add a couple animations. We will get to calling them from code, but first I need to walk you through making the animations.


    You add the animations on the Animation panel at the bottom of Godot editor. With the AnimationPlayer you click the "Animation" button and then select "new" and write a name for the animation.

    The animations we are going to add are these:

    • One animation is for the weapon swinging. I'll call it "swing".
    • And one is for the weapon not swinging. I'll call it "stay".

    We want them to be of the same length. To change the duration of an animation you type it on the top right of the animation player. I'll work with one second (which is the default, so you don't need to change it).

    Also set the animations to loop. On the right of the where you type the duration there is an icon with two arrows making a loop. Click it to make the animation a looping one.


    To add key frames to the animation, with the Animation panel open, select the time you want to add the keyframe. Then select the object you want to animate and move it to where you want (or change whatever properties you want to animate), and click the key icon that appears in the inspector next to the property.

    The first time you click the icon for a given property of an object Godot will ask you if you want to create a track for it. Each property of each object you animate will have a track in the animation.

    For positions Godot will also ask if you want to use a bezier curves track. This will create separate tracks for x, y, z. The bezier curves will allow us to make the motion smoother, but it is somewhat more complicated, so I suggest you try without it first. If you are not using bezier curves you can select the kind of interpolation on the right of the track, you want "continuous" and "cubic".

    Now, for the "swing" animation you are going to set some key frames, something like this:

    • Top left position at 0.0 seconds.
    • Bottom middle position at 0.25 seconds.
    • Top right position at 0.5 seconds.
    • Bottom middle position at 0.75 seconds.
    • Top left position at 1.0 seconds.

    And for the "stay" animation we just want the weapon centered. So only two key frames, one at the start and one at the end.

    You can set the time snap at the bottom of the Animation panel to 0.25 to make this easier (the default is 0.1, so it won't land on 0.25 and 0.75).

    Notice that the starts and ends on the same one so it loops. It also possible to select a key frame, then select a time, and on the context menu of the track select "Duplicate Key(s)".


    Now, we want Godot to interpolate between these animations. To do that we click on the Animation button again. This time select "Edit transition". Godot will open the "Cross-Blend Animation Times" window, where we can specify the blend times between animations. You can se it to something like half a second. You might want to come back to this and tweak it.

    One more thing, set the "stay" animation to auto start. It is the icon that looks like an A inside of a thick arrow (something like |A>) on the top of the Animation panel.


    And finally, when the player character is not moving you play the "stay" animation like this:

    $AnimationPlayer.play("stay")
    

    Otherwise you want to play the "swing" animation:

    $AnimationPlayer.play("swing")
    

    If you tell the AnimationPlayer to play the same animation it is already playing, it changes nothing. So do not worry about checking which animation it was player, plus you can get away by telling it to play it every frame.

    Godot will handle the transition between the animations according to the time you set in the "Cross-Blend Animation Times" window, so it should not start and stop swinging suddenly.


    Note: I suppose you want to use other animations for other things, for example for shooting the weapon. You might have that entirely separated for example by animating an intermediary pivot node. That is, making your scene tree something like this:

    PlayerCharacter
    └ Pivot
      └ Weapon
    

    And animating the Pivot. You might also have different AnimationPlayers for different parts if you need the animations to play at the same time (each AnimationPlayer only plays one animation). But be aware that they will not work together to move the same property.

    For more complex scenarios you would look into AnimationTree which is capable of playing multiple animations - of the same AnimationPlayer over the same objects at the same time and have them blend together. But since that is not explicitly necessary for what you are doing here, I'll leave it out of this answer.