Script that points upper body to camera sometimes stops working

Hello, I am working on a system that points the head and upper body in the direction of the camera. Sometimes if you move the camera too fast the head and body stops and doesn’t follow the camera anymore. I have tried to solve it myself, but it does not work. Any help is needed, thanks for reading.
Here is my script:

        Script
    local neckC0 = CFrame.new(0, 0.8, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1);
    local waistC0 = CFrame.new(0, 0.2, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1);
    local TweenService = game:GetService("TweenService")
    local Time = 0

game.ReplicatedStorage.CameraUpdateEvent.OnServerEvent:Connect(function(player, ytheta, xtheta, aiming, Anglebetween, FM, LM, RM, BM)
	wait(0.001)
	local neck = player.Character.Head.Neck
	local waist = player.Character.UpperTorso.Waist
	local head = player.Character.Head
	local torso = player.Character.UpperTorso
	spawn(function()
		Time = Time + 1
		local Angle = -xtheta
		local LastAngle = xtheta
		if -xtheta > 48 then
			Angle = LastAngle
		else
			LastAngle = Angle
		end
--		print(Anglebetween)
		if aiming == false then
			local NeckCFrameTween = TweenService:Create(
				neck,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = neckC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, (-xtheta - 0.2), 0)}
			)
			NeckCFrameTween:Play()
			
			local WaistCFrameTween = TweenService:Create(
				waist,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = waistC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, -xtheta, 0)}
			)
			WaistCFrameTween:Play()
			WaistCFrameTween.Completed:Wait()
			NeckCFrameTween.Completed:Wait()
	
	--		neck.C0 = neckC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, (-xtheta - 0.2), 0)
	--		waist.C0 = waistC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, -xtheta, 0)
			
		elseif aiming == false then
			local NeckCFrameTween = TweenService:Create(
				neck,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = neckC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, (-xtheta - 0.2), 0)}
			)
			NeckCFrameTween:Play()
			
			local WaistCFrameTween = TweenService:Create(
				waist,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = waistC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, -xtheta, 0)}
			)
			WaistCFrameTween:Play()
			WaistCFrameTween.Completed:Wait()
			NeckCFrameTween.Completed:Wait()
			Time = 0
	--		neck.C0 = neckC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, (-xtheta - 0.2), 0)
	--		waist.C0 = waistC0 * CFrame.fromEulerAnglesYXZ(ytheta*0.5, -xtheta, 0)
	
	
		elseif aiming == true then
			local NeckCFrameTween = TweenService:Create(
				neck,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = neckC0}
			)
			local WaistCFrameTween = TweenService:Create(
				waist,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = waistC0}
			)
			NeckCFrameTween:Play()
			WaistCFrameTween:Play()
	
			WaistCFrameTween.Completed:Wait()
			NeckCFrameTween.Completed:Wait()
			print(Time)
			Time = 0
	end
		
	if Time <= 10 then
			print("HFKI")
	--		local NeckCFrameTween = TweenService:Create(
	--			neck,
	--			TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
	--			{C0 = neckC0}
	--		)
	--		local WaistCFrameTween = TweenService:Create(
	--			waist,
	--			TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
	--			{C0 = waistC0}
	--		)
	--		NeckCFrameTween:Play()
	--		WaistCFrameTween:Play()
	--		print("Hi, the Time is: "..Time)
	--		WaistCFrameTween.Completed:Wait()
	--		NeckCFrameTween.Completed:Wait()
	----		neck.C0 = neckC0
	----		waist.C0 = waistC0
		end
	end)
