Footsteps ability similar to MM2

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? I’d like to make a script that shows the footsteps of every player, similar to Murder Mystery 2. I want to make it toggle-able. Where should I start?

  2. What is the issue? I don’t know where to start. I have plenty of scripting experience but I have never tried a script like this. I’m not very acquainted with tracking velocity of objects, although I do have experience in causing velocity.

  3. What solutions have you tried so far? I’ve googled and searched the DevForum for a while but I haven’t found anything.

I am in no way shape or form asking for code, I’d just like some guidance. I’m assuming to create this footstep effect is to make a part with the footstep decal every time the player’s HumanoidRootPart moves a couple of seconds. Help me out, please?

1 Like

I don’t have much experience in something like this either, but the first thing I’d try is:

  1. Create like a 1 stud part with the footstep
  2. When you want to cast it, clone that part and position it at their HumanoidRootPart position - Vector3.new(0, root.Size.Y /2 , 0)

I’m gonna check it out in studio right now and update you if it worked or not.

1 Like

Thanks for your contribution, I also will be testing this. Thanks!

It would be generally better to raycast downwards for accuracy concerns. Plus small raycasts are not heavy calculations.

2 Likes

That would probably be a better idea, I couldn’t get my code to work.

I couldn’t get it to work either. I know the position is wrong, but I kept it like that so I could mess around and adjust it, but I couldn’t adjust it as the part didn’t even appear. (script parented to the part)

local List = {}

table.insert(List,workspace["Respawning Dummy"].Dummy) -- debug purposes
for _,plr in pairs(game.Players:GetPlayers()) do
	if plr ~= game.Players.LocalPlayer then
		table.insert(List,plr)
	end
end
game.Players.PlayerAdded:Connect(function(plr)
	table.insert(List,plr)
end)
game.Players.PlayerRemoving:Connect(function(plr)
	if plr ~= game.Players.LocalPlayer then
		table.remove(List,table.find(List,plr))
	end
end)

task.wait(5)

while true do
	task.wait(1)
	print(List)
	for _,plr in pairs(List) do
		if plr:IsA('Model') then -- debug purposes
			local clone1 = script.Parent:Clone()
			local clone2 = script.Parent:Clone()
			clone1.Script:Destroy()
			clone2.Script:Destroy()
			print(CFrame.new(plr:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-5,0)))
			clone1.CFrame = CFrame.new(plr:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-5,0))
			clone2.CFrame = CFrame.new(plr:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-5,0))
		elseif not plr:IsA('Model') then
			local clone1 = script.Parent:Clone()
			local clone2 = script.Parent:Clone()
			clone1.Script:Destroy()
			clone2.Script:Destroy()
			print(CFrame.new(plr.Character:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-5,0)))
			clone1.CFrame = CFrame.new(plr.Character:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-5,0))
			clone2.CFrame = CFrame.new(plr.Character:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-5,0))
		end
	end
end

I got it to half work, I parented the clones to the workspace and now all I need to fix is the position.

I’ve gotten it perfect! Thanks! I didn’t use raycasting as I found just editing the raw vector3 was easier. Here’s my product!
footstep.rbxm (5.9 KB)

2 Likes

Currently, I’m bug fixing and tweaking, this comment only has a very rough base.

Turns out I need a bit more help,
image

local List = {}

table.insert(List,workspace["Respawning Dummy"].Dummy) -- debug purposes
for _,plr in pairs(game.Players:GetPlayers()) do
	if plr ~= game.Players.LocalPlayer then
		table.insert(List,plr)
	end
end
game.Players.PlayerAdded:Connect(function(plr)
	table.insert(List,plr)
end)
game.Players.PlayerRemoving:Connect(function(plr)
	if plr ~= game.Players.LocalPlayer then
		table.remove(List,table.find(List,plr))
	end
end)

task.wait(4)

