[ Advanced Tutorial ] Remote-less Footsteps

Hi there! :wave:

nickibreeki here. Today I’ll be teaching you guys how to create a Footstep Script without using any kind of RemoteEvents, from my perspective!
----------------------------------------------

Requirements

All you need to know is your basic understanding how the script or the program work,
Everything is is noob friendly! which mean no noob is being harm from this…
Welp! that it!

----------------------------------------------

People’s Perception

Most people think that creating footstep sounds is one of the hardest things to do.
Well, most people who are new to scripting or intermediate scripters always say that it’s hard because it wastes server resources by firing the remote every time a player moves.

But we’re not going to do that!
Who would fire the remote every time they walk, right? :woman_shrugging:

----------------------------------------------

Layout/Planning

Whenever you work on something, you need to plan! Planning will make your work get done faster.
I’ll be using a flowchart because it’s very easy to understand just a tree of processes that we’re going to follow.

“Let’s get to the main tutorial already.”

I mean, sure! No more yapping…! :eyes:

----------------------------------------------

STEP 1 - Create ModuleScript

First of all, we need a :scroll:ModuleScript
To get this or insert this instance, Right-Click, place your cursor on ⧉ Insert Object…, and you’ll see the search box in case you couldn’t find the :scroll:ModuleScript

This instance will be placed in ReplicatedStorage, PURR-FECT! :cat2:

RobloxStudioBeta_qEdnuhdlpw

Now, create another :scroll:ModuleScript inside the :scroll:ModuleScript that we just created! We’ll name this “FootstepData” because we’ll store all audio IDs here!

----------------------------------------------

Step 2 - Create Directory for Audio

Now, once you pass Step 1 - Create ModuleScript :white_check_mark:,
We’ll create the folder to store our audio files!

Same thing Right-Click on the :scroll:ModuleScript that we just created, find :file_folder:Folder.

It can be :file_folder:Folder, :file_folder:Model, or anything that you can recognize as storing audio!

RobloxStudioBeta_mQkPg4V53R

You did great! Now, in the next step, we’ll program it to make it work!
YES, YOU HEARD THAT RIGHT, THE PROGRAMMING PART!

----------------------------------------------

Step 3 - Get it to work

Alright, let’s review what we’ve done.

:white_check_mark: - We created 2 ModuleScripts: “Main” and “FootstepData”.
:white_check_mark: - We created the directory for our Footstep Audio.

image

If you’ve followed my steps and done everything correctly, then congratulations!! :+1:
If it doesn’t look like the image, just make it look like the exact image!

Short Yapping :speaking_head:

This part might make you feel like, “I don’t want to do this anymore,” but WAIT!!! A game without any kind of programming section, how is it going to be playable, right? Without programming, the game will just turn into a funny generic obby game instead of an enjoyable one.

FIRST, WE’LL NOT GET INTO THE MAIN PROGRAMMING PART JUST YET.
FIRST, WE NEED TO DO THE GOVERM- I MEAN- YEAH, COLLECT! COLLECTING! AUDIO IDs :eyes: :sweat_drops:

Man, every time I mention collecting, why do I have to drag politics into this thread too…


image

BACK TO THE MAIN TOPIC

Alright, now Double Click on your :scroll:FootstepData (ModuleScript). We’ll be adding Audio IDs here.

Once you’re done inserting Sound IDs into the table, we’ll start programming our main system script.

Main System

Once you’re done inserting Sound IDs, you can close the :scroll:FootstepData (ModuleScript) tab.
After closing that tab, Double Click on your :scroll:Main (ModuleScript)
You’ll be greeted with an empty ModuleScript.

Alright, we’ll import the services that we need to use for this.
image
This is all we’re using! That’s it!

Now, we’ll create our first function. This function will check/validate the :sound::file_folder:Audio Container.

This function will check and validate whether that folder exists or not. If it doesn’t, it will create one. Alright, now let’s put all the audio in the folder with this function!


Holy grilled! Even my house doesn’t have a grill! What on earth is this function?! Well, this function will create new audio, which will be parented to the :sound::file_folder:Audio Container!

Utility Functions

EDITTED: At the line 61, Please removed MoveDirection ~= Vector3.new() It’s appeared to be my mistake! Thanks @BossSpax

These two functions are utilities that will be used with footsteps!
The first function’s title already explains what it does, so you probably understand it because it’s very essential!

The second function is “MovingCheck”.
This function is used to validate whether the :man_standing: Actor/Character is moving or not by tracking the :man_standing::gear: Humanoid.States and the :man_running:Humanoid.MoveDirection that the humanoid is moving toward.

Event Functions

Let’s break down each function, step-by-step.

The First Function is :new::gear: onCharacterAdded

First, we’ll get the Humanoid and FootstepDirectory and determine the empty variable “Connection”, which we’ll use to manage the Footstep. Instead of using Humanoid.Running, we’ll use RunService.Heartbeat.

