Advertisement
Guest User

Procedural walk animation footplanting

a guest
Feb 13th, 2020
2,163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.68 KB | None | 0 0
  1. local player = game:GetService("Players").LocalPlayer
  2. local character = player.Character
  3. local rootPart = character.HumanoidRootPart
  4. local head = character.Head --lower torso when actual character
  5. local camera = workspace.CurrentCamera
  6.  
  7. local beam1, beam2 = workspace.beam1, workspace.beam2
  8. local pos1, pos2 = workspace.pos1, workspace.pos2
  9.  
  10. local cf = CFrame.new
  11. local ang = CFrame.Angles
  12. local v3 = Vector3.new
  13. local ray = Ray.new
  14. local sin = math.sin
  15. local pi = math.pi
  16. local rad = math.rad
  17. local deg = math.deg
  18.  
  19. local lastUpdate = 0
  20. local targLeft, targRight = v3(), v3()
  21. local oldLeft, oldRight = v3(), v3()
  22. local updateLeft = true
  23. local leftOff, rightOff = cf(-0.5, -0.5, 0), cf( 0.5, -0.5, 0)
  24. local lastspeed = 0
  25.  
  26. local function getVel()
  27.     local vel = rootPart.CFrame:vectorToObjectSpace(rootPart.Velocity)
  28.     local speed = v3(vel.X, 0, vel.Z).magnitude
  29.     return vel, speed
  30. end
  31.  
  32. local function getDirection()
  33.     local direction = camera.CFrame.lookVector
  34.     local heading = math.atan2(-direction.X, -direction.Z)
  35.     return heading
  36. end
  37.  
  38. local function predictPosition(current, velocity, timeAhead)
  39.     return current * cf(velocity * timeAhead)
  40. end
  41.  
  42. local function getNextPosition(origin, zAngle, xAngle, length)
  43.     local start = origin * ang(zAngle, 0, 0) * ang(0, 0, xAngle)
  44.     local ray = ray(start.p, -start.UpVector * length)
  45.     local hit, pos, nor = workspace:FindPartOnRayWithIgnoreList(ray, {character, beam1, beam2, pos1, pos2, workspace.Ignore})
  46.     return pos
  47. end
  48.  
  49. local function getLegToUpdate(predictedcf, vel)
  50.     local nextLeft = getNextPosition(predictedcf * leftOff, rad(-vel.Z), rad(vel.X), 3)
  51.     local nextRight = getNextPosition(predictedcf * rightOff, rad(-vel.Z), rad(vel.X), 3)
  52.     local relLeft = (predictedcf:PointToObjectSpace((nextLeft + targRight)/2) * v3(1, 0, 1)).magnitude
  53.     local relRight = (predictedcf:PointToObjectSpace((nextRight + targLeft)/2) * v3(1, 0, 1)).magnitude
  54.     if relRight > relLeft then
  55.         return true, nextLeft
  56.     else
  57.         return false, nextRight
  58.     end
  59. end
  60.  
  61. local function updateLegs(leftOrigin, rightOrigin, leftPos, rightPos)
  62.     local d1 = (leftOrigin.p - leftPos).magnitude
  63.     beam1.Size = v3(0.5, 0.5, d1)
  64.     beam1.CFrame = cf(leftOrigin.p, leftPos) * cf(0, 0, -d1/2)
  65.     local d2 = (rightOrigin.p - rightPos).magnitude
  66.     beam2.Size = v3(0.5, 0.5, d2)
  67.     beam2.CFrame = cf(rightOrigin.p, rightPos) * cf(0, 0, -d2/2)
  68. end
  69.  
  70. game:GetService("RunService").RenderStepped:Connect(function(s)
  71.     local vel, speed = getVel()
  72.     local direction = getDirection()
  73.     rootPart.CFrame = cf(rootPart.Position) * ang(0, direction, 0)
  74.     local leftSet, rightSet
  75.     if speed > 0 or math.abs(lastspeed-speed)/s > 0  then
  76.         local delayOf = 0.3
  77.         if lastUpdate + delayOf < tick() then
  78.             lastUpdate = tick()
  79.             local predictedcf = predictPosition(head.CFrame, vel, delayOf)--*1.5)
  80.             local leftLeg, setPos = getLegToUpdate(predictedcf, vel)
  81.             updateLeft = leftLeg
  82.             if leftLeg then
  83.                 oldLeft = targLeft
  84.                 targLeft = setPos
  85.             else
  86.                 oldRight = targRight
  87.                 targRight = setPos
  88.             end
  89.         end
  90.         local alpha = math.min((tick()-lastUpdate)/(delayOf/2), 1)
  91.         if updateLeft then
  92.             leftSet = oldLeft:lerp(targLeft, alpha) + v3(0, 0.75*sin(pi*alpha), 0)
  93.             rightSet = targRight
  94.         else
  95.             rightSet = oldRight:lerp(targRight, alpha) + v3(0, 0.75*sin(pi*alpha), 0)
  96.             leftSet = targLeft
  97.         end
  98.         else
  99.         targLeft = getNextPosition(head.CFrame * leftOff, rad(10), rad(-5), 3)
  100.         targRight = getNextPosition(head.CFrame * rightOff, rad(-10), rad(5), 3)
  101.         oldLeft, oldRight = targLeft, targRight
  102.         leftSet, rightSet = targLeft, targRight
  103.     end
  104.     pos1.Position = leftSet
  105.     pos2.Position = rightSet
  106.     updateLegs(head.CFrame * leftOff, head.CFrame * rightOff, leftSet, rightSet)
  107.     lastspeed = speed
  108. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement