Part Will Not Face Me

  1. What I Want To Achieve: I want to make it so the wall part that is spawned in will turn and face the player.

  2. The Issue: When I use the tool, the part spawned in is always in the same direction.

  3. Solutions I have Tried: I have tried :Lerp, CFrame.LookAt, and LookVector

Video url: 2023-07-30 20-36-01

Client Code
local localPlayer = game:GetService("Players").LocalPlayer
local event = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvents")["Combat"]["Wall"]
local clonedPart

script.Parent.RequiresHandle = false
script.Parent.Equipped:Connect(function()
	
	local hrp = script.Parent.Parent:WaitForChild("HumanoidRootPart")
	local part = Instance.new("Part")
	clonedPart = part
	part.Transparency = 0.8
	part.Parent = game:GetService("Workspace").CurrentCamera
	
	spawn(function()
		while clonedPart do
			local pos = hrp.Position + hrp.CFrame.LookVector*5 
			part.CFrame = CFrame.new(pos, hrp.Position) * CFrame.new(0,-2.5,0)
			task.wait(0.01)
		end
	end)
	
end)

script.Parent.Activated:Connect(function()
	
	if not clonedPart then return end
	local hrp = localPlayer.Character.HumanoidRootPart
	local pos = hrp.Position + hrp.CFrame.LookVector*5
	local ray = Ray.new(clonedPart.Position, Vector3.new(0, -0.5, 0))
	local _, _, _, material = workspace:FindPartOnRayWithWhitelist(ray, {workspace.Terrain})
	
	if material == Enum.Material.Air then return end
	if material == Enum.Material.Water then return end
	
	event:FireServer(clonedPart.Position, material, pos)
	clonedPart:Destroy()
	clonedPart = nil
	
end)

script.Parent.Unequipped:Connect(function()
	
	if clonedPart then
		clonedPart:Destroy()
		clonedPart = nil
	end
	
end)
Server Code
local wall = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvents")["Combat"]["Wall"]

wall.OnServerEvent:Connect(function(plr, position, material, angle)
	
	local currentTime = tick()
	local LastUsed = wallCdList[plr] or 0
	if currentTime - LastUsed > 30 then
		
		local wallPart = game:GetService("ReplicatedStorage")["Earth Wall"]:Clone()
		wallPart.Material = material
		if material == Enum.Material.Asphalt then
			wallPart.Color = Color3.fromRGB(115, 123, 107)
		elseif material == Enum.Material.Basalt then
			wallPart.Color = Color3.fromRGB(30, 30, 37)
		elseif material == Enum.Material.Brick then
			wallPart.Color = Color3.fromRGB(138, 86, 62)
		elseif material == Enum.Material.Cobblestone then
			wallPart.Color = Color3.fromRGB(132, 123, 90)
		elseif material == Enum.Material.Concrete then
			wallPart.Color = Color3.fromRGB(127, 102, 63)
		elseif material == Enum.Material.CrackedLava then
			wallPart.Color = Color3.fromRGB(232, 156, 74)
		elseif material == Enum.Material.Glacier then
			wallPart.Color = Color3.fromRGB(101, 176, 234)
		elseif material == Enum.Material.Grass then
			wallPart.Color = Color3.fromRGB(158, 162, 158)
		elseif material == Enum.Material.Ground then
			wallPart.Color = Color3.fromRGB(107, 106, 101)
		elseif material == Enum.Material.Ice then
			wallPart.Color = Color3.fromRGB(129, 194, 224)
		elseif material == Enum.Material.LeafyGrass then
			wallPart.Color = Color3.fromRGB(158, 162, 158)
		elseif material == Enum.Material.Limestone then
			wallPart.Color = Color3.fromRGB(206, 173, 148)
		elseif material == Enum.Material.Mud then
			wallPart.Color = Color3.fromRGB(44, 42, 40)
		elseif material == Enum.Material.Pavement then
			wallPart.Color = Color3.fromRGB(70, 67, 64)
		elseif material == Enum.Material.Rock then
			wallPart.Color = Color3.fromRGB(102, 108, 111)
		elseif material == Enum.Material.Salt then
			wallPart.Color = Color3.fromRGB(198, 189, 181)
		elseif material == Enum.Material.Sand then
			wallPart.Color = Color3.fromRGB(143, 126, 95)
		elseif material == Enum.Material.Sandstone then
			wallPart.Color = Color3.fromRGB(137, 90, 71)
		elseif material == Enum.Material.Slate then
			wallPart.Color = Color3.fromRGB(63, 127, 107)
		elseif material == Enum.Material.Snow then
			wallPart.Color = Color3.fromRGB(195, 199, 218)
		elseif material == Enum.Material.WoodPlanks then
			wallPart.Color = Color3.fromRGB(139, 109, 79)
		end
		wallPart.CFrame = CFrame.new(position)
		wallPart.Parent = game:GetService("Workspace")
		
		local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 0, false, 0)
		local goal1 = {Size = Vector3.new(1.25, 15.125, 12.5)}
		local goal2 = {Size = Vector3.new(1.25, 0, 12.5)}
		tweenService:Create(wallPart, tweenInfo, goal1):Play()
		
		spawn(function()
			task.wait(10)
			tweenService:Create(wallPart, tweenInfo, goal2):Play()
			task.wait(0.5)
			repeat
				wallPart.Transparency += 0.05
				task.wait(0.01)
			until wallPart.Transparency >= 1
			wallPart:Destroy()
		end)
		
	end
	
end)

Sorry for how long the scripts are, any help would be appreciated, thank you!

It’s because your create the cframe in world space you have to make it object space so it’s relative to your player’s humanoidrootpart

1 Like

So how would you fix this? I am quite confused. I read the documentation (at least when I searched it up I got this: 3D Workspace | Documentation - Roblox Creator Hub ) yet I am still quite confused on how to fix this.

2 Likes

How about you try first making the part orient to the humanoidrootpart’s cframe and then do your offset calculations

2 Likes

I will try that as soon as I can and let you know how it goes!

2 Likes

A few things I noticed in your script

  1. CFrame.new() is a deprecated function, keep using CFrame.lookAt()
  2. Use coroutines instead of spawn() - spawn is deprecated
  • coroutines allow for more flexibility
coroutine.wrap(function()

end)()

// As opposed to

spawn(function()

end)
  1. NEVER a good idea to pass through positions to the server through a remote and rely on those - allows for easy exploitation.
  2. Instead of using a While(true) loop and using task.wait() - which relies on the servers heartbeat, even better:
  3. Get all the services at the top of the script (readability and reduce redundancies)
local RunService = game:GetService("RunService")

// This will be much smoother for the client
RunService.RenderStepped:Connect(function()
   // Do Work
end)

Now to answer your question:
The reason your part is always being placed in the same direction, is because you’re using .Position when you fire server.
Why is this a problem? .Position doesn’t take into account the orientation of an object.
If you want to have the object face your character, it’d probably be more reliable to get the CFrame of your characters primary part or root part like so: localPlayer.Character.PrimaryPart.CFrame.
As a result, you’ll need to change the code on your server where the .Position is also being set for the wall → Doing something like wallPart.CFrame = char.PrimaryPart.CFrame will fix your problem.

To conclude:

Here’s my solution:

wallPart.CFrame = plr.Character.PrimaryPart.CFrame

Where you are going wrong:

Setting the position of the wall like this:

wallPart.CFrame = CFrame.new(position)

is the same as:

wallPart.Position = position

Which won’t change the objects orientation at all.

Sorry if I got out of scope a little bit, was just pointing out some mistakes I used to make when I also started :slight_smile:

2 Likes

Hello, Joel! Thank you so much for your response, it really did help a lot. I still have one slight problem though, using your code

wallPart.CFrame = plr.Character.PrimaryPart.CFrame

will still spawn it to the side of my character. However, it does face my character!

I tried to tweak it to the best of my ability and the closes I got was this code snippet right here,

wallPart.CFrame = plr.Character.PrimaryPart.CFrame + (plr.Character.PrimaryPart.CFrame.LookVector * 5)

Video link: 2023-07-31 04-32-33

I do not know if this is the model issue or if I can some how fix this within my script, my friend is the modeller not me and he is currently on a vacation!

P.S. I do really appreciate your detailed response. I am currently trying to implement all the changes that you recommended to me!

1 Like

Hey! Sorry for the late response, just got off of work not too long ago.

I noticed the primary problem with your script happens to be that the object is not properly rotated

wallPart.CFrame = plr.Character.PrimaryPart.CFrame * (plr.Character.PrimaryPart.CFrame.LookVector * 20) * CFrame.Angles(0,math.rad(90),0)

This will offset the part 20 studs in front of the players character and rotate it 90 degrees about the Y axis.

Or you can approach it like this (once you understand world + object space will be a lot more readable than my previous solution):

wallPart.CFrame = wallPart.CFrame:ToWorldSpace(CFrame.new(0,0,20)) * CFrame.Angles(0,math.rad(90),0)

The two code blocks I sent should be equivalent in functionality.

But does CFrame.Angles do? A CFrame constructor that helps you create precise rotations.
What does math.rad do? math.rad(90) = 90 degrees

  • Note that rad stands for radians, and math.rad(90) will convert degrees to radians.
1 Like

No worries about late responses, I do the same too. I am still kinda lost, it won’t work. I even implemented some of my own changes but nothing got close to it. The main issue with the first one is that it keeps throwing me an error about Vector since I have to change the multiplication sign to a plus sign for the radians. The second just spawns it in the middle of no where and doesn’t face you. I am kinda lost on what to do next.

1 Like

I see, I probably wrote down the order of the multiplications wrong for the first one. Still happens to me all the time haha.

An easy solution would be to go to the wallParts properties, and change the pivot point orientation of the wallPart to be 0,90,0 → Or if there is already a rotation, just add or subtract 90 from it. Should get the same effect without having to worry about multiplying the extra CFrame!

2 Likes

Thank you so much! Thank you for being patient, giving me tips on how to improve my actual code, and fixing my issue. I did what you said and did the orientation and with these two lines I fixed it.

wallPart.CFrame = plr.Character.PrimaryPart.CFrame + (plr.Character.PrimaryPart.CFrame.LookVector * 5)
wallPart.CFrame = wallPart.CFrame:ToWorldSpace(CFrame.new(0,0,0)) * CFrame.Angles(0,math.rad(90),0)

Thank you so much, I appreciate it a lot.

1 Like

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