Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 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 thrmotta · Jul 29, 2015 at 06:48 PM · c#debugdebuggingloggeneric

Generic Debug Message

So, this has been bugging me for awhile now and altough this isnt something crucial, it would save me sometime.

From time to time I have to create a Debug message to.... well, debug. And every message I create has the same format:

Lets say I have a variable called assetPathAndName, which is a string and holds the message "Assets/". So my Debug.Log will be like this:

 Debug.Log( "assetPathAndName: " + assetPathAndName );

Which will have the following output: "assetPathAndName: Assets/". (without the quotes)

How would I create a method which would only have a generic parameter (basically the types that Debug.Log supports, int, float, Vector3, string...) and would create a string containing both the variable name and the variable value?

Thanks!

Comment
Add comment · Show 3
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 Dave-Carlile · Jul 29, 2015 at 08:29 PM 2
Share

I don't believe it's possible to use reflection to get a variable name since it no longer exists once it's compiled to IL. There are some ways to get it it seems, but I don't know how cross platform it is.

avatar image Bunny83 · Jul 29, 2015 at 08:46 PM 2
Share

Exectly. With reflection alone it's almost impossible. Afaik Unity's $$anonymous$$ono version doesn't support expression trees. Reflection works on types only. If you pass a variable to a generic method two things happens:

  • The compiler inferres the generic type from the variable's type. For example "int" (or "string" in your case).

  • When you call the method you don't pass a variable to the method but it's value. The variables name isn't passed.

Even when you would analyse the compiled IL code (isn't possible in webbuilds afaik) there are two different cases:

  • You pass a local variable

  • You pass a member variable of a class.

In the first case the compiled code doesn't have any variable name. Local variables inside a method don't have names. They just have an index on the local stack.

In the second case the actual member can be deter$$anonymous$$ed, but for this you would have to literally analyse each opcode in all methods to find the places where your method get called and analyse it's parameter.

This is far to complicated for a debug library. However if you want a link to play with, here it is.

avatar image thrmotta · Jul 29, 2015 at 09:04 PM 0
Share

Actually, although not as generic as Id want to, the link @Dave Carlile sent contained the answer:

 public static string GetParameterInfo1<T>( T item ) where T : class
 {
     if( item == null )
         return string.Empty;
 
     var param = item.ToString( ).TrimStart( '{' ).TrimEnd( '}' ).Split( '=' );
     return "Parameter: '" + param[ 0 ].Trim( ) +
             "' = " + param[ 1 ].Trim( );
 }

The downside is that the call actually takes longer to write than what a regular Debug.Log call would (or maybe instantiating a class and using those brackets annoys me):

 int thisIsATest= 43;
 Debug.Log( GetParameterName1( new { thisIsATest} ) );

This actually prints 'thisIsATest' = 43

And the following will only prints "item: 43"

 public static string GetParameterName( object item )
 {
      return GetParameterName1( new { item }  );
 }

Which I think ends up in one of @Bunny83 cases.

Couldnt figure a way to bypass the class instantiating.

1 Reply

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

Answer by thrmotta · Jul 29, 2015 at 09:21 PM

Actually, this did work (tested with int, string, a Custom Interface and Vector3):

 public static void Check<T>( System.Func<T> expr )
 {
     // get IL code behind the delegate
     var il = expr.Method.GetMethodBody( ).GetILAsByteArray( );
     // bytes 2-6 represent the field handle
     var fieldHandle = System.BitConverter.ToInt32( il, 2 );
     // resolve the handle
     var field = expr.Target.GetType( )
         .Module.ResolveField( fieldHandle );
 
     Debug.Log( "Name is: " + field.Name );
     Debug.Log( "Value is: " + expr( ) );
 }

Got it from this link

Thanks @Bunny83 and @Dave Carlile for point me to the right link! =)

Comment
Add comment · Show 2 · 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 Bunny83 · Jul 29, 2015 at 10:30 PM 1
Share

Well, the IL parsing approach also requires you to create a class instance (the lambda delegate). Also "GetILAsByteArray" creates a byte array. Both not ideal for the GC.

Also be careful with that approach. You don't look at the actual opcode at all. You just assume that byte 2-6 are an integer that represents a field token id. If that's not the case ResolveField might fail and throw an exception or return complete nonsense.

avatar image thrmotta · Jul 29, 2015 at 11:01 PM 0
Share

True! I tried to use that method with Application.DataPath and it threw me an exception, now I understand why. Thanks :)

After all Ill just stick with the regular Debug.Log. Better to waist a second longer on typing than to wait for unity to build and throw me an exception.

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

23 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

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Not able to convert GetComponent ().netId to a string. 0 Answers

debugging multiple gameobjects with the same script 0 Answers

C# Generic return type 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