Attempting to make a Camera-bob with a motion similar to this;
been unsuccessful so far,
So far I’ve attempted While loops and For i = 's to no prevail.
Was wondering if Tweening would be a better solution, and if so how would I go about it for this movement.
Seems like you need to implement a sine or cosine loop CFrame rotation to the camera’s CoordinateFrame.
Something like this might work. (I’m not compiling this/running it at all so there might be errors)
local RUN = game:GetService"RunService"
local player = game:GetService"Players".LocalPlayer
local camera = workspace.CurrentCamera
local startPart = workspace.CameraPart -- something you place to keep it facing forward
RUN:BindToRenderStep("CameraEffect", Enum.RenderPriority.Last.Value, function()
camera.CFrame = startPart.CFrame * CFrame.Angles(math.rad(math.sin(tick())), math.rad(math.sin(tick())), math.rad(math.sin(tick())))
end)
SOMETHING like this, I’m not really sure if it’ll get you what you want.
For camera movement, you will want to use RunService:BindToRenderStep()
This will allow your code to run as every frame is rendered, and will stop any jittering and tearing on the screen. Don’t go overboard with this though, as it yields the actual frame rendering and can easily reduce the framerate if you do too much processing.
In terms of the actual bobbing motion, it depends on what you want exactly, but I’d experiment with just some basic time-based stuff, and just define the movement using sines with different periods and amplitudes. To get a really intricately controlled effect you could create some keyframes or even use some sort of physical object that you bind the camera to, but it all depends on the details of what you are aiming for.
And yes this is exactly what I mean, although I would have the priority before the camera renders (Camera’s RenderPriority is 200, so use <200), rather than last, and mess with those different sines to get a more exact effect.
You’ll definitely want to use sine or cosine, as these produce waves over time.
Here’s a quick code sample I wrote up, it probably won’t work out of the box since I haven’t tested it but it should work somewhat.
local headbob = CFrame.new()
local dt = 0
local moving = true --use something to set whether the character is moving or not
--I assume this should only run when the character is walking or running but this will
--only implement walking
game:GetService("RunService").RenderStepped(s)
dt = dt + s
if not moving then dt = 0 end
headbob = headbob:lerp(CFrame.Angles(0.5 * math.sin(dt * 2), 2 * math.cos(dt * 0.6), 0), 0.7)
--you may want to change the 0.7 value, but this essentially makes it so when dt ends it smoothly
--transitions to CFrame.new() to end the animation
--camera.CFrame = --etc, however you want to set it
end)
When you use math.sin or math.cos;
(for example lets say a * math.sin(dt * b)) dt is the total time elapsed a is the amplitude or the exremity of the wave, smaller values make it smaller, while bigger make it bigger b is the speed or the wave, or how quickly is goes from positive to negative.
The black wave represents y = 5 * sin(x * 2) or 5 * math.sin(dt * 2)
The red wave represents y = 0.5 * sin(x * 0.75) or 0.5 * math.sin(dt * 0.75)
You’ll notice that this wave is very large in size (very high on y axis), this is because of the 5 which says how big it will be.
You’ll also notice that its pretty tight wave, this is because of the 2 which says its going to oscillate (go up and down) 2 times as fast as normal (if you wanted it to be in hertz, or cycles per second you would do dt*2*pi*2 as the sin and cos functions are trigonometric functions and have to do with circles, so by doing that it will complete 2 full cycles per second.
The second wave is much smaller because of the amplitude is much smaller (0.5) and is also much more stretched out (0.75).
You might want to layer on some noise as well. Using something strictly like sin or cos is fine, but it can look a bit unnatural. Adding some noise will make it feel more “real”