Help with CFrames

So, I am currently trying to do something that shouldnt be to difficult, Im just really bad with CFrames and dont know what Im doing :sob:


Basically what I want to do is set the C0 property of a Motor6D to a CFrame.Angles that is rotated around a different point, in this case, the position of the Camera.

Problem with that, I have no idea how to do that :sob:

Right now all I have is the CFrame.Angles, but Im not sure how to make it rotated around the Motor6d. So any help with this would be greatly appreciated :D

1 Like

You can rotate around a point (like the camera’s position) by offsetting the CFrame like this:

local pivot = camera.CFrame.Position
local rotation = CFrame.Angles(math.rad(x), math.rad(y), math.rad(z))

local offset = (CFrame.new(pivot) * rotation * CFrame.new(-pivot))
motor6D.C0 = offset

But since Motor6D.C0 is relative to the part it’s attached to, you might want to multiply it with its original C0:
motor6D.C0 = originalC0 * offset

Let me know what exactly you’re rotating and I can try to help you make it more specific.

1 Like

Ok, so, I changed it up a bit, and instead of the Cameras position, I just started using the Characters Heads position, but I still got the same result.


It was sorta rotating around the point, except the higher up you looked, the further up the tool would go.

For context, Im trying to make a viewmodel for weapon rotate around a designated point, and face the direction the camera is facing (with some changes to make it more customizable)


This is my current code:

RunService.RenderStepped:Connect(function(DeltaTime)
	
	-- // Camera //
	local LookingUp = Camera.CFrame.LookVector.Unit:Dot(Vector3.new(0,1,0))
	
	
	-- // Move Tool
	if Tool then
		if CameraModule:IsFirstPerson() then
			local Rotation = CFrame.Angles(math.rad(90 * LookingUp),0,0)
			local Pivot = Character:FindFirstChild("Head").Position
			local Offset = (CFrame.new(Pivot) * Rotation * CFrame.new(-Pivot))
			
			ToolConnect.C0 = Offset
		else
			ToolConnect.C0 = CFrame.Angles(math.rad(90 * LookingUp),0,0) * CFrame.new(0,0.5,0)
		end
	end
end)

PS, Assuming what you meant by originalC0, I shoudlnt have to multiply it, as the value C0 is at by default is basically just CFrame.new(0,0,0), as it has no position nor rotation

Yeah, that happens because you’re rotating around a world position (Pivot), then applying that directly to the Motor6D’s C0, which is in object space. So when you look up, that world-space offset gets misaligned.

Since this is for a viewmodel, you don’t need to rotate around the head’s world position at all. You should rotate relative to the camera, since viewmodels are usually locked to the camera anyway.

Try this:

RunService.RenderStepped:Connect(function(DeltaTime)
	if Tool and CameraModule:IsFirstPerson() then
		local camCF = Camera.CFrame
		local rotation = CFrame.Angles(math.rad(90 * Camera.CFrame.LookVector:Dot(Vector3.new(0,1,0))), 0, 0)
		ToolConnect.C0 = camCF:ToObjectSpace(camCF * rotation)
	else
		ToolConnect.C0 = CFrame.Angles(math.rad(90 * Camera.CFrame.LookVector:Dot(Vector3.new(0,1,0))), 0, 0) * CFrame.new(0, 0.5, 0)
	end
end)

I think this should work. This way you’re applying the rotation in camera space, which avoids all that position drift. You can adjust the rotation math or add CFrame.new() offsets if you want to customize the sway or positioning.

1 Like

Im not sure if I did something wrong, but it still isnt exactly rotating around the cameras position.

It currently feels like its being rotated around the torso (which is what the Part0 of the Motor is), thus causing it to feel odd. As when you look down it seems completely fine, the viewmodel is in front of the camera, but if you look up, or forwards, not so much.

So I tried this:

-- || 
RunService.RenderStepped:Connect(function(DeltaTime)
	
	-- // Camera //
	local LookingUp = Camera.CFrame.LookVector.Unit:Dot(Vector3.new(0,1,0))
	
	-- // Move Tool
	if Tool then
		if CameraModule:IsFirstPerson() then
			print('First Person')
			local rotation = CFrame.Angles(math.rad(90 * LookingUp), 0, 0)
			ToolConnect.C0 = Camera.CFrame:ToObjectSpace(Camera.CFrame * rotation)
		else
			ToolConnect.C0 = CFrame.Angles(math.rad(90 * LookingUp),0,0) * CFrame.new(0,0.5,0)
		end
	end
end)

Please tell me if Im doing something wrong, cause I feel like I probably am lol

Yeah, the problem is you’re rotating in camera space but applying it to a Motor6D that’s still relative to the torso. Just skip the Motor6D and set the viewmodel’s CFrame directly:
viewmodel:SetPrimaryPartCFrame(Camera.CFrame * CFrame.new(0, -1, -2) * rotation)

