# Migration to v0.4.0

{% hint style="warning" %}
Since version 0.4.0 UdonToolkit requires UdonSharp 0.18 and above!
{% endhint %}

### Migration Guide

* Grab the [latest U# release here](https://github.com/MerlinVR/UdonSharp/releases) and import that first!
* Create a new empty scene and open it
* Click File -> Save Project
* Download the [latest UdonToolkit release here](https://github.com/orels1/UdonToolkit/releases)
* Remove the UdonToolkit folder completely while you are in that test scene
* Import the new UdonToolkit and wait for everything to compile
* Open `Edit` -> `Project Settings` -> `UdonSharp` and in the `Default Behaviour Editor` select `UdonToolkit Editor`
* Open your scene again and everything should work as expected

{% hint style="warning" %}
If you are using the **CameraSystem** - it is recommended to check that the `Start Sphere` and all the `Sphere` objects inside `VR Controls` have `Area Trigger` program assets assigned, unity seems to occasionally lose references to that particular asset
{% endhint %}

You will notice a `Legacy` folder inside UdonToolkit now which hosts all the old controllers and the legacy editor

### Controller Migration Guide

{% hint style="info" %}
You can take a look at all the U# behaviours in the **Misc** folder to see how you can use UdonToolkit now
{% endhint %}

Starting with v0.4.0 you don't need controllers anymore, and you can use all the UdonToolkit's attributes directly in the U# code!

There are some small differences mainly centered around Udon's limited support for things like Enums and cases where you want to perform some complex editor logic.

> All variables that you want to use UdonToolkit attributes with must have a `[UTEditor]` attribute on them that is last in the group

```csharp
// This will work
[SectionHeader("General")] [UTEditor]
public bool active = true;

// This won't work
[SectionHeader("Some other group")]
public float test = 0.01f;
```

This is due to some limitations of unity PropertyDrawers that do not allow proper modifier stacking

{% hint style="info" %}
Popup attribute now has new udon-friendly versions that use string names instead of Enums
{% endhint %}

```csharp
// Using an Animator source type to auto fetch Triggers from the `animator` variable
[Horizontal("AnimationTrigger")] [Popup("animator, "@animator", true)] [UdonPublic]
public string somePopupVar;
```

More examples in the [Popup attribute documentation](https://github.com/orels1/UdonToolkit/wiki/Attributes#popup)

{% hint style="danger" %}
If you want to execute editor only code in case of OnValueChanged, etc. you need to use directives
{% endhint %}

It is pretty rare that you'll have to use `#if`, but sometimes its unavoidable, especially when you want to use things like [OnValueChanged](https://github.com/orels1/UdonToolkit/wiki/Attributes#onvaluechanged) attribute.

Basically the logic behind this is as follows: you should use `#if !COMPILER_UDONSHARP && UNITY_EDITOR` if:

* You want to work with methods and types not exposed to udon
* You want to execute some logic in editor outside of playmode

In other cases - you should never need `#if` around your attribute related code

```csharp
[OnValueChanged("ToggleLights")] [UTEditor]
public bool lightsActive;

#if !COMPILER_UDONSHARP && UNITY_EDITOR
public void ToggleLights(SerializedProperty value) {
  // get the value of expected type first
  var val = value?.boolValue;
  if (value) {
    // do something here
  } else {
    // do something here
  }
}
#endif
```

As usual, check behaviours in the `Misc` folder as a reference to how things should be built. [UniversalAction](https://ut.orels.sh/behaviours/misc-behaviours#universal-action) is a good overall example.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ut.orels.sh/extras/migration-to-v0.4.0.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
