Skip to content

Python style decorator (add action to method with attribute) via rewriting IL

License

Notifications You must be signed in to change notification settings

kdw9502/UnityMethodDecorator

Repository files navigation

UnityDecoratorAttribute

UnityDecoratorAttribute is a library for adding custom actions to methods using attributes, similar to Python's @decorator. This library is implemented using Mono.Cecil.

By adding the DecoratorAttribute to a method, you can execute custom actions at the beginning and end of the method.

Installation

To use UnityDecoratorAttribute, download the package from this GitHub repository and import it into your Unity project.

Usage

Predefined Example Attributes

UnityDecoratorAttribute comes with several predefined example attributes that you can use to add custom actions to your methods:

[ParameterLog]
public void TestParameterLog(int a, float b, Text text)
{
}
[InstanceLog]
public void TestInstanceLog(int a)
{
}

Result

image

  • CallCounterAttribute : Stores the number of times a method is called and returns the count using CallCounter.GetMethodCallCount(className, methodName).

image

PerformanceCheck.GetExecutionCount(className, methodName): Returns the number of times the method has been executed (called).

PerformanceCheck.GetTotalExecutionTimeMs(className, methodName): Returns the total execution time of the method in milliseconds.

PerformanceCheck.GetMeanExecutionTimeMs(className, methodName): Returns the mean execution time of the method in milliseconds.

[PerformanceCheck]
public void Update()
{
    elapsedTime += Time.deltaTime;
    if (elapsedTime <= 5) 
        return;

    Debug.Log($"GetExecutionCount: {PerformanceCheck.GetExecutionCount(nameof(AttributeExample), nameof(Update))}");
    Debug.Log($"GetTotalExecutionTimeMs: {PerformanceCheck.GetTotalExecutionTimeMs(nameof(AttributeExample), nameof(Update))} ms");
    Debug.Log($"GetMeanExecutionTimeMs: {PerformanceCheck.GetMeanExecutionTimeMs(nameof(AttributeExample), nameof(Update))} ms");
    elapsedTime = 0;
}

image

Creating a Custom Attribute

To create a custom attribute, you need to inherit from UnityDecoratorAttribute.DecoratorAttribute:

c#public class ExampleAttribute : DecoratorAttribute
{
}

PreAction

The PreAction method is always called when the target method is called.

Defining PreAction

To define the PreAction method in your attribute, create a static method called PreAction. If your PreAction method needs parameters, define a field called PreActionParameterTypes with the required parameter types.

Example
public class DebugLogAttribute : DecoratorAttribute
{
    [Preserve]
    public static void PreAction(string className, string methodName)
    {
        Debug.Log($"{className}::{methodName}");
    }

    public static PreActionParameterType[] PreActionParameterTypes => 
        new[] {PreActionParameterType.ClassName, PreActionParameterType.MethodName};
}

PostAction

The PostAction method is called before the target method returns.

Defining PostAction

To define the PostAction method in your attribute, create a static method called PostAction. If your PostAction method needs parameters, define a field called PostActionParameterTypes with the required parameter types.

Example
public class ClampReturnAttribute : DecoratorAttribute
{
    public ClampReturn(int min, int max)
    {
    }
    
    [Preserve]
    public static void PostAction(ref int @return, int min, int max)
    {
        @return = Math.Clamp(@return, min, max);
    }

    public static ParameterType[] PostActionParameterTypes =>
        new[] {ParameterType.ReturnValue, ParameterType.AttributeValues};
}

The PostAction method can take parameters of different types. You can use the ParameterType enum to specify the type of each parameter.

public enum ParameterType
{
    ClassName,
    MethodName,
    This,  // Target Method's Instance
    ParameterValues, // Target Method's Parameter Values (only for PreAction)
    ReturnValue, //  Target Method's ReturnValue (only for PostAction)
    AttributeValues, // Attribute values
}

Limitations

This library does not support coroutines or async methods.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Python style decorator (add action to method with attribute) via rewriting IL

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages