Echo Location Visual Effect Tutorial

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):

77 Likes

I love it. I am going to playtest your game now.

2 Likes

My gosh, looks incredible!
This is the sort of thing that I’ve wanted for ages without knowing it! This could be used for loads of things, like some horror games, or even showcases! Great job! :smile:

3 Likes

Btw for anyone whos still interested in doing this, I plan to reupload this tutorial making building with this visual effect a whole lot easier. I also made a few mistakes in this tutorial such as not tweeting the part locally for a smoother and much nicer transition.

9 Likes

I can see this cool effect being useful in horror games. Someone better make one with it!

1 Like

Awesome! Can’t wait to see it!

2 Likes

It looks amazing. But how could I make the echo react to a Sound?

u need to use an attachment as the sound’s parent and then use the attachment’s position to determine where the sound is