I’m currently working on an FPS game, and for the server sided visuals, I didn’t want to have to reanimate a bunch of viewmodel animations for the actual character, so I came up with a system that effectively creates a clone of the client’s viewmodel via serialization and remote events. It works great, it covers animations without me having to do any extra work, but I’m having trouble with making the viewmodel rotate up and down around a part that I have set in the character to be around shoulder height.
Current behavior:
https://streamable.com/8is2em
Current script (for context, sv is the part in the character that the viewmodel gets positioned to and rotated to on the z axis only, and rot is the part in the character at shoulder height I want the viewmodel to rotate up and down around):
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SerialBit = require(ReplicatedStorage:WaitForChild("SerialBit"))
local event = ReplicatedStorage:WaitForChild("ViewmodelUpdate")
event.OnServerEvent:Connect(function(player, serializedData)
local char = player.Character
if not char then return end
if game.Workspace:FindFirstChild("ServerArms".. player.Name) then
game.Workspace:FindFirstChild("ServerArms".. player.Name):Destroy()
end
local deserializedArms : Model = SerialBit.reconstruct(serializedData)[1]
deserializedArms.Name = "ServerArms".. player.Name
deserializedArms.Parent = workspace
deserializedArms.VMArms["Left Arm"].Transparency = 1
deserializedArms.VMArms["Right Arm"].Transparency = 1
deserializedArms["Left Arm"].Transparency = 0
deserializedArms["Right Arm"].Transparency = 0
deserializedArms:MoveTo(char.sv.Position)
local currentCFrame = deserializedArms.PrimaryPart.CFrame
local _, _, currentZ = currentCFrame:ToEulerAnglesXYZ()
local _, _, svZ = char.sv.CFrame:ToEulerAnglesXYZ()
deserializedArms.PrimaryPart.CFrame = CFrame.new(currentCFrame.Position) * CFrame.Angles(0, 0, svZ)
deserializedArms:ScaleTo(0.8)
for _, limbName in pairs({"Left Arm", "Right Arm"}) do
local limb = char:FindFirstChild(limbName)
if limb and limb:IsA("BasePart") then
limb.Transparency = 1
limb.CanCollide = false
end
end
end)