We’ll also register the tick on the Actor/Character, because why not? I’m kind of lazy…
We’ll hook the coroutine with the Connection variable, and inside the coroutine, we have the RunService.Heartbeat and Humanoid.Died triggers. When Humanoid.Died is triggered, the Connection will be terminated.

The Second Function is :man_running::gear: OnHumanoidRunning

EDITTED: At the line 92, Please change the SetAttribute to GetAttribute!

First, we’ll determine the Velocity, which is returned as a Vector3. We’ll convert it to a single number using :three::straight_ruler:Vec3().Magnitude

Then, we’ll measure whether the player is actually moving or not.
When the :man_standing: Actor/Character moves, the value of the Velocity will change, so when we convert it to a single number, we’ll get the speed of the :man_standing: Actor/Character as it rises up to the WalkSpeed value.

When it’s more than 0, we’ll pass another check: the :man_standing::gear: MovingCheck - Function
When the :gear: Function returns True, we’ll proceed to get the :foot::brick: Humanoid.FloorMaterial, which will return the :brick:Enum Item of Enum.Material

We’ll pass the value returned by :foot::brick: Humanoid.FloorMaterial and find the :sound: Sound that matches the Enum.Material in our :scroll: FootstepData ModuleScript

When we get the :sound: Sound, we’ll trigger the Sound with a randomized volume.
When everything is done, we’ll hook the trigger to the MoveSpeed of the Humanoid.

The next thing is to enable the Footstep, and we’re all done with the first part!
There’s more, but we’ll get into that later!

Register The Events!

Lastly, but very important, we’ll register the events to the client!

After this function, we’re done! But that’s not all…
To make it works, It’s need some small work… !

SERVER-SIDE

we’ll hook the module with the server to create the audio to the audio container!

require(path_to_module):init()

CLIENT-SIDE

Same as how Server done but do the different! the system will be hook with LocalPlayer and Other Player and logging new player too!

require(path_to_module):init()

----------------------------------------------

Thanks for your participating my thread!

Thanks for your interest, I hope you got new knowledge from this thread!
Some word you may not understand my apology because i’m not a english native speaker !
something that you think is missing, You can reply to this thread to helping other people!

----------------------------------------------

Support me :coffee:

Currently there’s only 2 way to support my creation, You can show your support by

----------------------------------------------

Thanks @BossSpax for Bug Hunting! I just realize that there’s bunch of mistake appear on this tutorial!

Are you satisfying with my Tutorial?
  • Yeah! :grin:
  • It’s Ok :+1:
  • Kinda Meh :neutral_face:
  • Nah… :expressionless:

0 voters

23 Likes

Could this not have been done by just editing the RbxCharacterSounds script? This would have the added bonus of being able to add additional sounds like landing fairly trivially, the only difference functionally would be that you wouldn’t be able to play sounds at a set interval like you did here. (which honestly, I think you still could with additional effort)

  1. As far as I’m aware you can’t use MoveDirection on other peoples clients (so this will always return false). Base it off their Running state as Roblox does.
  2. (minor) Use a pre-made Random instead of making a new one each time.
  3. (also minor, but if sound ids have issues can be a memory leak) Base your sound destroy time off of TimeLength and PlaybackSpeed instead of using the Ended event. This is honestly preference but I do think it’s better practice as you can do it all in one line.
  1. You used SetAttribute instead of GetAttribute
  2. And this stuff is memory leak haven as you never disconnect either one. I can see conceptually that you think closing the thread would disconnect everything, but that’s just not how it works. (threads don’t function the same as unique scripts)
  1. The code in this has an edge case where it can error if any player does not have a character when you join.
  2. You never handle if the player doesn’t have a character when they join (huge issue in round based games)

(nitpick) Why do you do that whole isfrozen stuff, you already know its not frozen. Return table.freeze(module) straight up as that’s the only result it could ever be.

Everything else said I do appreciate you promoting doing character client side based off already known character state, and not making the server a middle man (some ppl still mess this up).

3 Likes

It’s also can be done on the RbxCharacterSounds too but for this tutorial is about making the custom one, Instead of using pre-made by @Roblox

Yeah you’re right, That’s my mistake right there, We’ll just straight remove only 1 section is MoveDirection then it’s will check only State and Velocity. Because this script is untested with 2 client…

:eyes::sweat_drops: I didn’t notice that there’s SetAttribute on the Variable, I’ll be fix the thread, Thanks for looking my mistake!

:eyes: Most round-based games store the player character far away, but this tutorial is made for one purpose only: to show how footsteps are done. If developers know their game is round-based and their characters don’t automatically spawn, they will know how to handle this. Let them manage that part.

Also, you mentioned nitpicking details. I know those things might seem unnecessary, but that’s how I want it done.

Overall I glad that you help me out with bug hunting Thanks you!

3 Likes