• 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
7
Question by TheAdam · Nov 08, 2013 at 02:49 PM · mecanim

is there a way to check if an animatorcontroller has a parameter?

With mecanim, if you try to set a parameter that doesn't exist, it logs a warning. It doesn't throw an exception or return null or anything useful like that. So if I set a parameter very often that doesn't exist, a lot of CPU time is spent logging warnings. How can I tell if a parameter exists in an animatorcontroller? It would be great if there was a method like ProceduralMaterial.HasProceduralProperty (which allows you to check if the ProceduralMaterial has the property in question).

(crossposted from gamedev.stackexchange)

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

11 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by mkgame · Jan 12, 2019 at 09:22 PM

I would recommend to speed up this check with a Dictionary:

         Dictionary<string, bool> animNames = new Dictionary<string, bool>();
         
         void Awake() {
              animNames.Add("Attack", false);
              animNames.Add("Run", false);
              animNames.Add("Walk", false);
         
              foreach (AnimatorControllerParameter param in MyAnimator.parameters) {
                  if (animNames.containsKey(param.Name)) {
                        animNames[param.Name] = true;         
                  }
              }
 
             // To check then the known param.
             if (animNames["Attack"] == true) {
                  // Attack param available, use it.
             }
         }
 
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
1

Answer by Wappenull · Sep 14, 2019 at 10:19 AM

(Contains code snippet from other answer. Credit to their respective author)

Simpler version

Involve GC alloc on Animator.parameters, not cool for repeated call.

 public static bool HasParameter( string paramName, Animator animator )
 {
     foreach( AnimatorControllerParameter param in animator.parameters )
     {
         if( param.name == paramName )
             return true;
     }
     return false;
 }

 // Usage sample
 public void SetFloatParamWithCheck( string paramName, float v )
 {
     // animator defined elsewhere.
     Animator animator;     

     if( HasParameter( animator, paramName ) )
     {
         animator.SetFloat( paramName , v );
     }
 }

Extension version

still involve GC alloc every call.

 public static class AnimatorHelper
 {
     public static bool ContainsParam( this Animator _Anim, string _ParamName )
     {
         foreach( AnimatorControllerParameter param in _Anim.parameters )
         {
             if( param.name == _ParamName ) return true;
         }
         return false;
     }
 }

 // Usage sample
 public void SetFloatParamWithCheck( string paramName, float v )
 {
     // animator defined elsewhere.
     Animator animator;     

     if( animator.ContainsParam( paramName ) )
     {
         animator.SetFloat( paramName , v );
     }
 }


An over-engineered version

With caching and resolving parameter hash in one go. Premature optimization is evil but you will need it in (some) practice.

 // Animator parameters query involve GC, cache it
 // Animator.GetParameter( index ) might also internally use it, so no better.

 // Assume typically working with 1 animator, could extending to collect more cache.
 Animator m_LastAnimatorCache; 
 // <key=paramname,value=hash>
 Dictionary<string,int> m_AnimatorParamCache = new Dictionary<string,int>( ); 

 private bool TryGetAnimatorParam( Animator animator, string paramName, out int hash )
 {
     // Rebuild cache
     if( (m_LastAnimatorCache == null || m_LastAnimatorCache != animator) && animator != null ) 
     {
         m_LastAnimatorCache = animator;
         m_AnimatorParamCache.Clear( );
         foreach( AnimatorControllerParameter param in animator.parameters )
         {
             int paramHash = Animator.StringToHash( param.name ); // could use param.nameHash property but this is clearer
             m_AnimatorParamCache.Add( param.name, paramHash );
         }
     }

     if( m_AnimatorParamCache != null && m_AnimatorParamCache.TryGetValue( paramName, out hash ) )
     {
         return true;
     }
     else
     {
         hash = 0;
         return false;
     }
 }

 // Usage sample
 public void SetFloatParamWithCheck( string paramName, float v )
 {
     // animator defined elsewhere.
     Animator animator;
     int hash;

     if( TryGetAnimatorParam( animator, paramName, out hash ) )
     {
         animator.SetFloat( hash, v );
     }
 }
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 lucasmontec · Dec 15, 2019 at 08:23 PM

Extension way of doing it:

 namespace Util
 {
     public static class AnimatorExtensions
     {
         /// <summary>
         /// Caches previous queries.
         /// </summary>
         private static readonly Dictionary<Animator, Dictionary<string, bool>> AnimatorParameterCache = 
             new Dictionary<Animator, Dictionary<string, bool>>();
          
         /// <summary>
         /// Returns true if an animator has a parameter.
         /// </summary>
         /// <param name="animator"></param>
         /// <param name="paramName"></param>
         /// <returns></returns>
         public static bool HasParameter(this Animator animator, string paramName)
         {
             //Check, cache and return
             if (AnimatorParameterCache.ContainsKey(animator) && AnimatorParameterCache[animator].ContainsKey(paramName))
                 return AnimatorParameterCache[animator][paramName];
             
             //Create the dictionary if we need to
             if (AnimatorParameterCache[animator] == null)
             {
                 AnimatorParameterCache[animator] = new Dictionary<string, bool>();
             }
                 
             AnimatorParameterCache[animator][paramName] = 
                 animator.parameters.Any(param => param.name == paramName);
 
             return AnimatorParameterCache[animator][paramName];
         }
     }
 }
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 koelibri · Jan 08, 2020 at 10:40 AM

Found the following very short solution using System.Array working for me:

public static bool HasParameter(Animator animator, string paramName)
{
        return System.Array.Exists(animator.parameters, p => p.name == paramName);
}

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 Kheremos · Oct 30, 2021 at 04:05 AM

This is what I use, as it's two lines. But remember, like previous posts have stated, it's not the most efficient way:

         foreach (var param in animator.parameters) if (param.name == SPEED_MULT)
              animator.SetFloat(SPEED_MULT, Random.Range(0.9f, 1.1f));

Not sure of the GC hit, but my code only runs this as the start of a scene to sort of desynchronize animations.

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
  • ‹
  • 1
  • 2
  • 3
  • ›

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

31 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

Related Questions

Can I change animation speed with mecanim? 2 Answers

Newly Created Animations not Playing with Mecanim 0 Answers

How to get all states and state machines in the Animator on Android? 0 Answers

Mecanim and body orientation 0 Answers

MatchTarget unable to target and giving varried results 0 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