How would you make a giant's footsteps trigger camera shake for nearby players?

I am trying to make a large skinned mesh player’s footstep animation events activate screenshake on each step for regular robloxian players that are in range, while the skinned mesh player and other skinned mesh players do not see those screenshakes (because they are large).

I’ve been looking for how this might be done, but so far haven’t found anything that specifically applies. I’ve tried looking at several different tutorials to piece them together (camera shake when monster is near, custom footstep sounds, camera shake on explosion) but I’m having trouble tying them together for this specific case.

I’m not new to roblox studio but I have struggled a lot with scripting over the years, a more indepth explanation would be super appreciated, but any advice is much appreciated! :happy1:

1 Like

Here, I have put together a test place using @ sleitnick’s Shake module:
CameraShake.rbxl (65.4 KB)
Here is the source code (all modules used are included in the file):

local Shake = require(script.Shake) -- We are using sleitnick's Shake module.

local function shakeCamera()
	local shakeInstance = Shake.new() -- Create a new shake instance
	
	shakeInstance.FadeInTime = 0.1 -- Time taken for shake to tween in
	shakeInstance.Frequency = 0.01 -- How often the camera should shake
	shakeInstance.Amplitude = 0.075 -- How big should each shake be
	shakeInstance.SustainTime = 0.2 -- How long the shake should last
	shakeInstance.FadeOutTime = 0.1 -- Time taken for shake to tween out
	
	shakeInstance:Start() -- Initialize the shake
	shakeInstance:BindToRenderStep(shakeInstance.NextRenderName(), Enum.RenderPriority.Camera.Value, function(pos, rot, isDone) -- Connect to render stepped loop
		workspace.Camera.CFrame *= CFrame.new(pos) * CFrame.Angles(rot.X, rot.Y, rot.Z) -- Update camera CFrame with the given position and rotation
		
		if isDone then
			return shakeInstance:Destroy() -- If shake is done, we destroy the shake instance as we no longer need it
		end
	end)
end

while task.wait(3) do
	shakeCamera() -- For testing, call this function whenever you want the camera to shake
end
1 Like

If you don’t want to use a module, another option might be modifying the player’s character’s humanoid’s CameraOffset.

--LocalScript
local runService = game:GetService("RunService")
local players = game:GetService("Players")

--get the player's character
local player = players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")

local function onStep()
    --check whether a shake is already happening to prevent weird things.
    if hum.CameraOffset ~= Vector3.zero then return nil end


    --compare the distance between the object and the player
    local distance = (part.CFrame.Position - char.HumanoidRootPart.CFrame.Position).Magnitude
    if distance < 10 then --less than 10 studs away from each other
        for i = 1, 50, 1 do --shake 50 times, with random offset values
            local xNum = math.random(1, 20) / 10
            local yNum = math.random(1, 20) / 10
            local zNum = math.random(1, 20) / 10
            local newOffset = Vector3.new(xNum, yNum, zNum)
            hum.CameraOffset = newOffset
        end
        --reset the offset
        hum.CameraOffset = Vector3.zero
    end
end

runService:BindToRenderStep("Shake", 2000, onStep)
3 Likes