Particle on a Humanoid

What I would do would be relatively simple:

  1. Insert a BasePart using instance.new from either the Client or Server. If it is created by the Client, it won’t be seen by other players. If it is created by the Server, other players would see your dust particles.
  2. Use a RunService loop to keep this part at the desired position. I recommend a position around here for your BasePart: HumanoidRootPart.CFrame - Vector3.new(0,2,0).
  3. Create a Particle Emitter within the BasePart using Instance.new. Adjust the particle emitter to your liking.
  4. Now that you have your particles working, you will have to make sure that the particles only enable when the player is moving. Here is some code I found in EgoMoose’s Character Controller which returns if the player is moving or not:
function Module:isMoving()
	local moveSq = ClientHumanoid.MoveDirection:Dot(ClientHumanoid.MoveDirection);
	return moveSq > 0 and ClientHumanoidRootPart.Velocity.magnitude > 4;
end
  1. In a RunService loop, check if the player is moving. If the player is moving, enable the particle emitter:
if Module:isMoving() then
    ParticleEmitter.Enabled = true;
else
    ParticleEmitter.Enabled = false;
end
  1. (Optional) If you want to disable the dust particle while in the air, just add this to the code above:
if ClientHumanoid.FloorMaterial == Enum.Material.Air then
    ParticleEmitter.Enabled = false;
else
    if Module:isMoving() then
        ParticleEmitter.Enabled = true;
    else
        ParticleEmitter.Enabled = false;
    end
end

Hope this helps!

1 Like

This goes in StarterCharacterScripts correct?

I would execute it through a module in the replicated-storage (executed by the client), however, a local script in the StarterCharacterScripts / StarterPlayerScripts would potentially work. Don’t take my word for it!

1 Like

Honestly. I think that would be quite unecessary to do a RunService loop CFraming particles. And maybe this would hurt performance. The script i have provided works fine, i guess…


But i would like to talk with you through messages about how the code you provided works! I want to learn a bit :slight_smile:

1 Like

I tried your code and it does work! But I would like to have it at the feet and not the whole body

Oh, in this case, instead of checking if there are parts, baseparts and meshes, you can check if the part is named X, also, this works for R15 and R6, if you are asking me.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Particles = ReplicatedStorage:FindFirstChild("Put your Particle name here") --Remember to put Your particle in ReplicatedStorage!

local Parts = script.Parent:GetChildren()

for _, Part in pairs(Parts) do
    if  Part.Name == "LeftFoot" or Part.Name == "RightFoot" or Part.Name = "RightLeg" or Part.Name = "LeftLeg" then
        local ParticlesInChar = Particles:Clone()
        ParticlesInChar.Parent = Part
    end
end
2 Likes

Hi TriipXX, I see what you’re talking about. So you want to make particles come out the player’s feet when ever they step. Personally, I like the particles to come out each foot individually, so this is the way I did it, I’m pretty sure you can optimize this even more.

local hrp = Figure:WaitForChild("HumanoidRootPart")
local runningSound = Instance.new("Sound")
runningSound.Parent = hrp
runningSound.SoundId = "rbxassetid://481217914"
runningSound.Volume = 2

local rightAttach = Figure:WaitForChild("Right Leg"):WaitForChild("RightFootAttachment")
local leftAttach = Figure:WaitForChild("Left Leg"):WaitForChild("LeftFootAttachment")

local rightParticles = script:WaitForChild("Dust"):Clone()
rightParticles.Parent = rightAttach
local leftParticles = script:WaitForChild("Dust"):Clone()
leftParticles.Parent = leftAttach

For this to work, you first have to copy the “Animate” default script (which I’ve sure you’ve done) and put it in StarterCharacterScripts. Remember some of these things are already predefined for R6 models, but you might have to change some stuff around for R15. So this code block initializes the running sound. The rightAttach and leftAttach is default attachments instances on Roblox’s R6 character (this is where the particles will spawn), right below the foot. I almost made pre-made dirt particles that is a child of the Animate script. Make sure the particles Rate property is set to zero, as we want to control when the particles spawn.

image

Now in the animate script, there is already a built in function for when an “Keyframe is reached”. Basically, you can rename different keyframes in your animation to do different things. For this example, for my run animation, I named right when the player stepped on the ground’s keyframe “LeftStep”, and I did the same with the right.

Control + F in the Animate script and find function keyFrameReachedFunc(frameName)
This function automatically fires when a keyframed is reach in an animation, such as “LeftStep” and “RightStep” accordingly.

