Position cannot be assigned to

So I was trying to set the position of a CFrame when I got the error:

Position cannot be assigned to 

So, uh why does this happen?

	local targetPo:Vector3 = mouse.Hit.Position
	local targetCFrame = CFrame.new(root.Position,targetPo)
	
	-- || Changes ||
	targetCFrame.Position = Vector3.new(1,1,1) -- errors here

CFrames are immutable data types, you need to reconstruct the CFrame using the position you want

	local targetPo:Vector3 = mouse.Hit.Position
	local targetCFrame = CFrame.new(root.Position,targetPo)
	
	-- || Changes ||
	targetCFrame = CFrame.new(1, 1, 1) * targetCFrame.Rotation

This is what I would do instead:

local targetPo:Vector3 = mouse.Hit.Position
	local targetCFrame = CFrame.lookAt(root.Position,targetPo) -- Same as CFrame.new with second parameter, but just makes easier to understand
	
	-- || Changes ||
	-- Now you just have to alter
	targetCFrame *= CFrame.new(1,1,1)

This just makes easier to work with.

1 Like

on the subject of CFrames, I am making something point towards well, the mouse, but if its parent is rotated, the thing has a bit of offset and doesnt exactly point to the mouse, cause again, its parent is rotated, how can I fix that?

Can you show your setup? I don’t think parts parented to other parts should have an offset

The reason is due to me using a motor6D I assume, cause I am setting the C0 property of the motor6D to the CFrame so yeah.

Also I feel like this is really dumb, but how the heck do I remove the Z value from my CFrame? I did this:

local finishedCFrame = CFrame.new(0,0,0) * CFrame.Angles(math.rad(maxedX),ry,0)

but for whatever reason its not being set to 0, all the other things work, just not that so Idk whats going on there. Anyhow heres my full code:

characterConnections['Heartbeat'] = RunService.Heartbeat:Connect(function()
	
	-- // Point Character //
	local targetPo:Vector3 = mouse.Hit.Position
	local targetCFrame = CFrame.lookAt(root.Position,targetPo)
	
	-- || Changes ||
	local rx,ry,rz = targetCFrame.Rotation:ToOrientation()
	
	local maxedX = math.max(math.min(math.deg(rx),25),-25)
	
	
	--targetCFrame *= CFrame.Angles(maxedX,math.rad(0),math.rad(0)) --  Ignore this
	local finishedCFrame = CFrame.new(0,0,0) * CFrame.Angles(math.rad(maxedX),ry,math.rad(0))
	
	print(finishedCFrame.Rotation)
	
	ViewmodelMotor.C0 = finishedCFrame
end)

If I’m understanding correctly, couldn’t you just inverse whichever orientation the part0 has (assuming you’re trying to get part1 axis aligned)?

local weld = script.Parent

game:GetService('RunService').Heartbeat:Connect(function()
	weld.C0 = CFrame.new(weld.C0.Position) * weld.Part0.CFrame:Inverse().Rotation
end)

This gives me the following, the rotating part is Part0, the one that isn’t rotating is Part1:

Medal_jsyjphJZQZ

I believe this is due to the order in which rotation is applied. Roblox’s “Orientation” is applied in YXZ order whereas CFrame.Angles is applied in XYZ order. Switch CFrame.Angles to CFrame.fromOrientation or equivalent, this should give you what you’re looking for

Ok works pretty well except only when facing forwards, as I am using math.min and math.max to limit the direction that the character can rotate, therefore messing it up when you face left or right, same with backwards:

So uh how can I go about fixing this one?

characterConnections['Heartbeat'] = RunService.Heartbeat:Connect(function()
	
	-- // Point Character //
	local targetPo:Vector3 = mouse.Hit.Position
	local targetCFrame = CFrame.lookAt(root.Position,targetPo)
	
	-- || Changes ||
	local rx,ry,rz = targetCFrame.Rotation:ToOrientation()
	
	local maxedX = math.max(math.min(math.deg(rx),25),-25)
	
	--targetCFrame *= CFrame.Angles(maxedX,math.rad(0),math.rad(0))
	local finishedCFrame = CFrame.new(0,0,0) * CFrame.Angles(math.rad(maxedX),ry,math.rad(0))
	local test = CFrame.new(0,-0.5,0) * ViewmodelMotor.Part0.CFrame:Inverse().Rotation
	
	ViewmodelMotor.C0 = test * finishedCFrame
end)

my guess is that I’d have to take finishedCFrame and rotate it by some other CFrame so idk

I see, I think what you’d want is to do is just use the targetCFrame for your orientation, then convert it to object space relative to the HumanoidRootPart’s CFrame. On the backend ToObjectSpace uses inverses but it’s easier to read. Also for R6 specifically, there is a C1 applied, we can remove that, and it should give you your intended result

local localPlayer = game:GetService('Players').LocalPlayer
local mouse = localPlayer:GetMouse()

local character = script.Parent
local torso = character:WaitForChild('Torso')
local rootPart = character:WaitForChild('HumanoidRootPart')
local root = rootPart:WaitForChild('RootJoint')

local MAX_ROTATION = math.rad(25)

game:GetService('RunService').Heartbeat:Connect(function()
	local mouseHit = mouse.Hit
	local targetCFrame = CFrame.lookAt(rootPart.Position, mouseHit.Position)
	
	local cframeRelative = rootPart.CFrame:ToObjectSpace(targetCFrame)
	
	local rX, rY, rZ = cframeRelative:ToOrientation()
	
	rX = math.clamp(rX, -MAX_ROTATION, MAX_ROTATION)
	
	root.C0 = CFrame.fromOrientation(rX, rY, 0) -- since c0 is part1 relative to part0
	root.C1 = CFrame.identity
end)

Ahh ok thanks! That works. I should probably go study so more CFrame stuff, thanks again!

1 Like

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