How to rotate a bone during an animation?

I have a character with idle and walk animations. Now I want to rotate the upper body without stopping the animations. So only one bone should stop playing the animation. If I try to stop the animation with animation.Stop(); it tells me that this bone isn’t playing any animations. The line of script that is supposed to be rotating the bone looks like this: transform.Rotate(0, Input.GetAxis(“Mouse X”) * sensitivityX, 0);. It doesn’t give me any console errors. Please help or ask for further information on my problem.

I made a little script to perform manual IK during a sword swing, to hit a particular target. I performed transform rotation on the particular bone in LateUpdate() and this worked for me. Although, be advised, use of LateUpdate() should be kept to a minimum for performance reasons.

2 Answers

2

If the bone you want to not animate is at the top of a chain (suppose the lower spine,) you could try to “subtract” it with:

// path in Heirarchy to bone. Set in Start():
Transform upperSpine = transform.find("bones/lowerSpine/upperspine");

animation["Walk"].AddMixingTransform(upperSpine);
// repeat for hips

AddMixingTransform (see the docs) is a wierd one. The first one subtracts all but that bone and below. The second+ is supposed to add more bone chains (but I haven’t done that.)

You upperSpine should then be completely non-animated, and “adding” method you are using should work.

A more robust solution is to just play the animation and overwrite the bone’s transform. The problem is, even if the bone never moves, the animation is resetting to that position ever frame. Adding 1 degree/frame won’t work any more – rotation is always reset to 0. Felix’s LateUpdate comment is correct – animation is set in Update, bones are positioned by animation after Update quits (overridding bone rots you made in update,) and then LateUpdate has a crack at them. Try:

// instead of changing rotation, change my rotation var:
float spineSpin = 0;
spineSpin += Input.GetAxis("Mouse X") * sensitivityX;
lowerSpine.eulerAngles = new Vector3(0, spineSpin, 0);

// complete guess. Math to apply overall model tilt to the spine:
lowerSpine.rotation = transform.rotation * lowerSpine.rotation;

The math to combine rotations (Quaternions) uses the multiply symbol, just because. rotation1*rotation2 computes rotate #1, followed by #2 on local coords. So "adds" 2 to 1. The network stuff sounds like a data problem. In my limited experience, if you're sending the "user rotation" and having the client remember the old value (not somehow resetting each frame in the hopes of fresh data,) then it should be laggy, but otherwise look the same.

I'd think should post as a fresh Q emphasizing networking. But just looking: o recommending not to use things like Quat.Eulerangle.x= (but not real problem, just now.) o You client has no "old value" to go back to if it doesn't get a fresh packet that frame. Suppose animation says x=0, and your RPC xValue is constant at 30. If a packet is delayed past a frame, x won't get the extra rotation that frame, so will appear to "snap back" to 0. Make xValue a global. Still use that to set rotation, but have the RPC only copy into xValue. Now, when you lose a frame, you have the "old" xValue.

i know this is old but i am in need of help my camera is not in the skeleton it is following a cube inside of the skeleton how do i get the spine to rotate along with the camera

You should perhaps submit a fresh question.

I tried to convert it to C# but i get stuck at the [RPC] where you wrote the last line.. i get an error.. I know why but I just dont know how to fix it. Please Help!!

You have to rotate the bone every frame. You cannot stop the animation for a single bone (as long as I know); the animation will rotate the bone every frame to the animated value, so you have to rotate the bone every single frame (possibly in LateUpdate, so it happens after the animation updates your bone rotation).

Late update did the trick to those wondering.

thanks LateUpdate workes indeed.