• RuntimesUnity
  • Make weapon recoil

I've created a weapon recoil animation for arms and torso, on unity it is on track 4 and i set the mixblend to add

The problem is that when the animation is over, the character stays with it's torso rotated back, i've tried cleaning the track animation and copying the track 0's animation, as the animation is complete, but nothing works, what should i do on the script or on spine editor?

  • Misaki ответили на это сообщение.
    Related Discussions
    ...

    gumegasonic If you are using ClearTrack(), it rather leaves the pose as it was when that method was called.
    To mix out the current animation to the setup pose, use SetEmptyAnimation() or AddEmptyAnimation() as described in the following section of the Runtime Guide: Applying Animations #Empty animations

    If you simply want to reset the skeleton to the setup pose without any mixing, you can use SetToSetupPose( ).

    I hope this will help you.

    Thank you, i used SetEmptyAnimation(), with state.update and state.apply and it worked!

    I used a key to test it, but i wanted to do it every time by using AnimationState.Complete += RecoilReset;
    It didn't work tho.

    There is another problem, using trackEntry4.MixBlend = MixBlend.Add;
    It didn't work as i intended to, when i shoot, the back of the character rotates to the position it is on the recoil animation, but what i wanted to do is to just add the rotation change to the rotation it is at, for example, when running, it rotates forward, and i just wanted it to rotate back a bit and then come back, for the recoil.

    • Misaki ответили на это сообщение.

      gumegasonic I am glad to hear that SetEmptyAnimation() worked!

      As for the other issues you are having, since it is difficult to identify the cause from only partial information of your code, could you please show us the entire code?

      • Изменено
      using Spine;
      using Spine.Unity;
      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      
      public class SpineWeaponSelector : MonoBehaviour
      {
          [SerializeField] private SkeletonAnimation skeletonAnim;
          [SerializeField] private AnimationReferenceAsset weapon1;
          [HideInInspector] public AnimationReferenceAsset currentWeapon;
          [HideInInspector] public int currentWeaponHand;
          private TrackEntry trackEntry4;
      
          void Start()
          {
              currentWeapon = weapon1;
      
              UpdateWeapon(1);
          }
      
          private void Update()
          {
              
          }
      
          public void UpdateWeapon(int weaponHand)
          {
              skeletonAnim.state.SetAnimation(1, currentWeapon, true);
      
              currentWeaponHand = weaponHand;
          }
      
          public void Recoil()
          {
              skeletonAnim.state.SetAnimation(4, currentWeapon.name + "_recoil", false);
      
              if(trackEntry4 == null)
              {
                  trackEntry4 = skeletonAnim.AnimationState.GetCurrent(4);
      
                  trackEntry4.MixBlend = MixBlend.Add;
      
                  skeletonAnim.AnimationState.Complete += RecoilReset;
              }
          }
      
          private void RecoilReset(TrackEntry trackEntry)
          {
              skeletonAnim.state.SetEmptyAnimation(4, 0.2f);
              skeletonAnim.state.Update(0);
              skeletonAnim.state.Apply(skeletonAnim.skeleton);
          }
      }
      • Misaki ответили на это сообщение.

        gumegasonic Thank you for showing us your code! I assume the following code would be enough for your purpose:

            public void Recoil()
            {
                trackEntry4 = skeletonAnim.state.SetAnimation(4, currentWeapon.name + "_recoil", false);
                trackEntry4.MixBlend = MixBlend.Add;
                skeletonAnim.state.AddEmptyAnimation(4, 0.2f, 0);
            }

        It looks like what you want to do is simply to mix out the animation played on track 4 to an empty animation when it is completed, so it looks like it could be achieved by calling AddEmptyAnimation() with delay:0. In other words, there appears to be no need to register RecoilReset() to the Complete event.

        Regarding the issue of MixBlend.Add not working as you intended, you may want to see the API reference again: MixBlend-add
        MixBlend.Add transitions from the current value to the current value plus the timeline value. Based on your explanation, it appears that your desired behavior can be achieved by the default MixBlend (Replace). Therefore, I think commenting out the line trackEntry4.MixBlend = MixBlend.Add; of the code above might be the behavior you are looking for.

        Could you check to see if this will accomplish what you want to do and let us know the results?

        • Изменено

        Thank you, this helped a lot

        I separated the recoil animation in 2 parts, one for the arm's recoil animation, and other for the back, on track 5, i did that because the back's recoil animation while running was strange, and now it's working very nicely

        but now i'm getting this error message:

        SerializedObjectNotCreatableException: Object at index 0 is null
        UnityEditor.Editor.CreateSerializedObject () (at <00d63564201b48698d51680c10078897>:0)
        UnityEditor.Editor.GetSerializedObjectInternal () (at <00d63564201b48698d51680c10078897>:0)
        UnityEditor.Editor.get_serializedObject () (at <00d63564201b48698d51680c10078897>:0)
        Spine.Unity.Editor.SpineAtlasAssetInspector.OnEnable () (at ./Library/PackageCache/com.esotericsoftware.spine.spine-unity@7883f0fafd/Editor/spine-unity/Editor/Asset Types/SpineAtlasAssetInspector.cs:71)

        this is the new code:

        public class SpineWeaponSelector : MonoBehaviour
        {
            [SerializeField] private SkeletonAnimation skeletonAnim;
            [SerializeField] private AnimationReferenceAsset weapon1;
            [HideInInspector] public AnimationReferenceAsset currentWeapon;
            [SerializeField] private AnimationReferenceAsset animationWithNoBackRecoil;
            [HideInInspector] public int currentWeaponHand;
            private TrackEntry trackEntry4, trackEntry5;
        
            void Start()
            {
                currentWeapon = weapon1;
        
                UpdateWeapon(1);
            }
        
            private void Update()
            {
                
            }
        
            public void UpdateWeapon(int weaponHand)
            {
                skeletonAnim.state.SetAnimation(1, currentWeapon, true);
        
                currentWeaponHand = weaponHand;
            }
        
            public void Recoil()
            {
                trackEntry4 = skeletonAnim.state.SetAnimation(4, currentWeapon.name + "_recoil", false);
                //trackEntry5.MixBlend = MixBlend.Add;
                skeletonAnim.state.AddEmptyAnimation(4, 0.2f, 0);
                if(skeletonAnim.state.GetCurrent(0).Animation != animationWithNoBackRecoil.Animation)
                {
                    trackEntry5 = skeletonAnim.state.SetAnimation(5, currentWeapon.name + "_recoil_back", false);
                    skeletonAnim.state.AddEmptyAnimation(5, 0.2f, 0.1f);
                }
            }
        }
        • Misaki ответили на это сообщение.

          Everything is looking good now

          Thanks a lot for your help!

          • Misaki ответили на это сообщение.

            gumegasonic I'm glad to hear that! Thank you for getting back to us 🙂