How to get targetSurface from camera Raycast?

i want make shift lock for mobile with point mouse or what ever name (:

i find a script give me a target (fr i forget if i got this from ai or on webside i will just input the script here).

local length = 100
local camera = workspace.CurrentCamera
viewportPoint = camera.ViewportSize / 2
unitRay = camera:ViewportPointToRay(viewportPoint.X, viewportPoint.Y, 0)
ray = Ray.new(unitRay.Origin, unitRay.Direction * length)
part = workspace:FindPartOnRay(ray)
print(part)

but now i need a TargetSurface i show just this
until now i cant find any thing to help also i dont really know how should this work like what should i do to get targetSurface on camera
and i got this script and its also give me a random surfaces (: someone help what should i do

local function GetEnumNormalFromRay(ray :RaycastResult)    
	local part: Part = ray.Instance
	local Position = ray.Position    

	local Normal = {
		[1] = {Position = part.Position + part.CFrame.RightVector * part.Size.X/2, EnumNormal = Enum.NormalId.Right},
		[2] = {Position = part.Position + part.CFrame.RightVector * -part.Size.X/2, EnumNormal = Enum.NormalId.Left},
		[3] = {Position = part.Position + part.CFrame.UpVector * part.Size.Y/2, EnumNormal = Enum.NormalId.Top},
		[4] = {Position = part.Position + part.CFrame.UpVector * -part.Size.Y/2, EnumNormal = Enum.NormalId.Bottom},
		[5] = {Position = part.Position + part.CFrame.LookVector * -part.Size.Z/2, EnumNormal = Enum.NormalId.Front},
		[6] = {Position = part.Position + part.CFrame.LookVector * part.Size.Z/2, EnumNormal = Enum.NormalId.Back},
	}        

	local Closest = Normal[1]

	for _,Side in pairs(Normal) do
		local lookForward = Vector3.FromNormalId(Side.EnumNormal)
		local lookToPoint = (Side.Position - Position).unit

		local angle = math.deg(math.acos(math.clamp(lookForward:Dot(lookToPoint), -1, 1)))

		if (Side.Position - Position).magnitude < (Closest.Position - Position).magnitude then
			if angle < 90 then
				Closest = Side
			end
		end
	end

	return Closest.EnumNormal
end

local length = 1000
local camera = workspace.CurrentCamera
viewportPoint = camera.ViewportSize / 2
unitRay = camera:ViewportPointToRay(viewportPoint.X, viewportPoint.Y, 0)
raycastResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * length)
if raycastResult then
	targetSurface = GetEnumNormalFromRay(raycastResult)
	print(targetSurface.Name)
else
	print("No object hit by the ray.")
end

also i will never rotate object (: if its should help

you should try using nox7’s roblox luau mouse target surface script on github.
on its own it prints the Enum.NormalId of the TargetSurface (Top, Right, etc)

i would also recommend adding RaycastParams so that the ray doesn’t intersect with the character.
so change the getRayCollisionNormal() function to:

local function getRayCollisionNormal(x,y)
	local rayIgnoreParams = RaycastParams.new()
	rayIgnoreParams .FilterType = Enum.RaycastFilterType.Exclude
	rayIgnoreParams .FilterDescendantsInstances = game.Players.LocalPlayer.Character:GetDescendants()

	local cam = workspace.CurrentCamera
	local unitRay = cam:ScreenPointToRay(x,y)
	local rayResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * maxRayDistance, rayIgnoreParams)
	if (rayResult) then
		local instance = rayResult.Instance
		local normal = rayResult.Normal

		-- Get an object-space normal for rotated instance
		if (instance) then
			normal = instance.CFrame:VectorToObjectSpace(normal)
		end

		return normal or nil;
	end
end

its still give me a random values i dont know but look if i made something wrong

maxRayDistance = 100
viewportPoint = workspace.CurrentCamera.ViewportSize
local function getRayCollisionNormal(x,y)
	
	
	local rayIgnoreParams = RaycastParams.new()
	rayIgnoreParams.FilterType = Enum.RaycastFilterType.Exclude
	rayIgnoreParams.FilterDescendantsInstances = game.Players.LocalPlayer.Character:GetDescendants()

	local cam = workspace.CurrentCamera
	local unitRay = cam:ScreenPointToRay(x,y)
	local rayResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * maxRayDistance, rayIgnoreParams)
	if (rayResult) then
		local instance = rayResult.Instance
		local normal = rayResult.Normal

		-- Get an object-space normal for rotated instance
		if (instance) then
			normal = instance.CFrame:VectorToObjectSpace(normal)
		end

		return normal or nil;
	end
end
print(getRayCollisionNormal(viewportPoint.X/2, viewportPoint.Y/2))

your code is close, but the original code has some last minute calculations to get the normal id.

heres a beefy script that’ll hopefully work for you that does those calculations inside of the function

local maxRayDistance = 100
local mouse = game.Players.LocalPlayer:GetMouse()
--------------- Function ---------------
local function getRayTargetSurface(x,y)
	local function getRayCollisionNormal()
		local rayIgnoreParams = RaycastParams.new()
		rayIgnoreParams.FilterType = Enum.RaycastFilterType.Exclude
		rayIgnoreParams.FilterDescendantsInstances = game.Players.LocalPlayer.Character:GetDescendants()

		local cam = workspace.CurrentCamera
		local unitRay = cam:ScreenPointToRay(x,y)
		local rayResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * maxRayDistance, rayIgnoreParams)
		if (rayResult) then
			local instance = rayResult.Instance
			local normal = rayResult.Normal

			-- Get an object-space normal for rotated instance
			if (instance) then
				normal = instance.CFrame:VectorToObjectSpace(normal)
			end

			return normal or nil;
		end
	end
	local hitNormal = getRayCollisionNormal(x, y)
	local surface = nil;

	if (hitNormal) then
		local dotY = hitNormal:Dot(Vector3.new(0,1,0))
		local dotX = hitNormal:Dot(Vector3.new(1,0,0))
		local dotZ = hitNormal:Dot(Vector3.new(0,0,1))
		if (math.abs(dotY) >= 0.9) then
			if (dotY < 0) then
				surface = Enum.NormalId.Bottom
			else
				surface = Enum.NormalId.Top
			end
		elseif (math.abs(dotX) >= 0.9) then
			if (dotX < 0) then
				surface = Enum.NormalId.Left
			else
				surface = Enum.NormalId.Right
			end
		else
			if (dotZ < 0) then
				surface = Enum.NormalId.Front
			else
				surface = Enum.NormalId.Back
			end
		end
	end
	
	return surface
end
----------------------------------------
while wait(1) do -- Test by repeating every 1 second
	print(getRayTargetSurface(mouse.X, mouse.Y))	
end
1 Like

much love for you you really fix my problem (: thank you

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.