Need help with a new (possibly more dynamic) animation equation

Keywords that you might not know because they’re system specific:
MovementIntensity: How wide of an arc the “Figure eight” has.
MoveDuration: How long it takes the animation method to complete the figure eight.

I’ve created an FPS where the arms/guns are connected to a central part, which is placed at the center of the camera, and then moved dynamically to create that little shake movement when you walk or sprint.

The animation is rougly a sideways figure 8 that I created using sine waves, but getting smooth interpolation between different intensity’s and durations of animations has presented a challenge for me, as I’m not incredible at math, but i can get by.

Right now, I have a series of static “Walk Styles” that have predetermined Movement intensity’s and durations. As I add accelerated movement and walkspeeds, it makes the system feel very cheap, so I use static walkspeeds.

This is the method that handles the “breathing” effect, as I call it.

function character:StartBreathing()
	spawn(function()
		local renderstepped = game:GetService('RunService').RenderStepped
		local AnimTime = 2.3
		local lastTick = tick()
		local PercentPosition = 0
		character.Properties.isBreathing = true
		local lastpercent = PercentPosition
		local laststep = 0
		while renderstepped:wait() do
			character.Properties.Walkspeed:update()
			game.Players.LocalPlayer.Character:FindFirstChild("Humanoid").WalkSpeed = character.Properties.Walkspeed.position
			if character.Properties.Speed >= 1 then
				if (tick() - laststep) > 10/character.Properties.Speed then
					character:FootStep()
					laststep = tick()
				end
			end
			local ElapsedTime = (tick() - lastTick)/(character.Properties.MoveDuration * AnimTime)
			lastTick = tick()
			PercentPosition = PercentPosition + ElapsedTime
			local x = math.sin(math.rad((PercentPosition) * 360)) * 4
			local y = math.sin(math.rad((PercentPosition * 2) * 360)) * 4
			character.Properties.NeckOffset = CFrame.new(math.rad(x*character.Properties.MoveIntensity),math.rad(y*character.Properties.MoveIntensity),0)
			camera.Properties.ShakeOffset = CFrame.new() * CFrame.Angles(-math.rad((y*character.Properties.MoveIntensity)/7),-math.rad((x*character.Properties.MoveIntensity)/15),0)
			lastpercent = PercentPosition
			if PercentPosition >= 1 then
				PercentPosition = 0
			end
			if not character.Properties.isBreathing or not game.Players.LocalPlayer.Character then
				break
			end
		end
	end)
end

and this is the event that calls the method that interpolates the Duration and Intensity

character.Running = game.Players.LocalPlayer.Character:WaitForChild('Humanoid').Running:connect(function(S)
	local State = game.Players.LocalPlayer.Character.Humanoid:GetState()
	character.Properties.Speed = S
	if State ~= Enum.HumanoidStateType.Jumping and State ~= Enum.HumanoidStateType.Freefall and State ~= Enum.HumanoidStateType.FallingDown then
		if (S >= 1) and (S <= 10) and character.Properties.walkStyle ~= 'Slow' and not character.State.Wallrunning and not character.State.Aiming then
			character.Properties.walkStyle = 'Slow'
			character:SetMovementIntensity(.2,4)
		elseif (S > 10) and (S <= 26) and character.Properties.walkStyle ~= 'Walk' and not character.State.Sprinting and not character.State.Wallrunning and not character.State.Aiming then
			character.Properties.walkStyle = 'Walk'
			character:SetMovementIntensity(.6,.5)
		elseif S > 19 and character.Properties.walkStyle ~= 'Sprint' and character.State.Sprinting  then
			character.Properties.walkStyle = 'Sprint'
			character:SetMovementIntensity(1.8,.35)
		elseif (S < 1) and character.Properties.walkStyle ~= 'Stopped' and not character.State.Aiming and not character.State.Wallrunning then
			character.Properties.walkStyle = 'Stopped'
			character:SetMovementIntensity(.2,4)
		elseif (S >= 1) and (S <= 10) and character.Properties.walkStyle ~= 'AimSlow' and not character.State.Wallrunning and character.State.Aiming then
			character.Properties.walkStyle = 'AimSlow'		
			character:SetMovementIntensity(.03,4)
		elseif (S < 1) and character.Properties.walkStyle ~= "AimStopped" and character.State.Aiming and not character.State.Wallrunning then
			character.Properties.walkStyle = 'AimStopped'		
			character:SetMovementIntensity(.01,4)
		end
	else
		--character:SetMovementIntensity(.2,4)
	end
end)

I’d like to move away from this incredibly static method, but I’m not sure where to begin. I can provide the SetMovementIntensity method if you need it, but it essentially just performs a linear interpolation between the old and new intensity’s/durations. It is called like this:

character:SetMovementIntensity(newIntensity, newDuration)

Any guidance/assistance is greatly appreciated, thank you for taking the time to read this far, I know it’s a lot to process

5 Likes

I’m still not sure what direction to go for this. It’s not the smoothest movement equation on the planet.