Controlling Local Character Body Parts via Script?

I’m making a third-person shooter game.
When a player aims a weapon I want the arms to adjust so that the weapon faces the direction the player is aiming at.

The code for this system is functional but I have run into 2 issues that I don’t know how to deal with.
1: Arms Position does not replicate between clients
2: Animations Mess with arm position

I position the arms by doing the following

Plane, ShoulderAngle, ElbowAngle = solveArm(RShoulderCF, TargetPosition, UpperArmLength, LowerArmLength)
	RShoulder.C0 = UpperTorso.CFrame:toObjectSpace(Plane) * CFrame.Angles(ShoulderAngle, 0, 0)
	RElbow.C0 = RElbowInit * CFrame.Angles(ElbowAngle, 0, 0)
	
	Plane, ShoulderAngle, ElbowAngle = solveArm(LShoulderCF,TargetPosition,UpperArmLength,LowerArmLength)
	LShoulder.C0 = UpperTorso.CFrame:toObjectSpace(Plane) * CFrame.Angles(ShoulderAngle, 0, 0)
	LElbow.C0 = LElbowInit * CFrame.Angles(ElbowAngle, 0, 0)

What’s the best way to achieve what I’m aiming for?

I’ve been struggling with the same issue.

I have actually done this in multiple games, “Realism” and “Open Source FPS” (both are not done yet), so here’s the most reliable solution:

So, I just removed the animation and made it “stable”, as in not making the parts I don’t want, don’t move.

But in your case, I bet you want that so:
I subtracted velocity from the hand, and added a relative CFrame from the Head/Torso to get my CFrame I want. It seems very hacky, but if you get it right it will become quite smooth.

I didn’t bother with replicating to other clients because it just isn’t necessary. If you want, here’s another solution to the animations:

You can use Animator:GetPlayingAnimationTracks() to get the current animation tracks. You can also detect if these tracks should override the arm movement, so you can stop the arm movement when necessary. This is also a hacky solution, but I haven’t found much luck with this.

1 Like

The current solution I’m working on implementing does the following.
I will create an object inside every character that indicates what the current C0 of the arms are and make clients update it on their end so the other clients don’t have to handle the calculations. Regarding the animations, I will update all existing animations including Roblox ones, and replace them with ones that don’t mess with the arms aka stable ones.

I like the idea, but not letting the clients do the calculations is way worse, since the Roblox servers are garbage. I would make the clients do all the calculations if I could!

The above is incorrect. Roblox has their own server, the other clients don’t handle the server. Roblox isn’t that advanced yet.

To indicate the current C0 of the arms, just look at the Weld’s C0. But what I would logically do is find the actual CFrame of the arm and subtract the inconsistencies from the predicted target position.

Anyways, I think you got it figured out, except for that minor misunderstanding of Roblox’s servers. I hope the game comes together well!

Yes, I totally forgot the value won’t replicate and I would have to use a remote or something. Firing a remote multiple times a second is at least sub-par optimal so that ruins everything. I also use the third-person camera CFrame to determine where the arms should be. I don’t know how I would manage to make the other clients do the calcs without having access to the camera CFrame.

You don’t.

Well, you don’t have to use a remote, replication is optional, if you have the weapon on the client, too. I would only replicate some particles and damage.

I’m not sure if this really matters, unless you’re using something from the Camera, like Camera.Focus or Camera.CFrame.

Firing a remote every split-second does ruin everything, so hold back on the replication for now!

1 Like

You can actually fire a lot more remotes than you think without horrible performance loss.

Firing remotes in a Heartbeat (30 times per second) is actually not a problem, but if you’re worried about performance you could fire it only a few times a second.

You wouldn’t, you’d send a remote to the server with all the calculations already done, and all you need to do is set the CFrames on the server, probably with a bit of lerping if you’re not going to be firing the remote super often.

Agreed. I did that once with the old and broken classic Paintball Gun.

Which is what I wouldn’t do for a gun, but in this case I would use it for a car.

He’s editing the CFrame of the characters Motor6D’s in the arms, so it should be fine here.

I know, but I wouldn’t necessarily replicate that since it’s unnecessary (unless it was the core aspect of the game, like in those poorly designed web shooter games where you don’t hear footsteps and your only way of knowing someone is looking at you is through where they’re pointing)

Its just something you’d want, not just because you see players moving their arms, but also bullets would go in completely different directions then the gun is holding. Its really not a performance problem to send remotes like this.

1 Like

It would have to be updated every frame to not look choppy.
I’m not sure if it would be absolutely horrible for performance but I’m taking into account the already existing remotes that are fired every second on top of that as well.
What I’m currently doing is that I’m updating the C0 of the localplayer’s arms in detail and using a base C0 that does not update for the other players in the game when they are aiming.
I’m aware of the firing inconsistencies caused by it not replicating on the server but I’m not sure if it will be an issue since all the effects are handled client-side.

That’s why you use :Lerp() on the CFrames to make them smooth.

It probably will, the bullet needs to go in same direction for everyone, so no matter where the gun is aiming its shooting where the player shot. If they fire directly up, the gun would face forward but the bullet would go up, which would look terrible.

I fixed this issue by using the client-side position of the gun for handling the bullet casting. (Has sanity logic)
It is really hard to notice the difference from the server perspective.

I’m sure Lerping would help but I’m not sure it would make it as smooth as I would Ideally want.