--	wait(1)
	Time = Time + 1
	print(Time)
	if Time <= 100000 then
		print("HI AND THE TIME IS: "..Time)
		if Time/100000 > 2 then
			print("AGEAIUHESJHNJKELNDSFKJAEGNAJEGNJDNGNKJWEGNDJLWENFLAK")
			local Angle3N = math.sin(neckC0.LookVector.Y/head.CFrame.LookVector.Y)
			local Angle3W = math.sin(waistC0.LookVector.Y/torso.CFrame.LookVector.Y)
			local NeckCFrameTween = TweenService:Create(
				neck,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = neckC0*CFrame.Angles(Angle3N, 0, 0)}
			)
			local WaistCFrameTween = TweenService:Create(
				waist,
				TweenInfo.new(0.1,Enum.EasingStyle.Linear,Enum.EasingDirection.In),
				{C0 = waistC0*CFrame.Angles(Angle3W, 0, 0)}
			)
			NeckCFrameTween:Play()
			WaistCFrameTween:Play()
			WaistCFrameTween.Completed:Wait()
			NeckCFrameTween.Completed:Wait()
			Time = 0
		end
		Time = 0
	end
end)

     Local script
local InputService = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local UpperTorso = Player.Character:WaitForChild("UpperTorso")
local Head = Player.Character:WaitForChild("Head")
local RE = game.ReplicatedStorage.CameraUpdateEvent
local Mouse = Player:GetMouse()
local LastAngle = 0
local LookVector
local Opposite
local Angle
local HeadLookVector
local Aiming = false
local ForwardMovement = false
local LeftMovement = false
local RightMovement = false
local BackMovement = false


InputService.InputBegan:Connect(function(key)
	if key.KeyCode == Enum.KeyCode.V then --You can change the Key/InputType with another Key/InputType of you choise
		Aiming = true
		print(key.KeyCode,Aiming)
	end
end)

InputService.InputEnded:Connect(function(key)
    if key.KeyCode == Enum.KeyCode.V then --You can change the Key/InputType  with another Key/InputType of you choise
		Aiming = false
		print(key.KeyCode,Aiming)
	elseif key.KeyCode == Enum.KeyCode.W then
		
	elseif key.KeyCode == Enum.KeyCode.W then
		
	elseif key.KeyCode == Enum.KeyCode.W then
		
	elseif key.KeyCode == Enum.KeyCode.W then
		
	end
end)

game:GetService("RunService").RenderStepped:Connect(function(delta)
    local Camera = workspace.CurrentCamera
    local Torso = Player.Character.UpperTorso
	local HeadLookVector = Player.Character.Head.CFrame.LookVector
	local lv = Camera.CFrame.LookVector
	local nv = Torso.CFrame.LookVector
	
	LookVector = Camera.CFrame.LookVector
	local Adjacent = math.sqrt((LookVector.X^2)+(LookVector.Z^2))
	Opposite = LookVector.Y
	Angle = math.atan2(Opposite, Adjacent)
	HeadLookVector = Head.CFrame.LookVector
    RE:FireServer(math.asin(LookVector.y), math.atan(LookVector.x, LookVector.z), Aiming, LookVector:Dot(HeadLookVector), ForwardMovement, LeftMovement, RightMovement, BackMovement)
--	RE:FireServer(math.asin(LookVector.y), Vector3.new(LookVector.x:Dot(LookVector.z)), Aiming)
end)

i believe the main problem is that tweens are being used, and the way tweens work is that they usually play until the animation is over. in a case like this, id recommend using the lerp function instead, that way, the cframes used in the joints will always interpolate to where theyre supposed to be, no matter how fast you move the camera; it does require a bit of extra scripting to give the interpolation other properties like the movement and movement direction, but its still better to use nonetheless.
i hope this information helps you for your system, and for the future.
side note: if lerping is not what you are looking for, then heres what you can do: write/find a module that allows for linear interpolation with cframes, allowing the joints to interpolate their cframes without it stopping or waiting for the animation to end. id highly recommend taking a look at the roblox wiki for cframe math operations, as it goes over the various different vectors and how you could modify them, which you could use to potentially create a system for the interpolation you need for this system.

2 Likes

Sorry if this has taken so long for a reply. No, this dont work.

