How can I check if a player is facing a part?

I’m attempting to make a vaulting system. I need to check if the player is facing the part they’re going to vault over, because it wouldn’t make sense if you were able to vault backwards. I’m pretty sure I’d have to use raycasting for something like this, but I’m not exactly sure how I would achieve what I’m desiring.
image
image
This is what I have so far. The transparent red part is the zone. The yellow part is the part the player will vault over. I want to make it so the player can only vault if they’re facing the yellow part. I want to make it so they don’t have to be looking at the part up and down, just left and right.


TL;DR: How can I check if a player is facing a part with their left/right rotation, and ignore their up/down rotation?

1 Like

This guy might help you find out

6 Likes

This would work, but there are some problems. I’m doing this on server, not local script, so I used Stepped instead of RenderStepped, but I’m having problems with the player who entered the zone.

zone.playerEntered:Connect(function(player)
-- player works here
        print(player)
	local RunService = game:GetService("RunService")
	RunService.Stepped:Connect(function(player)
-- player does not work here
		print(player)
	end)
end)

Is there a way to get around this?

1 Like

Have you tried doing this yet? The angles should be similar to the ones in the video from before.

2 Likes

you could make a ray from the head and check if the ray hit the part but if you want it to see like us players maybe you could add the dot product and some mangnitude

You can, but you really shouldn’t. This wouldn’t work if the part is above or below your head while still in your field of view. It’s also inefficient compared to the previous method, as it would need to cast a ray constantly.

1 Like

i updated my post to be more realistic ^^^

After doing some experimenting, I’ve ended up with this code.

zone.playerEntered:Connect(function(player)
	local function dotProduct()
		local str = "workspace.%s"
		return string.format(str, player.Name).Head.CFrame.LookVector:Dot(zoneGroup.CFrame.LookVector)
	end
	local str = "workspace.%s"
	local product = dotProduct(string.format(str, player.Name), zoneGroup)
end)

It’s probably really inefficient but who cares. I’m not very good with CFrames. I keep getting the error “attempt to index nil with ‘CFrame’” Do I just need to create CFrames in the part and the player? I was thinking they’d already be in the player by default.

1 Like

Can you try using workspace:FindFirstChild(player.Name) instead and see if it works?

Ignore what I just said, try using the player’s character object instead.

2 Likes

You are on the right track with using dot products, and they are not inefficient at all, actually dot product by itself is very fast.
By doing the dot product between the two LookVectors you can very quickly compare how closely their directions match (since they are by definition unit vectors). So when you place your activation zone, their LookVector should point in the direction that you want to allow the jump, and at runtime each frame you make sure that the character is within a certain range of this direction, by using the dot product (you want it that to be close to 1, which means both vectors are pointing exactly in the same direction)
However there only inefficient part in your code is having to do the string format to get the player’s model, which is very slow to do every frame. I would say you probably need to either cache that value (e.g. a table indexed by name) or find a way to get a direct reference to it from the parameter object (e.g. by using Tags or similar). good luck!

2 Likes

I was talking about how I did the workspace string thing, not the dot products. This is still good to know though

Ah gotcha. Well good thing it’s still useful. One more tip: if you want to ignore the difference in vertical orientation like you mention in your first post, you can just “flatten” both LookVectors by creating new vectors with same X and Z components but 0 for Y. then you do the dot product as usual, and it tells you how much their horizontal directions match, ignoring up/down look difference

I got a problem. My output shows that every 2nd value is -nan(ind)… whatever that means
Thanks in advance!

RunService.Heartbeat:Connect(function()
	for i,v in pairs(workspace:GetChildren()) do
		if v.ClassName == "Model" then
			local character = v:findFirstChildOfClass("Humanoid").Parent
			local characterToNpc = (npc.HumanoidRootPart.Position - character.HumanoidRootPart.Position).Unit
			local characterLook = character.HumanoidRootPart.CFrame.LookVector
			local dotProduct = characterToNpc:Dot(characterLook)
			if character.Humanoid.Health > 0 and not game.Players:GetPlayerFromCharacter(character.Parent) then
			print(dotProduct)
				if dotProduct > 0 and not looking then
					looking = true
				elseif looking then
					looking = false
				end
			end
		end
	end
end)

Nevermind. I figured it out, Dot was returning dotProduct of the npc itself which is -nan(ind).
Thanks anyways.