I’m working to create a gun/character system somewhat similar to ArmA 3.
Something important to note about ArmA 3 is how when you look down, your characters torso bends forward to point his weapon around.
I want to recreate this. How could I even go about with making my characters torso bend depending on the cameras look angle?
I should note that the system will be based on R15
You can use Motor6D to make this work.
You will need to work with C0 and C1 to make it work.
You can click the Motor6D above to read more on how it works.
With R15, the UpperTorso’s Waist joint will allow you to rotate the body around to your liking.
You can adjust the C0 to be able to rotate it around to the desired rotation.
But how?
Well, somehow we need to rotate the humanoid to the camera’s look vector Y position.
We will have to start off the code with a variable, which will function as the camera’s lookvector Y. local cameralookvectorY = workspace.CurrentCamera.CFrame.LookVector.Y
Now we have a variable which will show what our character wants to rotate to.
Now, we need to use math.asin to be able to find our desired radians. We can do this by creating a variable that represents math.asin(), with x being cameralookvectorY. This is what it should look like now. local cameralookvectorY = workspace.CurrentCamera.CFrame.LookVector.Y local radian = math.asin(cameralookvectorY)
Now that we have the radian, we are now able to rotate the waist. We can use CFrame.fromEulerAnglesYXZ() to rotate the waist, with rx being the radian. We will now also have another variable representing the C0 of the waist. This is an example of what it should look like in a localscript: local c0 = game.Players.LocalPlayer.Character:WaitForChild("UpperTorso"):WaitForChild("Waist").C0 function updatewaist() local cameralookvectorY = workspace.CurrentCamera.CFrame.lookVector.Y local radian = math.asin(cameralookvectorY) game.Players.LocalPlayer.Character.UpperTorso.Waist.C0 = c0*CFrame.fromEulerAnglesYXZ(radian,0,0) end
Hope I helped!
Transform is a property, not a function. Transform also does not replicate for performance reasons and it has to be set every frame due to overriding behaviour by anything that internally uses Transform (e.g. animations).
No, it wouldn’t, neither is updating the joints on the server in order to replicate to all clients. Great that this concern was made. Even in the thread above where the code was taken from, the author made an amendment to address the issue, however i’m not too fond of updating the joints on the server, since the server has to update the joint itself and then replicate the changes to all of the clients.
The server should just be for validation/verification of data, while all of the clients are just in charge of visuals. The idea is to have the client firing the remote every few seconds (like 0.1 seconds) if there’s a charge in the angle and have the server fire the event to all of the clients to interpolate to the desired angle. Here’s some code:
-- server
RemoteEvent.OnServerEvent:Connect(function(player, angle)
RemoteEvent:FireAllClients(player, angle)
end)
-- client
RemoteEvent.OnClientEvent:Connect(function(player, angle)
local character = player.Character
if character then
local neck = character.Head.Neck
local waist = character.UpperTorso.Waist
neck.C0 = neck.C0:lerp(neckC0 * CFrame.fromEulerAnglesYXZ(angle, 0, 0), 0.05)
waist.C0 = waist.C0:lerp(waistC0 * CFrame.fromEulerAnglesYXZ(angle, 0, 0), 0.05)
end
end)
local last = nil
while true do
local current_angle = math.asin(cam.CFrame.LookVector.Y)
if not last or math.abs(current_angle - last) > 0.005 then
RemoteEvent:FireServer(current_angle)
last = current_angle
end
task.wait(0.1)
end