So I have in my game, where I set the CFrame of the CurrentCamera, to a CFrame based on the HumanoidRootPart. It’s to have the camera face away from the teleporter once they arrive and in line with the character.

The reverse can be done too. Just align the X and the Z variables of the HumanoidRoot part to the CFrame of the camera. Keep everything else the same and wallah, Player always facing the same way as the camera.

local Cam = game.Workspace.CurrentCamera
local Root = Player.Character:WaitForChild("HumanoidRootPart")

local RRX, RRY, RRZ = Root.CFrame:ToOrientation( )

while wait(0.1) do
	local RX, RY, RZ = Cam.CFrame:ToOrientation( )
	Root.CFrame = CFrame.new(Root.CFrame.Position) * CFrame.fromOrientation(RX, RRY, RZ)
end

I think that will work.

1 Like

@Steve_Speedy I’m sorry if I answered so late, but I just can’t believe it was really that easy. Thank you. (How can I make the player not rotate 360 degrees now? It doesn’t look that realistic.)

Not sure what you mean. Really is should be instantaneous so 360 should not be seen. You can reduce the wait time to 0.01. Should be 10 times more accurate but it will use more processing power. Depends on how accurate you want it to be.

Maybe post like a video of it so we can see.

1 Like

@Steve_Speedy With your method I don’t have this problem anymore, but the player can rotate 360. Now let’s say I’m making an RPG game, and I want the player’s torso to move in the direction of the camera: then I want it to be realistic. In reality, we can’t rotate 360 around ourselves. Is there a way to solve this little problem? Otherwise you could tell in detail how you wrote this script? I still don’t understand. (P.S.: And yes, I looked it up on the Internet.)

@Steve_Speedy I changed your script so that the player can move from left and right, but then he turns around with 360. That’s what I mean.

It’s pretty full on. So I had an issue with my teleporter. When they were on a 45 degree angle, I would come out of the portal diagonally. Spent ages trying to work out how to fix it. Nothing anywhere had anything on it.

I was ended up aligning the torso to the teleporter CFrame but still had the problem because the camera didn’t rotate. So I had to work out how to turn the camera to face the right way. Looked up stuff about that and found out it had a CFrame.

So I set the Camera CFrame to the torso but it snapped to horizontal looking through the portal instead of looking down. I had everything sorted but then I had to work out what angle was wrong to have it snapping down.

So then I pulled the orientation RX,RY,RZ from the torso (HumanoidRootPart UpperTorso to be more precise) and the Camera, and I printed them out to see which one was different. It was the RY. So I stored the RY from the camera and took the RX and RZ from the torso. Using those I then constructed a brand new CFrame to align the Camera to. It used the position of the Torso and and then constructed the new Orientation from the RX and RZ of the torso and the RY of the Camera. Wallah, happy dance!!

So from what I can gather, your character spins too face. Like you can do super face 360s which is unrealistic. In this case, it’s probably better. I mean you can use a body gyro the that’s a whole new world of stuff to deal with.

Gyros have an issue too. So say you turn your camera so fast that it passes the 180 mark. It will then change direction and spin back the opposite way to get to the angle faster. So Clockwise, clockwise, clockwise, snap, Anticlockwise, yay lined up with the camera.

But that may actually be what you want.

It has some weird stuff though. I ditched it completely just because I couldn’t work it out properly. I don’t care if my NPCs instantly snap to face a direction. I don’t care about the realism that much.

Otherwise, are you just having the guy twist to face it without moving his legs, and then when it gets to like 45 degrees, the legs start to rotate with it?

If so, that’s getting complicated. Would have to orientate the lower torso to offset the turn of the root part. But only if the angle is less than 45. That’s doing my head in a bit.

As for moving left and right, so Strafing?

I think if you can SEE the 360 happen, a FULL circle, then it must be because you have something checking the angles and turning in increments. If so, What ever that is, that’s what will be reading the value and reacting to, sometimes causing the 360.

Not sure what that is though. My best guess is you have a gyro. If so… whole new kettle of fish.