Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by dev_mp · Apr 29, 2021 at 06:24 PM · nestedswitch-caserefactor

How to refactor nested switches

Hey guys. I need to update the character animation depending on the state (Idle, Walk, Interact) and the orientation (NE, E, SE, SW, W, NW). Animations are "IdleNE", "WalkW", etc.

In order to manage it I would like to have something similar to

 private void UpdateAnimation()
 {
   spriteAnimator.Play(currentState.toString() + currentOrientation.toString())
 }

but I came up with nasty nested switches instead...

 private void UpdateAnimation()
 {
     switch (currentState)
     {
         case PlayerState.Idle:
             switch (currentOrientation)
             {
                 case PlayerOrientation.E:
                     spriteAnimator.Play(idleE);
                     break;
                 case PlayerOrientation.NE:
                     spriteAnimator.Play(idleNE);
                     break;
                 case PlayerOrientation.NW:
                     spriteAnimator.Play(idleNW);
                     break;
                 case PlayerOrientation.W:
                     spriteAnimator.Play(idleW);
                     break;
                 case PlayerOrientation.SW:
                     spriteAnimator.Play(idleSW);
                     break;
                 case PlayerOrientation.SE:
                     spriteAnimator.Play(idleSE);
                     break;
             }
             break;
         case PlayerState.Walk:
             {
                 switch (currentOrientation)
                 {
                     case PlayerOrientation.E:
                         spriteAnimator.Play(walkE);
                         break;
                     case PlayerOrientation.NE:
                         spriteAnimator.Play(walkNE);
                         break;
                     case PlayerOrientation.NW:
                         spriteAnimator.Play(walkNW);
                         break;
                     case PlayerOrientation.W:
                         spriteAnimator.Play(walkW);
                         break;
                     case PlayerOrientation.SW:
                         spriteAnimator.Play(walkSW);
                         break;
                     case PlayerOrientation.SE:
                         spriteAnimator.Play(walkSE);
                         break;
                 }
                 break;
             }
             break;
         case PlayerState.Interact:
             switch (currentOrientation)
             {
                 case PlayerOrientation.E:
                     spriteAnimator.Play(interactE);
                     break;
                 case PlayerOrientation.NE:
                     spriteAnimator.Play(interactNE);
                     break;
                 case PlayerOrientation.NW:
                     spriteAnimator.Play(interactNW);
                     break;
                 case PlayerOrientation.W:
                     spriteAnimator.Play(interactW);
                     break;
                 case PlayerOrientation.SW:
                     spriteAnimator.Play(interactSW);
                     break;
                 case PlayerOrientation.SE:
                     spriteAnimator.Play(interactSE);
                     break;
             }
             break;
         default:
             break;
     }
 }
 

I'm not sure there is any proper alternative to do it, so any idea would be really welcome. Thanks in advance!

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Hellium · Apr 29, 2021 at 06:42 PM

I see at least two possibilities (NOT TESTED)

 private string[,] animations = new string[3,6]; // 3 states & 6 orientations
 
 private void FillAnimationArray()
 {
     animations[PlayerState.Idle, PlayerOrientation.E] = idleE;
     animations[PlayerState.Idle, PlayerOrientation.NE] = idleNE;
     animations[PlayerState.Idle, PlayerOrientation.NW] = idleNW;
     animations[PlayerState.Idle, PlayerOrientation.W] = idleW;
     animations[PlayerState.Idle, PlayerOrientation.SE] = idleSE;
     animations[PlayerState.Idle, PlayerOrientation.SW] = idleSW;
     
     animations[PlayerState.Walk, PlayerOrientation.E] = walkE;
     animations[PlayerState.Walk, PlayerOrientation.NE] = walkNE;
     animations[PlayerState.Walk, PlayerOrientation.NW] = walkNW;
     animations[PlayerState.Walk, PlayerOrientation.W] = walkW;
     animations[PlayerState.Walk, PlayerOrientation.SE] = walkSE;
     animations[PlayerState.Walk, PlayerOrientation.SW] = walkSW;
     
     animations[PlayerState.Interact, PlayerOrientation.E] = interact;
     animations[PlayerState.Interact, PlayerOrientation.NE] = interactNE;
     animations[PlayerState.Interact, PlayerOrientation.NW] = interactNW;
     animations[PlayerState.Interact, PlayerOrientation.W] = interactW;
     animations[PlayerState.Interact, PlayerOrientation.SE] = interactSE;
     animations[PlayerState.Interact, PlayerOrientation.SW] = interactSW;
 }
 
 private void UpdateAnimation()
 {
     spriteAnimator.Play(animations[currentState, currentOrientation]);
 }


 public class StateAnimationCollection
 {
     private Dictionary<PlayerOrientation, string> animations;
 
     public StateAnimationCollection(
         string eAnimation, string neAnimation, string seAnimation,
         string wAnimation, string nwAnimation, string swAnimation
     )
     {
         animations = new Dictionary<PlayerOrientation, string>()
         {
             { PlayerOrientation.E, eAnimation }
             { PlayerOrientation.NE, neAnimation },
             { PlayerOrientation.SE, seAnimation },
             { PlayerOrientation.W, wAnimation },
             { PlayerOrientation.NW, nwAnimation },
             { PlayerOrientation.SW, swAnimation }
         };
     }
 
     public string this[PlayerOrientation orientation] => animations[orientation];
 }

 // Could be simplified by using a Dictionary<PlayerOrientation, string> instead of a StateAnimationCollection
 private Dictionary<PlayerState, StateAnimationCollection> animations = new Dictionary<PlayerState, StateAnimationCollection>
 {
     { PlayerState.Idle, new StateAnimationCollection(idleE, idleNE, idleSE, idleW, idleNW, idleSW) },
     { PlayerState.Walk, new StateAnimationCollection(walkE, walkNE, walkSE, walkW, walkNW, walkSW) },
     { PlayerState.Interact, new StateAnimationCollection(interactE, interactNE, interactSE, interactW, interactNW, interactSW) },
 };
 
 
 private void UpdateAnimation()
 {
     spriteAnimator.Play(animations[currentState][currentOrientation]);
 }


Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by andrew-lukasik · Apr 29, 2021 at 08:08 PM