You want to put this inside the code:

if frameName == "LeftStep" then
	runningSound:Play()
	leftParticles:Emit(1)
elseif frameName == "RightStep" then
	runningSound:Play()
	rightParticles:Emit(1)
end

frameName is the current KeyFrame’s name. By default it’s named “KeyFrame” but assuming you changed the name or the keyframe with no spelling errors “LeftStep” and “RightStep” keyframes are in your animation.

Now, all there is left to do is test it!

As you can see it works beautifully!

12 Likes

Oh nice. Now does this only work for animated running animations?

Yes, it only works if you make a custom running animation and rename the Keyframes accordingly.

Oh cool. I’ll try this code in a little bit this seems like it works. Thank you for this I will let you know if it works or not. Also before I try this where do I put the first and second script? For the second do I put it below keyFrameReachedFun(frameName) or the same line its on? I want make sure this is right.

You put it inside the function. Again, if your rig is different you may need to rename some things in the script for it to work. For example the “Figure” variable might be renamed to “Character” on the R15 animate script or “Left Leg” will be “LeftFoot” on the R15 rig. Watch out for that.

1 Like

Ok, I’ll try it later thanks again! Sorry for the dumb questions I’m not so good at scripting or reading it.

Whenever you can…check your messages!!

If i am wanting to put a particle into a player’s character i first put a ParticleEmitter in the StarterCharacterScripts, this is because all the scripts in there go into the player’s character. Next i put a Script in StarterCharacterScripts and i type this code.

local e = script.Parent.ParticleEmitter
local e2 = e:Clone() 


e.Parent = script.Parent.RightFoot
e2.Parent = script.Parent.LeftFoot

I hoped this helped! If you need me to explain it, i will if i can (depending on the time).

I recently tried this and it doesn’t seem to work. Meaning when I spawn it’s connected to my feet but when I move it doesn’t move with me

You can check my post:

That does help but that is not exactly what I am looking for. But I am going to use yours for a damage effect. @DevKaister response helps the most (waiting for his reply). But I’ll show you a showcase of what I am going to use yours for.

Aha, I have finally come up with a working solution that works well! I hope it works for you.

Put this in code in a LocalScript in StarterPlayer.StarterPlayerScripts.

The Code
-- The player.
local player = game:GetService("Players").LocalPlayer

player.CharacterAdded:Connect(function(char)
	-- Wait for the player's character to spawn.
	
	local humanoid = char:WaitForChild("Humanoid")
	
	-- Get the feet, so we can add particles to them.
	local leftFoot = char:WaitForChild("LeftFoot")
	local rightFoot = char:WaitForChild("RightFoot")
	
	-- Create the initial ParticleEmitter. You might want to tweak the rate, speed, etc.
	local particle = Instance.new("ParticleEmitter")
	particle.Texture = "rbxassetid://242008870"  -- Asset URI of the particle.  I just used a toolbox one here.
	particle.Rate = 5
	particle.EmissionDirection = Enum.NormalId.Back
	particle.Speed = NumberRange.new(1)
	particle.Lifetime = NumberRange.new(1, 2)
	
	-- Whether or not a ParticleEmitter already exists in the feet, so we don't accidentally make 2.
	local spawned = false
	
	local pClone = particle:Clone()
	pClone.Parent = leftFoot
	local rpClone = particle:Clone()
	rpClone.Parent = rightFoot
	
	pClone.Enabled = false
	rpClone.Enabled = false
	
	-- Keep checking whether or not the player is moving.
	while true do
		local val = humanoid.MoveDirection
		
		if((humanoid.FloorMaterial ~= Enum.Material.Air) and (val.X ~= 0 or val.Y ~= 0 or val.Z ~= 0)) then
			if(spawned == false) then
				-- Set spawned to true, so we know the ParticleEmitters are enabled
				spawned = true
				
				-- Enabled the ParticleEmitters.
				pClone.Enabled = true
				rpClone.Enabled = false
			end
		else
			if(spawned) then
				-- Set spawned to so we know that they are disabled.
				spawned = false
				
				if(pClone ~= nil and rpClone ~= nil) then
					pClone.Enabled = false
					rpClone.Enabled = false
				end
			end
		end
		wait()
	end
end)

Happy coding! :grinning:

where would I put the particles?

You don’t need to put them anywhere, the script creates the particles automatically.