1
\$\begingroup\$

I bought an asset the other day containing an Atlas of character parts (head, hairs, clothes, body-parts). It's great and allows me to tint each piece any color I want. However, The artist decided to devide up the character like this:

enter image description here

Each child is a fully setup character, facing a certain direction, with an Animator attached to it, inside each Animator Controller you find this:

enter image description here

Some sample animations, pretty self-explanatory. However, I have never worked with sprites like this where its several parts, the entire character is maybe 30-40 parts (allowing for some fun animations). I'm used to making Blend Trees (on a single GameObject) and have one animation for each direction. The best solution for controlling these animations I could think of was something like this:

private void AnimControl() //call in update
    {
        if(direction != directionLastFrame) //do not run method if we are moving same direction
        {
            //standing still
            if (direction.x == 0 && direction.y == 0)
            {
                directionLastFrame = direction;
            }
            ////left
            else if (direction.x < 0.5f && direction.y == 0)
            {
                currentCharacterDirection.SetActive(false); //set current gameObject (which is a character facing a certain direction) inactive
                currentCharacterDirection = character.leftDirection; //change to correct direction
                currentCharacterDirection.SetActive(true); //set gameobject active again
                anim = currentCharacterDirection.GetComponent<Animator>(); //set the animation controller to the new gameObject
                directionLastFrame = direction; //set the new direction to check for
            }
            ////right
            else if (direction.x >= 0.5f && direction.y == 0)
            {
                currentCharacterDirection.SetActive(false);
                currentCharacterDirection = character.rightDirection;
                currentCharacterDirection.SetActive(true);
                anim = currentCharacterDirection.GetComponent<Animator>();
                directionLastFrame = direction;
            }
            ////down
            else if (direction.y < 0.5f && direction.x == 0)
            {
                currentCharacterDirection.SetActive(false);
                currentCharacterDirection = character.downDirection;
                currentCharacterDirection.SetActive(true);
                anim = currentCharacterDirection.GetComponent<Animator>();
                directionLastFrame = direction;
            }
            ////up
            else if (direction.y >= 0.5f && direction.x == 0)
            {
                currentCharacterDirection.SetActive(false);
                currentCharacterDirection = character.upDirection;
                currentCharacterDirection.SetActive(true);
                anim = currentCharacterDirection.GetComponent<Animator>();
                directionLastFrame = direction;
            }
        }

        anim.SetBool("Moving", playerMoving);
    }

I mean it works, but feels wrong? Anyone that can think of a better Idea here, worried this might be too slow. setting an object to active/inactive too often.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

The only things I see you could do to optimize your solution are:

  • Avoid calling GetComponent() on each frame, by adding to the script that have attached your child characters an Animator property, so they have their own animator property
  • Your direction assignation could be assigned just once, since in all of you if-else cases, direction gets the same value.
  • Similarly to the direction assignation, in all your if-else cases, you are first deactivating your character, then activating the new character, so you can avoid redundancy by doing those procedures at the start and end, respectively.

Since I don't know the common script both your parent and child characters have, I'll give my example with a custom script (you'd just need to add that on the scripts you know they have):

public class AnimatorCharacter : MonoBehaviour
{
    private Animator _animator;

    public Animator GetAnimator() { return _animator; }

    void Awake()
    {
        _animator = GetComponent<Animator>();
    }
}

So, in your implementation you'd do something like this:

private void AnimControl() //call in update
{
    if(direction != directionLastFrame) //do not run method if we are moving same direction
    {
        currentCharacterDirection.SetActive(false); //set current gameObject (which is a character facing a certain direction) inactive

        //standing still
        if (direction.x == 0 && direction.y == 0)
        {
            //...
        }
        ////left
        else if (direction.x < 0.5f && direction.y == 0)
        {
            currentCharacterDirection = character.leftDirection; //change to correct direction 
        }
        ////right
        else if (direction.x >= 0.5f && direction.y == 0)
        {
            currentCharacterDirection = character.rightDirection;
        }
        ////down
        else if (direction.y < 0.5f && direction.x == 0)
        {
            currentCharacterDirection = character.downDirection;
        }
        ////up
        else if (direction.y >= 0.5f && direction.x == 0)
        {
            currentCharacterDirection = character.upDirection;
        }

        currentCharacterDirection.SetActive(true); //set gameobject active again
        directionLastFrame = direction; //set the new direction to check for
    }

    currentCharacterDirection.GetAnimator().SetBool("Moving", playerMoving);
}

Setting aside that, your solution seems ok to me (although I don't know that asset's implementation). Hope this helps.

\$\endgroup\$
1
  • \$\begingroup\$ Some great stuff! Makes it a lot prettier :) \$\endgroup\$
    – Green_qaue
    Nov 18, 2017 at 20:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .