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
0
Question by 1337GameDev · Jan 09, 2014 at 05:01 PM · c#reflectionenumrtscommands

[C#] Creating a FSM based RTS unit, trouble with commands and reflection

I am creating an RTS game and want to assign commands to my unit, but want to avoid having a currentCommand enum and doing just a switch on that in update, oncollision, onDestroy, etc.

I chose to use delegates and assign methods to them from the command source file to implement this. I found a very nice article here:

Unity Gems - FSM

I have my delegates defined in my unit controller class, and I have my configureState method that takes a RTSCommand object (child command classes override methods that get assigned to the delegates) and it will assign methods form the input to the delegates with reflection.

My current problem is, how to pass an RTSCommand to this method when I call another method that gets passed in an enum of a command to give. Show I just switch on the enum and call the appropriate method with the RTSCommand reference that matches with the enum value?

Is there any better way to accomplish this? (I also want efficiency as this is for mobile as well (ipad3 or later for ios) )

Here is part of my code right now:

 private RTSCommand currentCommand;
 
     public Action DoUpdate = DoNothing;
     public Action DoLateUpdate = DoNothing;
     public Action DoFixedUpdate = DoNothing;
     public Action<Collider> DoOnTriggerEnter = DoNothingCollider;
     public Action<Collider> DoOnTriggerStay = DoNothingCollider;
     public Action<Collider> DoOnTriggerExit = DoNothingCollider;
     public Action<Collision> DoOnCollisionEnter = DoNothingCollision;
     public Action<Collision> DoOnCollisionStay = DoNothingCollision;
     public Action<Collision> DoOnCollisionExit = DoNothingCollision;
     public Action DoOnMouseEnter = DoNothing;
     public Action DoOnMouseUp = DoNothing;
     public Action DoOnMouseDown = DoNothing;
     public Action DoOnMouseOver = DoNothing;
     public Action DoOnMouseExit = DoNothing;
     public Action DoOnMouseDrag = DoNothing;
     public Action DoOnGUI = DoNothing;
 
     public IEnumerator DoNothingIE() {yield return null;}
 
     public delegate IEnumerator ExitState(IEnumerator i);
     ExitState exitState = DoNothingCoroutine;
 
     public delegate IEnumerator EnterState(IEnumerator e);
     EnterState enterState = DoNothingCoroutine;
 
     public static void DoNothing(){}
     public static void DoNothingCollider(Collider c){}
     public static void DoNothingCollision(Collision c){}
     public static IEnumerator DoNothingCoroutine(IEnumerator i){return i;}
 
     //change this to include passing in a class of the command to fetch methods from
     void ConfigureCurrentState(RTSCommand c)
     {
         //If we have an exit state, then start it as a 
         //coroutine
         if(exitState != null)
         {
             StartCoroutine(exitState( DoNothingIE()) );
         }
         //Now we need to configure all of the methods
         DoUpdate = ConfigureDelegate<Action>(c,"Update", DoNothing);
         DoOnGUI = ConfigureDelegate<Action>(c,"OnGUI", DoNothing);
         DoLateUpdate = ConfigureDelegate<Action>(c,"LateUpdate", DoNothing);
         DoFixedUpdate = ConfigureDelegate<Action>(c,"FixedUpdate", DoNothing);
         DoOnMouseUp = ConfigureDelegate<Action>(c,"OnMouseUp", DoNothing);
         DoOnMouseDown = ConfigureDelegate<Action>(c,"OnMouseDown", DoNothing);
         DoOnMouseEnter = ConfigureDelegate<Action>(c,"OnMouseEnter", DoNothing);
         DoOnMouseExit = ConfigureDelegate<Action>(c,"OnMouseExit", DoNothing);
         DoOnMouseDrag = ConfigureDelegate<Action>(c,"OnMouseDrag", DoNothing);
         DoOnMouseOver = ConfigureDelegate<Action>(c,"OnMouseOver", DoNothing);
         DoOnTriggerEnter = ConfigureDelegate<Action<Collider>>(c,"OnTriggerEnter", DoNothingCollider);
         DoOnTriggerExit = ConfigureDelegate<Action<Collider>>(c,"OnTriggerExir", DoNothingCollider);
         DoOnTriggerStay = ConfigureDelegate<Action<Collider>>(c,"OnTriggerEnter", DoNothingCollider);
         DoOnCollisionEnter = ConfigureDelegate<Action<Collision>>(c,"OnCollisionEnter", DoNothingCollision);
         DoOnCollisionExit = ConfigureDelegate<Action<Collision>>(c,"OnCollisionExit", DoNothingCollision);
         DoOnCollisionStay = ConfigureDelegate<Action<Collision>>(c,"OnCollisionStay", DoNothingCollision);
         enterState = ConfigureDelegate<EnterState>(c,"EnterState", DoNothingCoroutine);
         exitState = ConfigureDelegate<ExitState>(c,"ExitState", DoNothingCoroutine);
         //Optimisation, turn off GUI if we don't
 
         //Start the current state
         StartCoroutine(enterState(DoNothingIE()) );
         
     }
 
     //Define a generic method that returns a delegate
     //Note the where clause - we need to ensure that the
     //type passed in is a class and not a value type or our
     //cast (As T) will not work
     T ConfigureDelegate<T>(RTSCommand c, string methodRoot, T Default) where T : class
     {
         //Find a method called CURRENTSTATE_METHODROOT
         //The method can be either public or private
         var mtd = c.GetType().GetMethod(currentCommand.ToString() + "_" + methodRoot, System.Reflection.BindingFlags.Instance 
                                       | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod);
         //If we found a method
         if(mtd != null)
         {
             //Create a delegate of the type that this
             //generic instance needs and cast it                    
             return Delegate.CreateDelegate(typeof(T), this, mtd) as T;
         }
         else
         {
             //If we didn't find a method return the default
             return Default;
         }
         
     }
 
 public void giveCommand(Commander.Commands command, Transform targetTrans, Vector3 targetPos)
     {
         //verify we can rceieve the command (we can transition form current command state to new one)
         //then configure the new state 
         if(canDoCommand(currentCommand.getCommandValue(), command) )
         {
             //can then do command
                        //find RTSCommand reference for given enum input
 
         }
     }



Comment
Add comment · Show 2
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 1337GameDev · Jan 09, 2014 at 07:54 PM 0
Share

That doesn't seem like a terrible idea. hmm. Please post this as a seperate answer so it can be discussed and if it is found to be sufficient i can mark my question as answered.

avatar image RudyTheDev · Jan 10, 2014 at 11:20 AM 0
Share

Converted. That is just one option, so I didn't feel like it was the "right" answer to post it like one.

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by RudyTheDev · Jan 09, 2014 at 05:13 PM

Why not have a currentCommand as a class then? Derive individual command classes from the base class and have common methods.

 class SomeUnitClass
 {
     Command currentCommand;
     void Update() { currentCommand.Do(); }
     // ...
 }
 
 abstract class Command { public abstract void Do(); }
 
 class MoveCommand : Command { public override void Do() { } }
 
 class ShootCommand : Command { public override void Do() { } }
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

19 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

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

How to assign Enums to button? 0 Answers

how to get enum value by looking for their hashcode? 1 Answer

Accessing Enumeration from another script issue 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