I suggest state machines. Even the simplest ever and half-broken ones will fold this spaghetti code into something you will be able to understand, maintain, reuse and expand on.


Your MonoBehaviour, responsible for changing states and calling their Tick update methods:

PlayerAnimationController.cs

 using System.Collections.Generic;
 using UnityEngine;
 public class PlayerAnimationController : MonoBehaviour, IPawnAnimationController
 {
     IAnimationControllerState _currentState = null;
     [SerializeField] Animator _spriteAnimator = null;
     Animator IPawnAnimationController.Animator => _spriteAnimator;
     [SerializeField] Orientation _currentOrientation = Orientation.W;
     Orientation IPawnAnimationController.Orientation => _currentOrientation;
     [SerializeField][Range(-1f,1f)] float _horizontal = 0;
     [SerializeField][Range(-1f,1f)] float _vertical = 0;
     const float k_tick_rate = 1f / 30f;
     void OnEnable ()
     {
         _currentState = new IdleState{ Owner=this };
         InvokeRepeating( nameof(UpdateAnimation) , time:k_tick_rate , repeatRate:k_tick_rate );
     }
     void Update ()
     {
         _horizontal = Input.GetAxis("Horizontal");
         _vertical = Input.GetAxis("Vertical");
     }
     void UpdateAnimation ()
     {
         // tick current state:
         _currentState.Tick();
 
         // test for state transitions:
         var inputAxis = new Vector2{ x=_horizontal , y=_vertical };
         if( _currentState is IdleState )
         {
             if( inputAxis.sqrMagnitude>0 )
                 _currentState = new WalkState{ Owner=this };
             else if( Input.GetKey(KeyCode.E) )
                 _currentState = new InteractState{ Owner=this };
         }
         else if( _currentState is InteractState )
         {
             if( inputAxis.sqrMagnitude>0 )
                 _currentState = new WalkState{ Owner=this };
         }
         else if( _currentState is WalkState )
         {
             if( !(inputAxis.sqrMagnitude>0) )
                 _currentState = new IdleState{ Owner=this };
         }
     }
     #if UNITY_EDITOR
     void OnDrawGizmos ()
     {
         if( _currentState!=null )
         UnityEditor.Handles.Label( transform.position , $"({_currentState.GetType().Name})" );
     }
     #endif
 }

Minor types:

Orientation.cs

 public enum Orientation { E , NE , NW , W , SW , SE }    

IAnimationControllerState.cs

 public interface IAnimationControllerState
 {
     IPawnAnimationController Owner { get; set; }
     abstract void Tick ();
 }

IPawnAnimationController.cs

 public interface IPawnAnimationController
 {
     Animator Animator { get; }
     Orientation Orientation { get; }
 }

Your actual states that make the animator calls, and describe what happens in this state:

IdleState.cs

 public struct IdleState : IAnimationControllerState
 {
     public IPawnAnimationController Owner { get; set; }
     static Dictionary<Orientation,string> animationStates = new Dictionary<Orientation,string>{
         { Orientation.E , "idle E" } ,
         { Orientation.NE , "idle NE" } ,
         { Orientation.NW , "idle NW" } ,
         { Orientation.W , "idle W" } ,
         { Orientation.SW , "idle SW" } ,
         { Orientation.SE , "idle SE" } ,
     };
     public void Tick () => Owner.Animator.Play( animationStates[Owner.Orientation] );
 }

WalkState.cs

 public struct WalkState : IAnimationControllerState
 {
     public IPawnAnimationController Owner { get; set; }
     static Dictionary<Orientation,string> animationStates = new Dictionary<Orientation,string>{
         { Orientation.E , "walk E" } ,
         { Orientation.NE , "walk NE" } ,
         { Orientation.NW , "walk NW" } ,
         { Orientation.W , "walk W" } ,
         { Orientation.SW , "walk SW" } ,
         { Orientation.SE , "walk SE" } ,
     };
     public void Tick () => Owner.Animator.Play( animationStates[Owner.Orientation] );
 }

InteractState.cs

 public struct InteractState : IAnimationControllerState
 {
     public IPawnAnimationController Owner { get; set; }
     static Dictionary<Orientation,string> animationStates = new Dictionary<Orientation,string>{
         { Orientation.E , "interact E" } ,
         { Orientation.NE , "interact NE" } ,
         { Orientation.NW , "interact NW" } ,
         { Orientation.W , "interact W" } ,
         { Orientation.SW , "interact SW" } ,
         { Orientation.SE , "interact SE" } ,
     };
     public void Tick () => Owner.Animator.Play( animationStates[Owner.Orientation] );
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

117 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Tried to make a List.>(), it doesn't work, so how do I do that? 1 Answer

nested triggers and an OnMouseDown event 0 Answers

Assign 1st array of materials into multiple gameobjects. 0 Answers

Case Statement Error? 3 Answers

How to get smooth 4 directional movement in top down without diagonal movement? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges