• RuntimesUnity
  • Two-skeleton animation issue

  • Изменено

Hi everyone, I am completely new to the Spine-Unity runtime. The situation is as follows: I have a Player game object, which has 2 skeletons as child objects: one containing front animations and the other with side animations. When moving up and down, the side animations are disabled, when moving left and right, the frontal animations are disabled. Thus, the skeletons don't conflict. But a problem arose when we had to introduce new animations responsible for interaction with objects. For example, we have the Plowing animation, which itself refers to the side skeleton. Debug.Log shows that everything is fine with the code, the trigger fires and the animation is set, but it isn't visible in the game at all. Just a slight twitch and then the character is back in Idle animation.

Here are my scripts:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public InventoryManager inventoryManager;
    private TileManager tileManager;
    private SpineAnimatorController spineAnimatorController; // Reference to the SpineAnimatorController script

    private void Start()
    {
        tileManager = GameManager.instance.tileManager;
        spineAnimatorController = GetComponent<SpineAnimatorController>(); // Get the SpineAnimatorController component
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (tileManager != null)
            {
                Vector3Int position = new Vector3Int((int)transform.position.x, (int)transform.position.y, 0);

                string tileName = tileManager.GetTileName(position);

                if (!string.IsNullOrWhiteSpace(tileName))
                {
                    if (tileName == "interactable" && inventoryManager.toolbar.selectedSlot.itemName == "Hoe")
                    {
                        tileManager.SetInteracted(position);
                        spineAnimatorController.SetCharacterState("PlowingSide"); // Trigger the plowing animation

                        Debug.Log("Plowing animation triggered!");
                    }
                    else
                    {
                        // Check the surrounding tiles
                        Vector3Int[] surroundingPositions = new Vector3Int[]
                        {
                            new Vector3Int(position.x - 1, position.y, 0), // Left
                            new Vector3Int(position.x + 1, position.y, 0), // Right
                            new Vector3Int(position.x, position.y - 1, 0), // Down
                            new Vector3Int(position.x, position.y + 1, 0), // Up
                            new Vector3Int(position.x - 1, position.y - 1, 0), // Bottom-left
                            new Vector3Int(position.x + 1, position.y - 1, 0), // Bottom-right
                            new Vector3Int(position.x - 1, position.y + 1, 0), // Top-left
                            new Vector3Int(position.x + 1, position.y + 1, 0) // Top-right
                        };

                        foreach (Vector3Int surroundingPosition in surroundingPositions)
                        {
                            string surroundingTileName = tileManager.GetTileName(surroundingPosition);

                            if (surroundingTileName == "interactable" && inventoryManager.toolbar.selectedSlot.itemName == "Hoe")
                            {
                                tileManager.SetInteracted(surroundingPosition);
                                spineAnimatorController.SetCharacterState("PlowingSide"); // Trigger the plowing animation
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    public void DropItem(Item item)
    {
        Vector2 spawnLocation = transform.position;
        Vector2 spawnOffset = Random.insideUnitCircle * 1.25f;

        Item droppedItem = Instantiate(item, spawnLocation + spawnOffset, Quaternion.identity);
        droppedItem.rb2d.AddForce(spawnOffset * .2f, ForceMode2D.Impulse);
    }

    public void DropItem(Item item, int numToDrop)
    {
        for (int i = 0; i < numToDrop; i++)
        {
            DropItem(item);
        }
    }
}`

`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine.Unity;

public class SpineAnimatorController : MonoBehaviour
{
    public SkeletonAnimation frontSkeletonAnimation;
    public SkeletonAnimation sideSkeletonAnimation;

    public AnimationReferenceAsset walkingUp;
    public AnimationReferenceAsset walkingDown;
    public AnimationReferenceAsset idleSide;
    public AnimationReferenceAsset walkingSide;
    public AnimationReferenceAsset plowingSide; // New animation reference for plowing

    public string currentState;
    public float speed;
    public float movement;
    private Rigidbody2D rigidbody;

    public string currentAnimation;

    void Start()
    {
        rigidbody = GetComponent<Rigidbody2D>();
        currentState = "IdleSide";
        SetCharacterState(currentState);
    }

    void Update()
    {
        Move();
    }

    public void SetAnimation(AnimationReferenceAsset animation, bool loop, float timeScale)
    {
        if (animation.name.Equals(currentAnimation))
        {
            return;
        }
        frontSkeletonAnimation.state.SetAnimation(0, animation, loop).TimeScale = timeScale;
        sideSkeletonAnimation.state.SetAnimation(0, animation, loop).TimeScale = timeScale;
        currentAnimation = animation.name;
    }

    public void SetCharacterState(string state)
    {
        if (state.Equals("IdleSide"))
        {
            SetAnimation(idleSide, true, 1f);
            sideSkeletonAnimation.gameObject.SetActive(true);
            frontSkeletonAnimation.gameObject.SetActive(false);
        }
        else if (state.Equals("WalkingSide"))
        {
            SetAnimation(walkingSide, true, 2f);
            sideSkeletonAnimation.gameObject.SetActive(true);
            frontSkeletonAnimation.gameObject.SetActive(false);
        }
        else if (state.Equals("WalkingUp"))
        {
            SetAnimation(walkingUp, true, 2f);
            sideSkeletonAnimation.gameObject.SetActive(false);
            frontSkeletonAnimation.gameObject.SetActive(true);
        }
        else if (state.Equals("WalkingDown"))
        {
            SetAnimation(walkingDown, true, 2f);
            sideSkeletonAnimation.gameObject.SetActive(false);
            frontSkeletonAnimation.gameObject.SetActive(true);
        }
        else if (state.Equals("PlowingSide")) // New state for plowing animation
        {
            SetAnimation(plowingSide, false, 1f);
            sideSkeletonAnimation.gameObject.SetActive(true);
            frontSkeletonAnimation.gameObject.SetActive(false);

            Debug.Log("Plowing animation state set!"); // Add debug log statement
        }
    }

    public void Move()
    {
        movement = Input.GetAxis("Horizontal");
        rigidbody.velocity = new Vector2(movement * speed, rigidbody.velocity.y);
        if (movement != 0)
        {
            if (movement > 0)
            {
                transform.localScale = new Vector2(1f, 1f);
                SetCharacterState("WalkingSide");
            }
            else
            {
                transform.localScale = new Vector2(-1f, 1f);
                SetCharacterState("WalkingSide");
            }
        }

        float verticalMovement = Input.GetAxis("Vertical");
        rigidbody.velocity = new Vector2(rigidbody.velocity.x, verticalMovement * speed);
        if (verticalMovement != 0)
        {
            if (verticalMovement > 0)
            {
                SetCharacterState("WalkingUp");
            }
            else
            {
                SetCharacterState("WalkingDown");
            }
        }
        else if (movement != 0)
        {
            SetCharacterState("WalkingSide");
        }
        else
        {
            SetCharacterState("IdleSide");
        }
    }
}
Related Discussions
...

Based on the provided scripts and the issue described, it seems like the problem might be related to how the animations are being managed and switched between the two skeletons. Since the PlowingSide animation is specifically for the side skeleton, ensure that the side skeleton is active and properly set to play the PlowingSide animation. One potential issue could be the animation state not being correctly updated or the animation not being properly triggered due to conditions not being met or conflicts with other animations.

A few things to check and try:

  1. Ensure that the plowingSide AnimationReferenceAsset is correctly assigned in the Unity Inspector and points to the correct animation in your Spine project.
  2. Verify that the SetAnimation method correctly identifies the plowingSide animation by its name and that there are no typos or mismatches in the animation name.
  3. Since the PlowingSide animation is not looping (as indicated by the false parameter in SetAnimation(plowingSide, false, 1f);), ensure that there's no immediate state change after setting the PlowingSide state that could override the plowing animation before it has a chance to play.
  4. Add debug logs in the SetAnimation method to confirm that the method is called with the expected parameters when the plowing animation is supposed to play.
  5. Check if there are any other scripts or components that might be affecting the visibility or state of the skeletons and animations.

If after these checks the issue still persists, consider isolating the animation triggering logic in a simpler setup to ensure there's no interference from other parts of the code and to confirm that the animation itself is correctly set up and can play as expected.

Make sure you aren't setting animations each frame. That will reset the animations each time instead of letting them play. Maybe log every time an animation is set, so you can see if they are set too often or if you are inadvertently setting idle after plow for some reason.