How to make an ESP/Chams effect (see through walls)

    Hello! I noticed that nobody has given a good tutorial on how to do this effect, leaving many to wonder if using ViewportFrames are their only option. I have come across a much simpler method which I will explain here.

What are ESP/Chams?

    In this post, when I say "ESP/Chams" I am referring to the kind of "wall-hack" where you can distinctly see the silhouette of the object in question. Such as this:

Screenshot 2025-05-07 221237

Simple ESP / Chams Guide

Screenshot 2025-05-07 220558

    For this effect you can create a Highlight instance either as a direct child of the target or with its Adornee property set to the target. It can be seen both directly and through walls.

I’m pretty sure you’re supposed to put Highlights in the PlayerGui, but I haven’t had any issues sticking them in a Model/Part in the workspace on the client side.


Occluded ESP / Chams Guide

Screenshot 2025-05-07 215524

How does it work?

    Highlights behind other visible Highlights apparently do not get rendered. We can use this to “mask” the highlight that should only be seen behind obstructions.

    To create this effect, you can make an object/model with a Highlight set to Occlude which will be the line-of-sight Highlight. Then, clone that object/model and set the new Highlight to AlwaysOnTop which will be the occlusion Highlight.

That is all you need to do to get this effect working. Here are some tips:

  • Perform size = size * 0.99 on the occlusion Instance to avoid z-fighting with the line-of-sight Highlight.

  • If you need the target to move around, use WeldConstraints to keep the occlusion Instance flush with the line-of-sight Instance.

  • You can set the line-of-sight Highlight FillTransparency to 0.999 to have no highlight on visible sections of the target (first picture in topic).

  • You can add the accessories to the occlusion Highlight as well, I just personally like this effect more.


Code

This is the script that generates Occluded Chams on the local Character.

I have also included an rbxl file if you would rather just jump in and see the effect.

note: this doesn’t handle first-person interactions with the highlights. Let me know if you want me to include how to do that in this guide.

Download: OccludedChams.rbxl (56.7 KB)

LocalScript:

local plr = game:GetService("Players").LocalPlayer

local chr = plr.Character or plr.CharacterAdded:Wait()


local chamsChr = Instance.new("Model")
chamsChr.Parent = workspace
chamsChr.Name = "ChamsChr"

for _, child in pairs(chr:GetChildren()) do

	if not child:IsA("BasePart") then continue end

	local cloned = child:Clone()
	cloned.Parent = chamsChr
	cloned:ClearAllChildren()
	cloned.CanCollide = false
	if cloned:IsA("MeshPart") then cloned.TextureID = "" end

    cloned.Size = cloned.Size * 0.99 -- prevents z-fighting with the line-of-sight Highlight 

	local weld = Instance.new("WeldConstraint") -- weld the chams part to its corresponding part so it stays flush
	weld.Parent = cloned
	weld.Part0 = cloned
	weld.Part1 = child
end


-- create the "line-of-sight Highlight"
local losHighlight = Instance.new("Highlight")

losHighlight.Parent = chr

losHighlight.DepthMode = Enum.HighlightDepthMode.Occluded

losHighlight.FillColor = Color3.new(1, 0, 0)

losHighlight.OutlineTransparency = 1


-- create the "occlusion Highlight"
local occHighlight = losHighlight:Clone()

occHighlight.Parent = chamsChr

occHighlight.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop

occHighlight.FillColor = Color3.new(0, 0, 1)

occHighlight.FillTransparency = 0


You should be sure to make these effects on the client side so that it causes no server lag.

I will update this thread accordingly if I find more unique ways to use the Highlight instances in such a manner. Let me know if you have questions, feel that I didn’t explain something well enough, or have anything to add to this guide!

7 Likes

Hey @azavier123!

This is a very clean and helpful guide. Thanks for putting this together!

Using Highlight for ESP is super efficient and client-safe, especially compared to ViewportFrames, which can be overkill and tricky to manage.

The visual example and clear explanation make it easy to follow. Definitely bookmarking this!

Looking forward to any updates you add later! :rocket:

1 Like

Compared to ViewportFrames, yes. But is it a reliable alternative? no, it only supports up to 31 highlights at a time

As a performance limit, Studio only displays 31 simultaneous Highlight instances on the client at a time

2 Likes

The word you’re looking for is “foolproof”, not reliable. I’m willing to say doing it with Highlights is much more reliable in every single way except for that one small drawback.

That issue can be mitigated quite easily. it’s not like you should have 31 highlight instances being displayed at any given time anyway. The most natural solution (using Occluded Chams as an example) would be to group all similar highlights into one model. For example, there would be a lineOfSightHighlight model and also an occlusionHighlight model. Then you just need 2 highlight instances in total for this system to work with as many players as you need (and you still have 29 highlight slots to work with).

1 Like