Jahro Watcher Mode in Unity

Guide to Mastering Real-Time Debugging

Introduction

Welcome to Jahro's Watcher Mode, the real-time monitoring tool made to lend you an extra hand while building amazing games in Unity. In game development, having a watchful eye on variable values as they transform and evolve can make a big difference. It can help you debug effectively, understand your game's behaviour, and fine-tune your designs. That's exactly where Jahro's Watcher Mode shines!

Understanding Watcher Mode

Watcher Mode in Jahro is your real-time surveillance tool in the world of Unity game development. It gives you the power to monitor the state of any field or property in your project, live, while your game is running. Consider it like your personal "dashboard system" keeping an eye on variables!

You can observe:

  1. Fields: Yes, those good old instance variables or class variables you define in your class. Static, non-static, private, or public, Watcher Mode watches them all.
  2. Properties: In C#, properties are a natural extension of fields, providing a flexible mechanism to read, write, or compute their values
You can watch primitive types like ints, floats, strings, and booleans. It doesn't stop there, though. Arrays, Unity's Vector2, Vector3, or even your custom type instances.

Using Jahro Watch Attributes

Applying the [JahroWatch] attribute to your fields or properties will make them accessible in Jahro's Watcher Mode, allowing you to track changes in real time.

Let's have a look at how it's done:

[JahroWatch("Health")]
private int playerHealth = 100;
In this case, the 'playerHealth' field is under Jahro's supervision, with its current value displayed as 'PlayerHealth' in the Watcher Mode.

Note: Jahro don't modify values in Watcher Mode. Please use Commands functionality to change actual values.

The [JahroWatch] attribute offers multiple options for customization, including naming, description, and grouping:

  • Naming: When using the JahroWatch attribute, it's necessary to specify a name. This name is what's displayed in the Watcher Mode. Here's an example:

[JahroWatch("Health")]
private int playerHealth = 100;
  • Description: This description will be visible in the UI, providing further clarity on the variable's function.

[JahroWatch("Health", "The player's current health")]
private int playerHealth = 100;
  • Grouping: To keep your watched variables neatly organized, Jahro allows you to specify a group name. Variables with identical group names will be grouped together in the Watcher Mode UI. If no group name is provided, the variable will be assigned to the 'Default' group.

[JahroWatch("Health", "The player's current health", "Player Stats")]
private int playerHealth = 100;

Static Variables in Watcher Mode

Watching static variables is a breeze with Jahro. Just like with commands, all it takes is a simple JahroWatch attribute, and you're good to go!

Let's take a look at an example:

[JahroWatch("Total Score", "The total score of the game", "Game Stats")]
public static int totalScore;
In this case, 'totalScore' is a public static integer that holds the total score of the game. By marking it with JahroWatch attribute, its value is displayed in Watcher Mode under the 'Game Stats' group with the name 'Total Score'.

Here's another example:

[JahroWatch("Gravity", "The current gravity value in the game", "Game Settings")]
public static Vector3 gravity { get; private set; }
Here, 'gravity' is a public static Vector3 representing the gravity value in the game. Just like the previous example, it is marked with JahroWatch attribute and therefore is visible in Watcher Mode. It belongs to the 'Game Settings' group and appears as 'Gravity Value'.

Using JahroWatch for static variables is as straightforward as it gets. As long as the variable is static and accessible (i.e., private, public or internal), JahroWatch can watch it!

Non-static Variables in Watcher Mode

Non-static variables require a tad more care to be monitored in Jahro's Watcher Mode. Because they're not static, they are related to specific instances of a class, and Jahro needs to know exactly which instance you're referring to.

This is where the Jahro.RegisterObject() function steps into the spotlight. By registering an object, Jahro knows to which instance the non-static field or property belongs.

Here's how you do it:

public class PlayerController : MonoBehaviour
{
    [JahroWatch("Player Health", "The current health of the player", "Player Stats")]
    public int health;

    void Start()
    {
        Jahro.RegisterObject(this);
    }
}
In the example above, we have a non-static field 'health' in the 'PlayerController' class. To monitor the 'health' field of a specific player, we use the Jahro.RegisterObject function and pass this, which represents the current instance of the PlayerController.

With that, Jahro is able to track the 'health' field of this specific player instance in real time. It will display this information in Watcher Mode under the 'Player Stats' group with the name 'Player Health'.

