Part not positioning correctly to the player

Goal

I’m creating a light admin command. How it’s supposed to work is; when a player says /light PLAYERNAME 255,0,0, the light model will go infront of the character as shown.

The light model is added, and edited on the server and is not created when the Player Joins, or the character is added. The light model is only created when an admin runs the light command.

Issue

The part’s position changes with the players turn. Here’s examples with the character facing opposite directions.

image | image

PivotTo Issue

I’ve tried using PivotTo already three times, it has not worked once for me.
image

The brick on the right that has no neon on it, is supposed to be the light. With this, when I use PivotTo, it teleports my character.
Here’s a video to show the issues with PivotTo.

Creating the Issue

How you create the problem is by doing the following;

  • Spawn your character,
  • Move away from the Position of 0,0,0,
  • Change your rotation so it isn’t 0,0,0,

The error will occur then.

Workarounds

  • Unknown.

Any recommendations to achieve this?

Script

This must go into an admin command, and you must be moved away from the original starting position of 0,0,0… else you will not recreate the error. This is triggered by an admin command, and is supposed to work no matter where the character looks, or is positioned in the world.

--[[This must go into an admin command, and you must be moved away from the original starting position of 0,0,0.. else you will not recreate the error. This is triggered by an admin command, and is supposed to work no matter where the character looks, or is positioned in the world.]]
task.wait(7)
local Workspace = game.Workspace;local PlayerName = "PUT_YOUR_PLAYERS_NAME_HERE"
if Workspace:FindFirstChild(PlayerName) and not Workspace:FindFirstChild(PlayerName.." Light") then
	local ModelOfLight = Instance.new("Model");
	ModelOfLight.Name = (PlayerName.." Light");
	ModelOfLight.Parent = game.Workspace
	local lightPart = Instance.new("Part");
	lightPart.Parent = ModelOfLight;
	ModelOfLight.PrimaryPart = ModelOfLight:FindFirstChild("Light");
	local NewLight = Instance.new("SurfaceLight",lightPart);
	local newWeld = Instance.new("Weld",lightPart)
	newWeld.Part0 = lightPart;
	newWeld.Part1 = Workspace[PlayerName].HumanoidRootPart;
	lightPart.Massless = true
	lightPart.Size = Vector3.new(0.7, 1.4, 2.2);
	lightPart.Name = "Light";
	lightPart.Anchored = false;
	lightPart.CanCollide = false;
	lightPart.Transparency = 0
	ModelOfLight.PrimaryPart = ModelOfLight:WaitForChild("Light",30);
	local PlayerPos = Workspace[PlayerName].PrimaryPart.Position 
	ModelOfLight.PrimaryPart.Position = Vector3.new(PlayerPos.X + 2,PlayerPos.Y + 3,PlayerPos.Z + 2)
	--ModelOfLight.PrimaryPart.Orientation = Workspace[PlayerName].HumanoidRootPart.Orientation - Vector3.new(40,0,0)
	NewLight.Range,NewLight.Brightness,NewLight.Face = 16,1,"Bottom"
end
3 Likes

Just pivot it to the needed CFrame and use a weld constraint instead of a weld

3 Likes

So… I did what you said;
image

This teleports the player to a new position, along with not setting the part correctly…

local PlayerPos = Workspace[PlayerName].PrimaryPart.Position 
ModelOfLight.PrimaryPart:PivotTo(CFrame.new(PlayerPos.X,PlayerPos.Y,PlayerPos.Z))
1 Like

Try checking the variables and make sure all of the local variables are actually connecting to what you want them to connect to. Try using print statements to make sure everything is where it should be, and make sure the HumanoidRootPart is being properly accessed. I’ve had similar issues before.

2 Likes

Everything is connecting correctly, the issue is that the part isn’t getting the correct CFrame essentially. I’m not sure how I’d even get that, as the play can be in a constant state of motion. If they look a specific way, they’ll get the correct area… but only in that instance. If I use CFrame, or Pivot To… the player moves as a result.

1 Like

I pasted the script you provided into a blank Roblox file and tried it out.

It don’t see any issues like described above.

Maybe some other script is causing issues.

1 Like

Did you try using it whilst moving in different directions, and not just on spawn?

This is a light command, that’s activated when an admin calls for it. It works when you look a specific way, but outside of that… it does not position the Light Part correctly

1 Like

Here is my test file:

Light.rbxl (53.3 KB)

It seems to work.

1 Like

Yeah, if you add a wait before the light is added… the light won’t line up correctly sadly. Thank you for looking at it though!
image

I don’t understand your comment.

You change the light position with the line:

ModelOfLight.PrimaryPart.Position = Vector3.new(PlayerPos.X + 0, PlayerPos.Y + 1, PlayerPos.Z + -8)

1 Like

@wastbo gave you the correct solution, I think you might have just implemented it incorrectly. Here’s what I modified in your code to make it give the expected output:

local Workspace = game.Workspace;local PlayerName = "PUT_YOUR_PLAYERS_NAME_HERE"
if Workspace:FindFirstChild(PlayerName) and not Workspace:FindFirstChild(PlayerName.." Light") then
	local ModelOfLight = Instance.new("Model");
	ModelOfLight.Name = (PlayerName.." Light");
	ModelOfLight.Parent = game.Workspace
	local lightPart = Instance.new("Part");
	lightPart.Parent = ModelOfLight;
	ModelOfLight.PrimaryPart = ModelOfLight:FindFirstChild("Light");
	local NewLight = Instance.new("SurfaceLight",lightPart);
	lightPart.Massless = true
	lightPart.Size = Vector3.new(2.2, 0.7, 1.4);
	lightPart.Name = "Light";
	lightPart.Anchored = false;
	lightPart.CanCollide = false;
	lightPart.Transparency = 0
	ModelOfLight.PrimaryPart = lightPart;
	ModelOfLight:PivotTo(CFrame.lookAt((Workspace[PlayerName]:GetPivot() * CFrame.new(0, 4, -4)).Position, Workspace[PlayerName]:GetPivot().Position))
	local newWeld = Instance.new("WeldConstraint",lightPart)
	newWeld.Part0 = lightPart;
	newWeld.Part1 = Workspace[PlayerName].HumanoidRootPart;
	NewLight.Range,NewLight.Brightness,NewLight.Face = 16,1,"Front"
end

This ensures that the part is always positioned 4 studs in front and above the player and will always face the player’s torso. Here are some pictures of the output:

image
image

Not sure if this achieves what you’re looking for but that’s what I assumed.

1 Like

I’ve updated my post to explain the goal in detail, how the model is added, and explaining how to error occurs.

I’ve added the issues PivotTo gives me when trying to use it with the light.

The reasons your solutions work; is because you’re spawning it immediately, instead of moving from the origin spawn point, and orientation. (0,0,0)

Thank you for trying though!

@ProgrammingRottie @wastbo @mc7oof @Maytronics13

1 Like

Here’s what I created to emulate the admin command (obviously not exact):

game.Players.PlayerAdded:Connect(function(Plr)
	
	local Char = Plr.Character or Plr.CharacterAdded:Wait()

	Plr.CharacterAdded:Connect(function(Character)
		Char = Character
	end)

	Plr.Chatted:Connect(function(msg)
		if (msg:find("/light")) then
			local ModelOfLight = Instance.new("Model");
			ModelOfLight.Name = (tostring(Plr).." Light");
			ModelOfLight.Parent = game.Workspace
			local lightPart = Instance.new("Part");
			lightPart.Parent = ModelOfLight;
			ModelOfLight.PrimaryPart = ModelOfLight:FindFirstChild("Light");
			local NewLight = Instance.new("SurfaceLight",lightPart);
			lightPart.Massless = true
			lightPart.Size = Vector3.new(2.2, 0.7, 1.4);
			lightPart.Name = "Light";
			lightPart.Anchored = false;
			lightPart.CanCollide = false;
			lightPart.Transparency = 0
			ModelOfLight.PrimaryPart = lightPart;
			ModelOfLight:PivotTo(CFrame.lookAt((Char:GetPivot() * CFrame.new(0, 2, -9)).Position, Char:GetPivot().Position))
			local newWeld = Instance.new("WeldConstraint",lightPart)
			newWeld.Part0 = lightPart;
			newWeld.Part1 = Char.HumanoidRootPart;
			NewLight.Range,NewLight.Brightness,NewLight.Face = 16,1,"Front"
		end
	end)
end)

