Hello, this is the very first tutorial I’ve ever created so I’m likely to screw something up. If you have any questions or suggestions go ahead and say something in the comments or message me.
If you have ever seen the game Lurking (there’s is a gameplay video by Markiplier if your curious they can hear you... | Lurking - YouTube), it has a really cool shader/visual effect that act like echos and after some experimenting, I was able to replicate it in Roblox studio. Ima just head into it and provide steps on how to do it and explain on the way, but note this isn’t just basic forcefield outlining a part, and making the exact visual effect can be extremely tedious/annoying.
I am currently making a game using this echolocation visual if you would like to check it out (it’s definitely not finished):
Step 1:
First, you start by making a part called “Echo”. This is simply a sphere that’s completely white, the material is ForceField, anchored is true, and CastShadow false. You can also just Instance.new() a part in but I find it easier to just clone from replicated storage, especially since we will be adding a child to the Echo object later. I suggest if your spawning the echo from the character you make the size of it (7.05, 7.05, 7.05) since having it too small will cause a slight camera obstruction.
Step 2:
Go ahead and put it in replicated storage when you’re done making the echo object. Depending on how you want to spawn the echo, you simply clone the Echo object from replicated storage into the workspace and give the position to where ever you want the echo to originate from. I’m just going to spawn an echo 5 studs above 0, 0, 0 every 5 seconds with a script called “SpawnEcho” in ServerScriptService. Side note: if your spawning from a character, I suggest spawning it -3.2 studs under the humanoidRootPart. This gives the echo the appearance that it’s coming from your feet, not your torso.
Code
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local echoObject = ReplicatedStorage.Echo
while wait(5) do
local echoClone = echoObject:Clone()
echoClone.Position = Vector3.new(0, 5, 0)
echoClone.Parent = workspace
end
Then tween the cloned echo so it fades out while also increasing in size; I suggest a size of 50. As you might notice it looks like the cheap echo I was talking about earlier but we aren’t done yet.
Code
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local echoObject = ReplicatedStorage.Echo
local echoInfo = TweenInfo.new(
3,
Enum.EasingStyle.Quint,
Enum.EasingDirection.Out,
0,
false,
0
)
local echoGoals = {
Size = Vector3.new(50, 50, 50);
Transparency = 1;
}
while wait(5) do
local echoClone = echoObject:Clone()
echoClone.Position = Vector3.new(0, 5, 0)
echoClone.Parent = workspace
TweenService:Create(echoClone, echoInfo, echoGoals):Play()
end
The Echo should look like this:
Step 3: Understanding this step takes some knowledge of normals and how they render but you could probably just find a box with inverted normals in the toolbox and not worry about it; basically, if you have a box with normals inverted, the inside of the box will be the only thing you can see and the faces which normally faces the viewer appears to be invisible. Combining this with a normal box you can make a sort of outline. Once you make the outline effect make sure that the middle part is neon black and the outline (inverted box) is plastic white. This is your new annoying building tool if your game is based on this echo visual.
Step 4: I suggest making a sort of room or identifiable thing before continuing with this step. Let’s go back to the Echo object and add a PointLight as a child of the part. Go ahead and copy the properties into the light object: Brightness = 500, Color = (255, 255, 255), Range = 1, and Shadows are off. You can experiment with this a bit, but I found these settings to be the best. You could also mess with the Shadows setting as true so that you can’t see echos through walls but you would still have the forcefield going through walls. If you don’t understand why we are doing this right now, don’t worry, it will make sense in the next/last step.
Step 5: Go ahead and tween the range and brightness of the PointLight we just made so that it mimics the echo (fades out as it gets bigger).
You won’t see much difference till this last part. Go ahead and set these lighting settings in the script:
LightSettings
Lighting technology = Voxel
local Lighting = game:GetService("Lighting")
Lighting.Brightness = 0
Lighting.Ambient = Color3.new(0, 0, 0)
Lighting.ColorShift_Bottom = Color3.new(0, 0, 0)
Lighting.ColorShift_Top = Color3.new(0, 0, 0)
Lighting.EnvironmentDiffuseScale = 0
Lighting.EnvironmentSpecularScale = 0
Lighting.GlobalShadows = false
Lighting.OutdoorAmbient = Color3.new(0, 0, 0)
Lighting.ClockTime = 0
Lighting.ExposureCompensation = 1
Lighting.FogColor = Color3.new(0, 0, 0)
Lighting.FogEnd = 1000
Lighting.FogStart = 500
You can experiment with this as much as you want though I find these settings work best.
That’s it! if you did everything correct you should get something like this:
Finial Code
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local Lighting = game:GetService("Lighting")
--Lighting Settings:
Lighting.Brightness = 0
Lighting.Ambient = Color3.new(0, 0, 0)
Lighting.ColorShift_Bottom = Color3.new(0, 0, 0)
Lighting.ColorShift_Top = Color3.new(0, 0, 0)
Lighting.EnvironmentDiffuseScale = 0
Lighting.EnvironmentSpecularScale = 0
Lighting.GlobalShadows = false
Lighting.OutdoorAmbient = Color3.new(0, 0, 0)
Lighting.ClockTime = 0
Lighting.ExposureCompensation = 1
Lighting.FogColor = Color3.new(0, 0, 0)
Lighting.FogEnd = 1000
Lighting.FogStart = 500
--End
local echoObject = ReplicatedStorage.Echo
local echoInfo = TweenInfo.new(
3,
Enum.EasingStyle.Quint,
Enum.EasingDirection.Out,
0,
false,
0
)
local echoGoals = {
Size = Vector3.new(50, 50, 50);
Transparency = 1;
}
local echoLightGoals = {
Range = 18;
Brightness = 0;
}
while wait(5) do
local echoClone = echoObject:Clone()
echoClone.Position = Vector3.new(0, 5, 0)
echoClone.Parent = workspace
TweenService:Create(echoClone, echoInfo, echoGoals):Play()
TweenService:Create(echoClone.PointLight, echoInfo, echoLightGoals):Play()
end
If you have any questions, I will try to answer them as soon as I can.
P.S. The echo does look different when coming from your character.
I am currently making a game using this echolocation visual if you would like to check it out (it’s definitely not finished):