while true do
	task.wait(1)
	for _,plr in pairs(List) do
		if plr:IsA('Model') then -- debug purposes
			local clone1 = script.Parent:Clone()
			local clone2 = script.Parent:Clone()
			clone1.Script:Destroy()
			clone2.Script:Destroy()
			clone1.Parent = workspace
			clone2.Parent = workspace
			local a = plr:WaitForChild('HumanoidRootPart').CFrame - plr:WaitForChild('HumanoidRootPart').CFrame.Position
			local c1 = CFrame.new(Vector3.new(.6,0,0)) * a
			local c2 = CFrame.new(Vector3.new(-.6,0,0)) * a
			clone1.CFrame = CFrame.new(plr:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-3,0)) * c1
			clone2.CFrame = CFrame.new(plr:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-3,0)) * c2
			task.spawn(function()
				task.wait(5)
				clone1:Destroy()
				clone2:Destroy()
			end)
		elseif not plr:IsA('Model') then
			local clone1 = script.Parent:Clone()
			local clone2 = script.Parent:Clone()
			clone1.Script:Destroy()
			clone2.Script:Destroy()
			clone1.Parent = workspace
			clone2.Parent = workspace
			local a = plr.Character:WaitForChild('HumanoidRootPart').CFrame - plr.Character:WaitForChild('HumanoidRootPart').CFrame.Position
			local c1 = CFrame.new(Vector3.new(.6,0,0)) * a
			local c2 = CFrame.new(Vector3.new(-.6,0,0)) * a
			clone1.CFrame = CFrame.new(plr.Character:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-3,0)) * c1
			clone2.CFrame = CFrame.new(plr.Character:WaitForChild('HumanoidRootPart').Position + Vector3.new(0,-3,0)) * c2
			task.spawn(function()
				task.wait(5)
				clone1:Destroy()
				clone2:Destroy()
			end)
		end
	end
end
1 Like

I’ve just decided to leave it at this.
fixed.rbxm (5.8 KB)

I whipped up a little test version just to see how I’d go about making it. My result looked like this:
https://gyazo.com/f1a0fe6301449cbdf62dfee62fa80d13

And my code looked like this:

-- Client essentials
local player = game.Players.LocalPlayer
local character
local humanoid
local rootPart

local function onCharacterAdded(newCharacter)
	character = newCharacter
	humanoid = newCharacter:WaitForChild("Humanoid")
	rootPart = newCharacter:WaitForChild("HumanoidRootPart")
end
if player.Character then
	onCharacterAdded(player.Character)
end
player.CharacterAdded:Connect(onCharacterAdded)

-- Services :D
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local RepStorage = game:GetService("ReplicatedStorage")

-- Variables
local activeFootplacers = {}
local footstepModel = RepStorage:WaitForChild("Footstep")

local lastFootstepsPlaced = tick()
local DELAY_BETWEEN_PLACES = 0.4

-- Handling the table thingy
Players.PlayerAdded:Connect(function(p)
	activeFootplacers[p.Name] = p.CharacterAdded:Wait()
end)
task.wait(3) activeFootplacers[player.Name] = character -- testing it on myself

-- Main function
local function generateFooties()
	if tick() - lastFootstepsPlaced >= DELAY_BETWEEN_PLACES then
		lastFootstepsPlaced = tick()
		
		for _, char in pairs(activeFootplacers) do
			local leftFootstep, rightFootstep = footstepModel:Clone(), footstepModel:Clone()
			leftFootstep.CFrame = char.HumanoidRootPart.CFrame * CFrame.new(-Vector3.new(0.75, (char.HumanoidRootPart.Size.Y/2) + 2, 0))
			rightFootstep.CFrame = char.HumanoidRootPart.CFrame * CFrame.new(-Vector3.new(-0.75, (char.HumanoidRootPart.Size.Y/2) + 2, 0))
			
			leftFootstep.Parent = workspace
			rightFootstep.Parent = workspace
			
			local goAwayLeft = TweenService:Create(leftFootstep, TweenInfo.new(5), {
				Transparency = 1
			})
			local goAwayRight = TweenService:Create(rightFootstep, TweenInfo.new(5), {
				Transparency = 1
			})
			goAwayLeft:Play()
			goAwayRight:Play()
			
			goAwayLeft.Completed:Connect(function()
				leftFootstep:Destroy()
			end)
			goAwayRight.Completed:Connect(function()
				rightFootstep:Destroy()
			end)
		end
	end
end

RunService.Heartbeat:Connect(generateFooties)

[Edit]: Ah, just looked at your code and didn’t realize you wanted it to be done on the server. The “similar to MM2” in the title lead me to believe you only wanted to create footsteps locally.

2 Likes