• 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
Question by brazorf · Jul 31, 2014 at 02:12 AM · fsm

Basic idle/walk Movement FSM as a beginner experiment

I'm trying to implement a very basic idle/walk FSM over the default FPSInputController. I've worked with FSM some year ago but i feel like my patterns won't apply in this context. Here's my approach: i've 2 main abstract classes like these

 public abstract class AbstractFSM {
     protected List<AbstractFSMState> states;
     protected AbstractFSMState currentState;
     
     public abstract void Setup();
     
     public void Run(FSMInput input) {
         this.currentState.Enter();
         int next = this.currentState.Execute(input);
         this.currentState.Exit();
         this.currentState = this.states[next];
     }
 }

 public abstract class AbstractFSMState {
     public void Enter() {
         Debug.Log("Entering state " + this.getName());    
     }
 
     public void Exit() {
         // 
     }
     
     public int Execute(FSMInput input) {
         this.Enter();
         int next = this.ExecuteImpl(input);
         this.Exit();
         return next;
     }
     
     public abstract string getName();
     public abstract void EnterImpl();
     protected abstract int ExecuteImpl(FSMInput input);
     public abstract void ExitImpl();
     
 }

Then their implementations

 public class FSMMovement : AbstractFSM {
     public static int STATE_IDLE = 0;
     public static int STATE_WALK = 1;
 
     public override void Setup () {
         Debug.Log("FSMMovement is being setup.");
         this.states = new List<AbstractFSMState>();
         this.states.Add(new StateIdle());
         this.states.Add(new StateWalk());
         this.currentState = this.states[0];
         Debug.Log("Init state is " + this.currentState.getName());
     }
 
 }

 // The ExecuteImpl in StateIdle, omitted the rest
 protected override int ExecuteImpl(FSMInput input) {
     Vector3 directionVector = (Vector3)input.Get("direction");
     if (directionVector != Vector3.zero) {
         return FSMMovement.STATE_WALK;
     } else {
         return FSMMovement.STATE_IDLE;
     }
 }

 // The ExecuteImpl in StateWalk, omitted the rest. Basically,
 // it's the same code from default FPSInputController - except
 // for the audio lines.
 protected override int ExecuteImpl(FSMInput input) {
     Vector3 directionVector = (Vector3)input.Get("direction");
     AudioSource audio = (AudioSource)input.Get("audio");
     CharacterMotor motor = (CharacterMotor)input.Get("motor");
     
     if (directionVector != Vector3.zero) {
         if (!audio.isPlaying) {
             audio.Play();
         }
         
         // Get the length of the directon vector and then normalize it
         // Dividing by the length is cheaper than normalizing when we already have the length anyway
         float directionLength = directionVector.magnitude;
         directionVector = directionVector / directionLength;
 
         // Make sure the length is no bigger than 1
         directionLength = Mathf.Min(1.0f, directionLength);
 
         // Make the input vector more sensitive towards the extremes and less sensitive in the middle
         // This makes it easier to control slow speeds when using analog sticks
         directionLength = directionLength * directionLength;
 
         // Multiply the normalized direction vector by the modified length
         directionVector = directionVector * directionLength;
     } else {
         audio.Stop();
     }
 
     // Apply the direction to the CharacterMotor
     motor.inputMoveDirection = transform.rotation * directionVector;
     motor.inputJump = Input.GetButton("Jump");
 }

Finally, i've changed the FPSInputController Update() like this

 void Update() {
     // Get the input vector from kayboard or analog stick
     Vector3 directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
     
     // Collect input
     FSMInput input = new FSMInput();
     input.Add("direction", directionVector);
     input.Add("audio", audio);
     input.Add("motor", motor);
     
     // Execute
     this.fsm.Run(input);
     return;
 }


I built this code in about an hour and suddenly stopped because i spot many issues, one coming to light for first.

As you can see any state will need a lot of informations from the game context (the controller input, the audio source, the motor script, etc.). I've tried to skip over this adding a FSMInput class -a mere collection built on C# Dictionary- but there's a lot of overhead passing all these data anytime.

On the other hand i won't like hard-coding anything in a single script with tons of switch/case lines.

Can you suggest an approach that better fits in this scenario? Maybe passing the GameObject as the only input value? Or am i doing this completely wrong?

Thanks for reading!

Comment

People who like this

0 Show 0
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

0 Replies

· Add your reply
  • Sort: 

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

2 People are following this question.

avatar image avatar image

Related Questions

Using Playmaker for a game-scope FSM 0 Answers

NullReferenceException on a FSM attribute 1 Answer

GOAP - how can you change the state outside of an action? 1 Answer

How Complex Should Mecanim State Machines Be? 2 Answers

really weird problem, Enum refusing to change state. 1 Answer


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