Here’s a video of me running away from the origin, turning, and then chatting “/light” to run the command:

Can you send portion of the script that includes the admin command? Maybe that will help out a bit.

1 Like

I just tested yours in a different place and it works perfectly, and i’m not sure why it doesn’t work perfectly with mine. I’ll send the entire function I call in the admin module.

This is the light, and unlight command. These are located in a module in ServerScriptService.

What gets sent to the function is the player who calls it, and a message that gets split up between spaces in the message.

Essentially, /light PLAYERNAME BrickColor/Color3Value.

	["Light Command"] = { 
		CommandPhrases = {"light"}; 
		Level = 6,
		Hidden = false,
		Active = true,
		Description = "This will respawn the player to the spawn.",
		Function = function(plr,message) 
			local Module,Players,Workspace = CommunicationModule.FindModule("Functions"),CommunicationModule.FindService("Players"),CommunicationModule.FindService("Workspace")
			local TableOfPlayers = Module.Functions["Find Player"](plr,message)
			local ColorString = string.split(message," ")[2]
			warn("Current issue with Light Command; it doesn't light everyone when stating to :light all")
			for NumberPosition,PlayerName in pairs (TableOfPlayers) do
				if Workspace:FindFirstChild(PlayerName) and not Workspace:FindFirstChild(PlayerName.." Light") then
					local ModelOfLight = Instance.new("Model");
					ModelOfLight.Name = (PlayerName.." Light");
					ModelOfLight.Parent = game.Workspace
					local lightPart = Instance.new("Part");
					lightPart.Parent = ModelOfLight;
					ModelOfLight.PrimaryPart = ModelOfLight:FindFirstChild("Light");
					local NewLight = Instance.new("SurfaceLight",lightPart);
					local newWeld = Instance.new("WeldConstraint",lightPart)
					newWeld.Part0 = lightPart;
					newWeld.Part1 = Workspace[PlayerName].HumanoidRootPart;
					lightPart.Massless = true
					lightPart.Size = Vector3.new(0.7, 1.4, 2.2);
					lightPart.Name = "Light";
					lightPart.Anchored = false;
					lightPart.CanCollide = false;
					lightPart.Transparency = 0;
					ModelOfLight.PrimaryPart = ModelOfLight:WaitForChild("Light",30);
					local PlayerPos = Workspace[PlayerName].Head.Position
					ModelOfLight.PrimaryPart.Position = Vector3.new(PlayerPos.X,PlayerPos.Y+ 4.854,PlayerPos.Z - 8.532)
					local TBL = {"Players Position:"..tostring(PlayerPos),"Lights Position:"..tostring(ModelOfLight.PrimaryPart.Position)}
					warn(TBL)
					ModelOfLight.PrimaryPart.Orientation = Vector3.new(0,90,15)
					NewLight.Range,NewLight.Brightness,NewLight.Face = 13,1,"Left"
				end
				if Workspace:FindFirstChild(PlayerName) then
					local NewLight = Workspace:FindFirstChild(PlayerName.." Light").Light.SurfaceLight
					if ColorString ~= nil then
						local Color = string.split(ColorString,",")
						local R,G,B = Color[1],Color[2],Color[3]
						if (R and G and B) then
							NewLight.Color = Color3.fromRGB(R,G,B)
						elseif ColorString == BrickColor.new(ColorString) then
							NewLight.Color = BrickColor.new(ColorString)
						else
							error("Nothing to support the lighting color")
						end
					end
				end
			end
		end}
	;
	["Remove Light Command"] = {
		CommandPhrases = {"unlight"}; 
		Level = 6,
		Hidden = false,
		Active = true,
		Description = "This will respawn the player to the spawn.",
		Function = function(plr,message) 
			local Module,Players,Workspace = CommunicationModule.FindModule("Functions"),CommunicationModule.FindService("Players"),CommunicationModule.FindService("Workspace")
			local TableOfPlayers = Module.Functions["Find Player"](plr,message)
			local ColorString = string.split(message," ")[2]
			for NumberPosition,PlayerName in pairs (TableOfPlayers) do
				if Workspace:FindFirstChild(PlayerName) and Workspace:FindFirstChild(PlayerName.." Light") then
					Workspace[PlayerName.." Light"]:Destroy()
				end
			end
		end}
	;

I just now realized - but the reason for the teleportation is because you’re creating a weld between the part and the player’s primary part before you update the CFrame. I couldn’t really give you a technical reason as to why it happens but I know that is the cause of that issue.

Try replacing your code with this:

["Light Command"] = { 
		CommandPhrases = {"light"}; 
		Level = 6,
		Hidden = false,
		Active = true,
		Description = "This will respawn the player to the spawn.",
		Function = function(plr,message) 
			local Module,Players,Workspace = CommunicationModule.FindModule("Functions"),CommunicationModule.FindService("Players"),CommunicationModule.FindService("Workspace")
			local TableOfPlayers = Module.Functions["Find Player"](plr,message)
			local ColorString = string.split(message," ")[2]
			warn("Current issue with Light Command; it doesn't light everyone when stating to :light all")
			for NumberPosition,PlayerName in pairs (TableOfPlayers) do
				if Workspace:FindFirstChild(PlayerName) and not Workspace:FindFirstChild(PlayerName.." Light") then
			         local ModelOfLight = Instance.new("Model");
			         ModelOfLight.Name = (PlayerName.." Light");
			         ModelOfLight.Parent = game.Workspace
			         local lightPart = Instance.new("Part");
			         lightPart.Parent = ModelOfLight;
			         ModelOfLight.PrimaryPart = ModelOfLight:FindFirstChild("Light");
			         local NewLight = Instance.new("SurfaceLight",lightPart);
			         lightPart.Massless = true
			         lightPart.Size = Vector3.new(2.2, 0.7, 1.4);
			         lightPart.Name = "Light";
			         lightPart.Anchored = false;
			         lightPart.CanCollide = false;
			         lightPart.Transparency = 0
			         ModelOfLight.PrimaryPart = lightPart;
			         ModelOfLight:PivotTo(CFrame.lookAt((workspace[PlayerName]:GetPivot() * CFrame.new(0, 2, -9)).Position, workspace[PlayerName]:GetPivot().Position))
			         local newWeld = Instance.new("WeldConstraint",lightPart)
			         newWeld.Part0 = lightPart;
			         newWeld.Part1 = workspace[PlayerName].PrimaryPart
			         NewLight.Range,NewLight.Brightness,NewLight.Face = 16,1,"Front"
				end
				if Workspace:FindFirstChild(PlayerName) then
					local NewLight = Workspace:FindFirstChild(PlayerName.." Light").Light.SurfaceLight
					if ColorString ~= nil then
						local Color = string.split(ColorString,",")
						local R,G,B = Color[1],Color[2],Color[3]
						if (R and G and B) then
							NewLight.Color = Color3.fromRGB(R,G,B)
						elseif ColorString == BrickColor.new(ColorString) then
							NewLight.Color = BrickColor.new(ColorString)
						else
							error("Nothing to support the lighting color")
						end
					end
				end
			end
		end}
	;

Let me know if this has any issues.

1 Like

This works perfectly! Could you explain what it was I was doing wrong? I’m still semi unsure as to what exactly went wrong.

I know that I was teleporting due to the weld constraint being added too soon… but what else was I missing?

Most of it came down to how you were updating the position of the light part. When you set the position of the light part in your initial script, you use Vector3 to do so. Vector3 represents a vector, or coordinate, in 3D space and doesn’t account for the orientation.

This actually sets the position of the light to the correct position - it just doesn’t account for the orientation, which is why it is not the position you wanted. CFrames fix this problem, as they consist of both position and orientation components. So if you wanted to ensure that a part would always be in front of the player no matter which direction they’re facing, you would utilize CFrames:

Part.CFrame = HumanoidRootPart.CFrame * CFrame.new(0, 0, -5) -- The part will be 5 studs in front of the player

I don’t know if that explained it well, I have a hard time explaining things in depth. :slight_smile:

1 Like

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