Remember to only use Jahro.RegisterObject for objects that are pertinent to your current gameplay situation. Unnecessary usage can lead to clutter in your Watcher Mode.

Monitoring Array and Complex Types

One of Jahro's most powerful features is its ability to monitor arrays and complex types such as vectors, transforms, components, and more. It's not just about simple integers and strings.

[JahroWatch("Player Position", "Tracks the player's position", "Player Data")]
public Vector3 playerPosition;

[JahroWatch("Level Data", "Shows data of each level", "Game Data")]
public LevelData[] gameLevels;
In these examples, Jahro displays the playerPosition vector and the gameLevels array in a friendly, easily understandable format (just ensure that custom classes have pretty ToString() method overrided).
Null Values

If an object reference is null, Jahro explicitly shows 'Null' as its value. This feature ensures you can quickly detect potential issues where you might expect a reference, but it's unassigned.

[JahroWatch("Nonexistent Object", "A reference that does not exist", "Test Data")]
public GameObject nonexistentObject;
In this example, if nonexistentObject is not assigned in the Unity editor or through code, Jahro will show 'Null' as its value in Watcher Mode.

Exceptions Handling


Occasionally, accessing a property might result in an exception. Jahro catches these exceptions and provides the specifics about the exception right there in the Watcher Mode.

[JahroWatch("Risky Property", "This property might cause an exception", "Test Data")]
public string riskyProperty
{
    get
    {
        throw new Exception("This is a problematic property!");
    }
}
In the example above, Jahro captures the exception caused by accessing riskyProperty and displays the details in the Watcher Mode.

Detailed Information for Complex Types

For complex types like RectTransform, Jahro goes above and beyond and displays a variety of detailed information. For instance:

[JahroWatch("Camera Transform", "Tracks camera transform properties", "Player Data")]
public Transform cameraTransform;
When watching the cameraTransform above, Jahro provides detailed information about position, rotation, local scale, and child count. This extensive information makes it easier for you to understand the current state of your game objects.

Refreshing Watch Values

Jahro's Watcher Mode is designed to constantly keep you updated. The values you're watching are refreshed in line with the Unity's Update loop, meaning the data you see is always up to speed with what's happening in your game.

// Assuming these two objects are initialized and updated somewhere in your game
private GameObject player;
private GameObject enemy;

[JahroWatch("Player-Enemy Distance", "Tracks the distance between the player and an enemy", "Gameplay Metrics")]
public float DistanceBetweenPlayerAndEnemy
{
    get 
    {
        if (player != null && enemy != null)
        {
            return Vector3.Distance(player.transform.position, enemy.transform.position);
        }
        else
        {
            return -1;
        }
    }
}
In this example, the DistanceBetweenPlayerAndEnemy property calculates the distance between a player and an enemy in the game world. The value will be refreshed in Watcher Mode every Unity Update, giving you real-time data on how the distance changes during gameplay.

Performance Caution

However, it's important to remember that every system resource comes with a cost. Though Jahro is optimized for performance and refreshes values only when the Watcher tab is active.

Unwatching Variables

There may come a time when you no longer need to monitor a particular variable. Perhaps you're done troubleshooting that area of your game, or the data the variable provides is no longer needed. Whatever the case may be, Jahro allows you to discontinue tracking these variables.

You can stop watching all variables of an object by using the UnregisterObject method:

Jahro.UnregisterObject(this);
In this case, all watched variables related to the this object will be removed from the Watcher Mode. So if the variable you want to stop watching is part of the object you're unregistering, it will no longer be tracked.
Related articles
Getting Started with Jahro: Your First Steps to Efficient Unity Debugging
Embark on your journey with Jahro. Follow our simple step-by-step guide to install the plugin, create commands, and launch your project. Enhance your Unity 3D debugging experience with Jahro's powerful tools. Start now for a smoother, more efficient workflow.
Level Up Your Debugging Game in Unity with Jahro Commands
Discover how Jahro Commands can revolutionize your debugging process in Unity. Simplify game state management and create your own cheat codes.
Making Debugging Easy: The Comprehensive Guide to Jahro Logs in Unity
Learn to use Jahro Logs in Unity for a smoother debugging experience. Check out our detailed guide now!