Search Unity

Blend animation and recalculate some bones' rotation?

Discussion in 'Animation' started by teighshiclbw, May 11, 2019.

  1. teighshiclbw

    teighshiclbw

    Joined:
    Jun 26, 2018
    Posts:
    34
    Character has a idle animation and a shoot animation and some run animations.

    Animator has 2 layer, Base is for moving, Shoot is for shooting.
    Shoot layer has a upper body mask because shoot animation is for upper body.

    When character stand and shoot, looks fine.



    But when character run and shoot, gun strange rotate down.

    Shoot animation is made for idle animation, not for run animation.
    Notice upper body(3 spine bones), idle animation and run animation are different at this part.
    Because two arms are spine's child, so when spine rotate, two arms have to rotate.
    Different spine rotation will affect arms' blend result.
    Because idle animation and run animation have different spines rotation, when blend run animation and shoot animation, strange things happen, in this case, gun rotate down instead of rotate up.

    Then I got a idea, fix two arms' rotation.
    1. Set animator parameter to make character back to idle state
    2. Animator.Update()
    3. Record two arms' rotation
    4. Set animator parameter to make character restore to run state
    5. Animator.Update()
    6. Rewrite two arms rotation using recorded two arms' data
    And here's result

    This is the result I want.
    But the problem is that animator need to update 2 times, which lead to a seriously performance problem.

    Is there any way to reduce computation and increase performance base on my method?
    Or is there any other method to get the result I want?

    Thanks in advance!
    Project(Unity 5.6.5f1):
    http://www.mediafire.com/file/7tiazd8s5bd499s/RunShootProblem%282%29.rar/file

    Code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerBehaviour : MonoBehaviour
    6. {
    7.     public bool EnableBoneFix;
    8.  
    9.     Animator animator;
    10.  
    11.     Transform leftShoulder;
    12.     Transform leftUpperArm;
    13.     Transform leftLowerArm;
    14.     Transform leftHand;
    15.     Transform rightShoulder;
    16.     Transform rightUpperArm;
    17.     Transform rightLowerArm;
    18.     Transform rightHand;
    19.  
    20.     void Start()
    21.     {
    22.         animator = GetComponent<Animator>();
    23.  
    24.         leftShoulder = animator.GetBoneTransform(HumanBodyBones.LeftShoulder);
    25.         leftUpperArm = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
    26.         leftLowerArm = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
    27.         leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand);
    28.         rightShoulder = animator.GetBoneTransform(HumanBodyBones.RightShoulder);
    29.         rightUpperArm = animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
    30.         rightLowerArm = animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
    31.         rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
    32.     }
    33.    
    34.     void Update()
    35.     {
    36.         animator.SetFloat("hor", Input.GetAxis("Horizontal"));
    37.         animator.SetFloat("ver", Input.GetAxis("Vertical"));
    38.        
    39.         if (Input.GetButtonDown("Fire1"))
    40.             animator.SetTrigger("Shoot");
    41.     }
    42.  
    43.     void LateUpdate()
    44.     {
    45.         if (EnableBoneFix)
    46.         {
    47.             //Restore to idle state
    48.             float hor = animator.GetFloat("hor");
    49.             float ver = animator.GetFloat("ver");
    50.             animator.SetFloat("hor", 0);
    51.             animator.SetFloat("ver", 0);
    52.             animator.Update(0);
    53.  
    54.             //Record two arms' rotation
    55.             Quaternion idleLeftShoulderRotation = leftShoulder.rotation;
    56.             Quaternion idleLeftUpperArmRotation = leftUpperArm.rotation;
    57.             Quaternion idleLeftLowerArmRotation = leftLowerArm.rotation;
    58.             Quaternion idleLeftHandRotation = leftHand.rotation;
    59.             Quaternion idleRightShoulderRotation = rightShoulder.rotation;
    60.             Quaternion idleRightUpperArmRotation = rightUpperArm.rotation;
    61.             Quaternion idleRightLowerArmRotation = rightLowerArm.rotation;
    62.             Quaternion idleRightHandRotation = rightHand.rotation;
    63.  
    64.             //Restore back to run state
    65.             animator.SetFloat("hor", hor);
    66.             animator.SetFloat("ver", ver);
    67.             animator.Update(0);
    68.  
    69.             //Make two arms acts like idle state
    70.             leftShoulder.rotation = idleLeftShoulderRotation;
    71.             leftUpperArm.rotation = idleLeftUpperArmRotation;
    72.             leftLowerArm.rotation = idleLeftLowerArmRotation;
    73.             leftHand.rotation = idleLeftHandRotation;
    74.             rightShoulder.rotation = idleRightShoulderRotation;
    75.             rightUpperArm.rotation = idleRightUpperArmRotation;
    76.             rightLowerArm.rotation = idleRightLowerArmRotation;
    77.             rightHand.rotation = idleRightHandRotation;
    78.         }
    79.     }
    80. }
    81.  
     
    wildWind likes this.
  2. wildWind

    wildWind

    Joined:
    Jan 18, 2016
    Posts:
    5
    have you got any ideas?
     
  3. JackPotato

    JackPotato

    Joined:
    Jul 16, 2018
    Posts:
    7
    Anyone figure this out? I think it may have something to do with the base layer affecting the initial rotation of the bones and therefore the layered animation but not sure how to get around this