My idea is to rotate the waist and when the waist has rotated 65 degrees, move the legs to the orientation of the waist. I have managed to program it in a Local Script, but I have not managed to replicate it yet because when sending the position of the player it goes with much delay and is very buggy, this is the code that I have programmed so far.
(Only client side)
1.gif (708×378) (ibb.co)
(Server Replication) Here, the problem is that player position is not being updated when the torso moves and its very laggy.
2.gif (690×388) (ibb.co)
I would appreciate a little help!
LocalScript (Character Scripts)
--> Services and declaring variables.
local TweenService = game:GetService('TweenService')
local RunService = game:GetService('RunService')
local Players = game:GetService('Players')
local Context = game:GetService('ContextActionService')
local Replicated = game:GetService('ReplicatedStorage')
local MovementControllerEvent = Replicated:WaitForChild('MovementControllerEvent')
local Player = Players.LocalPlayer
local WorkspaceCamera = workspace.CurrentCamera
local Character = Player.Character or Player.CharacterAdded:Wait()
--> Humanoid Parts.
local Humanoid = Character:WaitForChild('Humanoid')
local RootPart = Character.PrimaryPart
local UpperTorso = Character:WaitForChild('UpperTorso')
local WaistJoint = UpperTorso:WaitForChild('Waist')
--> Player Variables.
local CurrentSpeed = nil
local MaxRotation = math.rad(65)
local WaistC1 = WaistJoint.C1;
--> Tween Service Variables
local AdjustRoot = nil
local AdjustWaist = nil
local AdjustLimbs = nil
Humanoid.Running:Connect(function(HumanoidSpeed)
CurrentSpeed = HumanoidSpeed
end)
Humanoid.AutoRotate = false
RunService:BindToRenderStep("InmersiveCameraController", 400, function()
local TargetPos = (WorkspaceCamera.CFrame * CFrame.new(0,0,-1000)).p
local TorsoFront = RootPart.CFrame.LookVector
local TorsoRight = RootPart.CFrame.RightVector
local VectorToTarget = (TargetPos - RootPart.Position)
local FixedRotation = math.atan2(TorsoRight:Dot(VectorToTarget), TorsoFront:Dot(VectorToTarget))
local Theta = math.asin(WorkspaceCamera.CFrame.LookVector.y)
if (FixedRotation < - MaxRotation) then
FixedRotation = - MaxRotation
elseif (FixedRotation > MaxRotation) then
FixedRotation = MaxRotation
end
local PlayerRotation = nil
local WaistCF = CFrame.Angles(0, FixedRotation, 0) * WaistC1
if (CurrentSpeed > 0.5) then
WaistCF = CFrame.Angles(0, 0, 0) * WaistC1
if (AdjustRoot and AdjustRoot.PlaybackState == Enum.PlaybackState.Playing) then
AdjustRoot:Cancel()
end
if (AdjustLimbs and AdjustLimbs.PlaybackState == Enum.PlaybackState.Playing) then
AdjustLimbs:Cancel()
end
AdjustRoot = TweenService:Create(RootPart, TweenInfo.new(0.33), {
CFrame = CFrame.new(RootPart.Position, Vector3.new(TargetPos.X, RootPart.Position.Y, TargetPos.Z))
})
AdjustRoot:Play(); --> Start tween to keep it updated
elseif (math.abs(FixedRotation) == MaxRotation and CurrentSpeed <= 0.5) then
PlayerRotation = UpperTorso.CFrame.Rotation
AdjustLimbs = TweenService:Create(RootPart, TweenInfo.new(0.33), {
CFrame = CFrame.new(RootPart.Position) * PlayerRotation
})
AdjustLimbs:Play(); --> Start tween to keep it updated
end
if (AdjustWaist and AdjustWaist.PlaybackState == Enum.PlaybackState.Playing) then
AdjustWaist:Cancel()
end
AdjustWaist = TweenService:Create(WaistJoint, TweenInfo.new(0.33), {
C1 = WaistCF
})
AdjustWaist:Play(); --> Start tween to keep it updated
if (AdjustLimbs and AdjustLimbs.PlaybackState == Enum.PlaybackState.Playing) then
AdjustLimbs:Cancel()
AdjustLimbs = TweenService:Create(RootPart, TweenInfo.new(0.33), {
CFrame = CFrame.new(RootPart.Position) * PlayerRotation
})
AdjustLimbs:Play(); --> Start tween to keep it updated
end
MovementControllerEvent:FireServer(PlayerRotation, WaistCF)
end)
Handler (Player Scripts)
--> Services and declaring variables.
local TweenService = game:GetService('TweenService')
local RunService = game:GetService('RunService')
local Players = game:GetService('Players')
local Player = Players.LocalPlayer
local Replicated = game:GetService('ReplicatedStorage')
local MovementControllerEvent = Replicated:WaitForChild('MovementControllerEvent')
MovementControllerEvent.OnClientEvent:Connect(function(Sender, AdjustLimbsCF, WaistCF)
local Character = Sender.Character
if not Character then
return
end
local RootPart = Character.PrimaryPart
local UpperTorso = Character:WaitForChild('UpperTorso')
local WaistJoint = UpperTorso.Waist
if (AdjustLimbsCF ~= nil) then
local AdjustLimbs = TweenService:Create(RootPart, TweenInfo.new(0.33), {
CFrame = CFrame.new(RootPart.Position) * AdjustLimbsCF
})
AdjustLimbs:Play(); --> Start tween to keep it updated
end
local AdjustWaist = TweenService:Create(WaistJoint, TweenInfo.new(0.33), {
C1 = WaistCF
})
AdjustWaist:Play(); --> Start tween to keep it updated
end)
Server
local Players = game:GetService('Players')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local MovementControllerEvent = ReplicatedStorage:WaitForChild('MovementControllerEvent')
MovementControllerEvent.OnServerEvent:Connect(function(Sender, AdjustLimbsCF, WaistCF)
--MovementControllerEvent:FireAllClients(Sender.Name, AdjustLimbsCF, WaistCF)
for _, Player in pairs(Players:GetChildren()) do
if (Player ~= Sender) then
MovementControllerEvent:FireClient(Player, Sender, AdjustLimbsCF, WaistCF)
end
end
end)
Here is the place if you want to test what I wrote, thank for reading!
Torso rotation.rbxl (56.8 KB)