In that case, how can I animate said tools? I was originally basing this off of a tutorial that Ive been using for the last year involving motor6ds so you can just use the roblox animator to animate (cause I just cant animate anywhere else lol).

I was considering doing this, but I dont know how I’d go about having animations in that case.

Yeah if you want to use the Animator and keyframe animations, then yeah you’ll need Motor6Ds. In that case, you can still use a rig with Motor6Ds and just update the root part’s CFrame manually:

viewmodel.HumanoidRootPart.CFrame = Camera.CFrame * CFrame.new(0, -1, -2)

Let the animations handle the rest. Just don’t mess with the Motor6D C0s at runtime unless you’re doing procedural stuff.

2 Likes

Ohh I didnt think about that.

So I take it by this you mean for the viewmodel I have I should make another rig that holds the tool and do the animations on that rig?

That would explain how people get the shirt of the player on a viewmodels arms.

Thanks! I will now go and do this lol. Ill probably set this as the solution later, I just gotta test some stuff out first.

Yeah, that’s the setup. Use a rig with Motor6Ds for animation, then move the root part to follow the camera. No need to touch C0 every frame. Clean and it works.

No worries. Hopefully this got you on the right track.

Off-topic but I would assign LookingUp like so:

RunService.RenderStepped:Connect(function(DeltaTime)
	
	-- // Camera //
	local LookingUp = Camera.CFrame:ToOrientation()
	
	
	-- // Move Tool
	if Tool then
		if CameraModule:IsFirstPerson() then
			local Rotation = CFrame.Angles(math.rad(LookingUp),0,0)
			local Pivot = Character:FindFirstChild("Head").Position
			local Offset = (CFrame.new(Pivot) * Rotation * CFrame.new(-Pivot))
			
			ToolConnect.C0 = Offset
		else
			ToolConnect.C0 = CFrame.Angles(math.rad(LookingUp),0,0) * CFrame.new(0,0.5,0)
		end
	end
end)

For your original question. As far as I understand it, you want something like:


Correct? For this, you can set the C0 to:

local CFrame = Torso.CFrame:ToObjectSpace(Camera.CFrame) * C0Offset
1 Like

from personal experience,
it is really not worth it trying to animate via code

believe me, animating is really simple, whether it’s blender or moon animator (i don’t use the roblox animator)

yeah, i didn’t contribute much to helping, but seriously animating is NOT that difficult
i can go through the basics with you (in blender cause i use blender) if it helps

1 Like

Ok so Ive been working on it for a bit, and I was curious how I would go about replicating the viewmodel to other clients so they can see the animations and not.

I take it I probably just create the viewmodel on the server, give the client NetworkOwnership of it, and then move it around and such.

But I was curious if there are other methods that are more optimized or something. I’ve never done this before so any advice would be nice :D

Dont worry, all my animations are just animations I make via the roblox animator, I have no idea how to animate with code and I dont plan to find out for a while lol

Glad to hear you’re getting it sorted! For replicating the viewmodel, you’re mostly on the right track, but a few things to keep in mind.

Viewmodels are usually client-only for performance and privacy reasons. Other players don’t actually need to see your viewmodel; they see the actual character rig and tools, which get replicated automatically by default. If your goal is just first-person visuals, keep it local.

But if you do want others to see specific animated props or effects (like a reloading animation or something synced), then yeah, you’d spawn the viewmodel from the server, give the client NetworkOwnership, and sync animations through remote events or AnimationControllers.

Just don’t move the whole viewmodel through replicated CFrames every frame, that gets expensive fast. Use events to trigger animations or state changes, and let the local client handle visual updates.

1 Like

As of now how I move the viewmodel is yes, just setting the CFrame every frame, you said it gets pretty costly if I were to make that replicate to other clients correct? In that case, how would I go about updating the position and such?

Exactly. Updating the CFrame every frame and replicating it isn’t scalable. Roblox will throttle that hard. Instead, keep the viewmodel client-side for visuals, and if other players need to see something (like reloads), fire a RemoteEvent and play the animation locally on each client. Only sync what actually needs to be seen - never raw position every frame.

1 Like

By this did you mean not setting the CFrame of the objects in the viewmodel to match the viewmodels animations?

Cause what I meant by this was putting the viewmodel at a certain position.

If we are on the same page, how can I optimize the task I said above? As I’d like for other players to see which direction your viewmodel is facing that way it doesnt look like you’re always just looking straight ahead.

Any ideas?

Okay I see what you’re saying. You don’t need to replicate the whole viewmodel. Keep it local and just send the camera’s facing direction (like a vector or angle) to the server when it changes. Other clients can use that to rotate a simplified prop or marker. That way you’re not syncing CFrame every frame and just the direction when it matters.