Easier Way To Detect A Player Behind A Wall?

Okay so, how would I detect when a player is behind a wall and make the wall transparent?

As I’ve stated previously, I have no clue how you have the heiarchy of your buildings ordered. Because what I’d do is check if you had a building, and if so, say your heiarchy was like this:

image

In the code I’d alter it to be like:

local player = game.Players.LocalPlayer

local camPos = workspace.CurrentCamera.CFrame.Position
local rootPos = player.Character.HumanoidRootPart.Position

local result = workspace:Raycast(camPos,(rootPos-camPos).Unit*250)

if result then -- check if we hit something
    local character = result.Instance.Parent -- defining the character, you get the part that was hit but the character is a model, so you'd go part.Parent.
    local humanoid = character:FindFirstChild'Humanoid' -- this is a way to tell if it is a character, if you can find the humanoid
    if not humanoid then -- we're checking if there ISN'T a humanoid present
        if char:IsA'Model' and char.Name == 'Walls' then -- checks if we have hit a wall and not some other object
            for i,v in pairs(char:GetChildren())do -- this whole loop function gets all the walls in the model and makes them invisible
                if v:IsA'BasePart' then
                    v.Transparency = 1
                end
            end
        end
    end
end

That should check if there’s a wall and if it is a wall it’ll get all the walls and make them transparent. Of course the exact code won’t work in your case due to you having a different building organization than I do but it gets the idea across I hope.

Alright, lemme see if this work.

What exactly is char supposed to be? There is no instance of char and it’s appearing as a error in the script.

Oh, my apologies, char is supposed to be character, I accidentally abbreviated it :sweat_smile:

I think a ray casted from the player’s camera’s position to the player’s character’s position would work well, if it hits something in between then you’ll know the player is behind an object.

The raycast API is fairly simple if you look at it the right way.

Raycasts consists of 3 things: the origin (starting point), direction (how much it extends), and params (whitelisting parts, blacklisting parts, etc.)

What you’re going to do, is raycast from the origin (camera position), to the players position (cameraPos - characterPos), and use a whitelist for all the parts that you can see through:

local Character = Player.Character
local Camera = workspace.Camera

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Whitelist --> Only the parts in "FilterDescendantsInstances" will be considered
params.FilterDescendantsInstances = {} --> Walls go in here

game:GetService("RunService").RenderStepped:Connect(function() --> Runs every frame
    local cameraPos = Camera.CFrame.Position --> Getting the camera position
    local characterPos = Character:GetPrimaryPartCFrame().Position --> Getting the character position
    local raycastResult = workspace:Raycast(cameraPos, (characterPos - cameraPos), params)
    if raycastResult then --> A wall intercepts the camera and the character
        --> Make walls transparent
    else
        --> Make walls opaque
    end
end)

What exactly would I make transparent? I tried raycastResult.Transparency, but it kept indexing nil and when going behind a wall it wouldn’t work.

The RaycastResult is what workspace:Raycast() returns if it hits something. To get the part hit, you’d have to do raycastResult.Instance:

This works well, but how would I make the transparency go back to normal?

So would I do something like raycastResult.Instance.Transpareny?

No, not in this case. You’re making wall1, wall2, wall3, and wall4 transparent when any of them intercepts the players view. So, when you hit a wall, make all of them transparent. If it doesn’t hit a wall, make them opaque again. RaycastResult only returns the Instance hit (so only one wall), not all of them.

I tried

local Character = game.Players.LocalPlayer.Character
local Camera = workspace.Camera

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Whitelist 
params.FilterDescendantsInstances = {} 

game:GetService("RunService").RenderStepped:Connect(function() 
	local cameraPos = Camera.CFrame.Position  
	local characterPos = Character:GetPrimaryPartCFrame().Position 
	local raycastResult = workspace:Raycast(cameraPos, (characterPos - cameraPos), params)
	if raycastResult then 
		workspace.house.Walls.wall2.Transparency = 0.6
	else
		workspace.house.Walls.wall2.Transparency = 0
	end
end)

And it didn’t work.

You didn’t even whitelist anything yet. Insert workspace.house.Walls.wall2 into the table, along with the other walls.

You should have something like this:

1 Like

Works good, thanks! (30 carsh)

Hey! This might be old but your script seems very useful. How can I make a table for it though?

local Character = game.Players.LocalPlayer.Character
local Camera = workspace.Camera

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Whitelist 
params.FilterDescendantsInstances = {workspace.Model.Parto} 

game:GetService("RunService").RenderStepped:Connect(function() 
	local cameraPos = Camera.CFrame.Position  
	local characterPos = Character:GetPrimaryPartCFrame().Position 
	local raycastResult = workspace:Raycast(cameraPos, (characterPos - cameraPos), params)
	if raycastResult then 
		workspace.Model.Parto.Transparency = 0.6
	else
		workspace.Model.Parto.Transparency =  0
	end
end)

I just editted some and yes, it is working. However, I want to do it in multiple parts without copy pasting the script and setting the script individually. How do I do it? For example, in Whitelist, I got two models. “workspace.Model.Parto” and “workspace.Model.Testing”. These two are far away from each other. How do I make it transparent in one script when it blocks the view? I tried experimenting but when I get blocked by the part called “Parto”. Both the testing and Parto get quite invisible.