Skip to main content



There are two ways to setup your UdonSharp scripts to be a plugin for ProTV.

The first way is for if you don't have any existing script and want to make a new one. This way is simpler and comes with a built-in inspector to make things easier.
Simply just make a new U# class that inherits from the TVPlugin class and then call the base.Start(); method in your start method as the first thing.
Then to receive the events, just add them as a public override method. (You can checkout the full list of events further down) Here's what that will look like:

public class MyCustomPlugin : TVPlugin
// optional priority override, default is 0
// if you want your plugin to be higher priority, reduce the number, eg: -15
public override sbyte Priority => 10;

public override void Start()
if (init) return; // prevent start from being called accidentally more than once.
base.Start(); // sets up all the TV stuff.

// Put all your other start code here.

public override void _TvMediaReady()
UnityEngine.Debug.Log($"Url has been successfully loaded: {OUT_URL}");

The second way is if you are trying to integrate an existing script into the ProTV ecosystem, you can handle the plugin registration yourself. Just add a TVManager field to your class and call the _RegisterListener method in your Start method:

public class MyExistingClass : MyCustomBaseClass
[SerializeField] private TVManager tv;
private bool hasTV;

private VRCUrl OUT_URL;

private void Start()
// some other of your existing code here

if (tv == null) tv = GetComponentInParent<TVManager>(true); // optional search for convenience.
hasTV = tv != null; // caching the null check for performance is recommended.
if (hasTV) tv._RegisterListener(this, 10); // the register with an optional priority value
// The priority value determines the order in which the plugins are called when a listener event is triggered.
// For more methods and information regarding the listener API, you can examine the ArchiTech.SDK/Runtime/ATEventHandler.cs class
// specifically the USharp API region.

// some other of your existing code here

public void _TvMediaReady()
UnityEngine.Debug.Log($"Url has been successfully loaded: {OUT_URL}");

(More information about the OUT variables in the Core Architecture Doc page)


For UdonGraph scripts, this is done with the following:

  • Create variable of type UdonBehavior to assign the TVManager instance to it. Let's call it TV.
  • Create another variable of type UdonBehavior and make it not public. Let's call it SELF.
    • This makes it automatically fill with the custom behavior's own reference, which is exactly what we need.
  • Optionally, also create a variable of type int and call it PRIORITY.
    • Set the default value of PRIORITY to whatever you want (for example 10)
  • Drag the SELF, TV, and PRIORITY variables into the graph to produce GET nodes.
  • Create node with parameters: UdonBehavior -> SetProgramVariable [ TV, "IN_LISTENER", SELF ]
  • Create node with parameters: UdonBehavior -> SetProgramVariable [ TV, "IN_PRIORITY", PRIORITY ]
  • Create node with parameters: UdonBehavior -> SendCustomEvent [ TV, "_RegisterListener" ]
  • Create node: Events -> Event Start
  • Connect the Start event to the SetProgramVariable nodes and then connect SetProgramVariable to the SendCustomEvent node.
  • Done. Here's what that looks like in the graph:
    Udon Graph showing how to register a behavior with the TV

Now that your behaviour is connected as a listener, you can start processing the TV events. Checkout the TVPlugin Scripting API for the full list of events.