Problems with surface normal

  1. What do you want to achieve? Keep it simple and clear!
    I’m trying to place a part with a decal over a wall using raycast.

  2. What is the issue? Include screenshots / videos if possible!
    For some reason I haven’t been able to figure out the part won’t appear as I want to, it’s horizontal instead of vertical and close to the wall.

What I get:
image

What I want:
image
(From: “Surface normal help” post by [rek_kie]"

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve tried to straight up copy and paste code that should work for what I want and applying it to my needs but it will still appear like that.

The raycast:

		local ray = Ray.new(Part.Position, Part.CFrame.LookVector *  500)
		local hit, pos, normal = game.Workspace:FindPartOnRayWithIgnoreList(ray,{Part})
	      EffectsEv:FireAllClients("WallBurn", Character, pos, normal)

The CFrame:

	Event.OnClientEvent:Connect(function(Type, Char, pos, normal)
		local Effect = RP.FX.Crack_Burn:Clone()
		Effect.Parent = workspace

		if pos then
			local cf = CFrame.lookAt(pos, pos + normal)
			Effect.CFrame = cf * CFrame.new(0, 0, -(Effect.Size.Z / 2))
		end
         end)

It’s horizontal because the decal’s face is likely Top and not Front
You can fix this by making the Z-component of the effect part’s size flat, and the X/Y as intended
I don’t see the need for a raycast to be called on the server to dictate the properties of something such as an effect

-- variables

local Player					= game:GetService("Players").LocalPlayer
local Character					= Player.Character or Player.CharacterAdded:Wait()
local RootPart					= Character.HumanoidRootPart

local EffectModel				= RP.FX.Crack_Burn

-- setup for raycast function; this is custom & forked from my personal utils module
-- Ray.new is deprecated and should not be used
local WhitelistParams			= RaycastParams.new()
WhitelistParams.FilterType		= Enum.RaycastFilterType.Whitelist
WhitelistParams.IgnoreWater		= true

local function WhitelistRay(Origin : Vector3, Direction : Vector3, Whitelist : Array<Instance>): RaycastResult
	WhitelistParams.FilterDescendantsInstances = Whitelist
	return workspace:Raycast(Origin, Direction,WhitelistParams)
end

local function RenderCrackEffect()
	local RaycastResult : RaycastResult = WhitelistRay(RootPart.Position, RootPart.CFrame.LookVector * 500, {workspace})
	assert(RaycastResult, "no part/instance found to render effect")
	local NewEffect = EffectModel:Clone()
	NewEffect.Parent = workspace
	NewEffect.CFrame = CFrame.lookAt(RaycastResult.Position, RaycastResult.Position + RaycastResult.Normal) -- * CFrame.new(0, 0, 0.01) -- possibly offset by 0.01 so it can be visible
	task.spawn(function() -- destroy effect after 1 second
		task.wait(1)
		NewEffect:Destroy()
	end)
end

EffectsEv.OnClientEvent:Connect(function() RenderCrackEffect() end)
1 Like

Yup, I just noticed that too. But thank you, if I hadn’t checked the part I wouldn’t have noticed it.