-
Notifications
You must be signed in to change notification settings - Fork 2
Guides
If you would like to see other examples on how to create different systems using CyanTriggers, be sure to check the provided example scenes. CyanTriggerExamples/Examples.unity You can also download the CyanKey example world for implementation of a simple escape room.
A common action in many worlds is a Mirror toggle. The simplest form of this is an Interact event with a toggle action.
This is the simplest way to make a local only Mirror toggle. GameObject.ToggleActive is a Custom Action though. If you would like to make this using non custom actions, you can do it manually by getting the value, flipping it, and setting it back.
In this example, there are 4 actions.
- Local bool variable. - This will be used to store the state of the GameObject to toggle
- GameObject.Get activeSelf - This will get the current state of the GameObject and store it in the local variable
- bool.UnaryNegation - This will flip the value of the local bool variable.
- GameObject.SetActive - This will set the state of the GameObject to the variable.
Getting the player’s name is something that was not possible in SDK2. It can be done easily in SDK3 in CyanTriggers. Once you have the player you want, you can get the player name by calling VRCPlayerApi.Get displayName.
In this example, OnPlayerJoined provides the player that joined the instance. Using that, the player name can be fetched and printed to the console. This example has three actions:
- Local string variable - This will be used to store the player’s name
- VRCPlayerApi.Get displayName - This will take the input player object and get the display name and store it in the local variable
- Debug.Log - This will then print the local variable to the console, which stores the player’s name.
In SDK2, OnKeyDown and OnKeyUp were direct events. This is not the case for SDK3 and CyanTriggers. If you would like to perform actions when a key is pressed, you will need to check on update if the key was pressed on this frame.
In this example, the main points are that the event needs to be in an update loop. There are three events that should be used: Update, LateUpdate, or FixedUpdate. Inside the event itself, you need to check Input.GetKeyDown. There are other input actions you can use as well.
In SDK2, Events would not execute if the GameObject was inactive or if the VRC_Trigger was inactive. This is no longer the case in Udon with CyanTriggers. If you would like to prevent an action from happening in these cases, you need to manually check and return from the Event early. To make things easier, there is a single Action that can do this for you called ReturnIfDisabled. This can be added anywhere, but to act like SDK2, it should be the first action in the event.
If you would like to understand what the ReturnIfDisabled action is doing, you can see the expanded version below:
This guide is also available as a video tutorial.
With synced variables, it is easy to create a synced toggled object for your world. Synced variables paired with the OnVariableChanged event lets you easily handle when a variable has been updated on any client.
In this example, you can see everything needed to sync a toggle for all players, including late joiners. There are three sections to this, Variable definition, Modifying the variable, Handling variable changes.
In the example, there is only one variable defined for this CyanTrigger. This variable is called “value”. It is of type bool and it is set to sync. An important part of this is that it is set to the default state of the object. In the scene, the toggled object is already active, thus the variable should also start active. If not, the first interaction modifying it will not change for players properly.
In this example, I am using the Interact event to modify the variable state. This can be any event, but Interact is easy to demonstrate. When modifying a variable, you must be the owner of the object inorder to change the value. With this in mind, the first action in the Event is Networking.SetOwner. This will make the local player the owner of the object, allowing us to change the value of the variable. The next action then modifies the variable’s value. For this example, I am flipping the bool value using bool.UnaryNegation and storing it back in the same variable.
OnVariableChanged is the event you should use to handle values changing for variables. This will check when a variable’s value has changed from a local action, or from a synced variable changing. When this Event executes, you have the updated value in the variable and can use it for additional actions. The OnVariableChanged event also provides a variable containing the old value. In this example, I am taking another object, called “Thing”, and setting it’s active state to the value of the variable.
CyanTriggers come with some example prefabs which show how to track different parts of the player.
- PlayerBaseTracker - This prefab will update it's position every frame to be the location of the local player's base position. This is the value returned by VRCPlayerApi.GetPosition and VRCPlayerApi.GetRotation
- PlayerBoneTracker - This prefab will update it's position every frame to be the location of the specified local player's bone. Use the global variable to select which bone to track.
- PlayerTracker - This prefab will update it's position every frame to be the location of the specified local player's tracker. Use the global variable to select which item to track. There are 3 options: Head, left hand, and right hand.
Randomization in CyanTriggers is currently not as easy compared to SDK2 VRC_Triggers. The are multiple steps to randomizing what actions happen. THis guide requires understanding of Special Actions.
First, you need to get a random value. In the example image, there are two actions for this. The first is creating a local float variable to store the random value. The second is using the Random.Get value action and storing it in the local variable. Random.Get value will return a number between 0 and 1.
Once we have a random value, we need to check it for each probability per action group. This can be done with the If and ElseIf actions. The first action must be an If action. In the condition, we want to check if the random value is less than the first probability. In the example, the first probability is 0.25 or 25% chance. To check for this probability, the float.LessThan action is used. In the ConditionBody, add all the actions for this random probability. Using Custom Events and SendCustomEvent can help in organizing everything as it separates the randomization selection from the randomized actions. For all other randomized actions, use the ElseIf action. These will be setup the same way, but the probability will need to be the sum of all previous probabilities so far plus the new probability we want. In the example, the second randomized action group also has a probability of 0.25 or 25% chance. To check for this, the random value needs to be between 0.25 and 0.5. The first if handles when the value is less than 0.25, so this check only needs to verify the value is less than 0.5. For the last probability, the Else special action can be used. Since there will be no other checks after it, the remaining portion can be used as the last probability. In the example, the first two handle for all values less than 0.5, which means the last action has a probability of 0.5 or 50% chance.
In order to sync the randomization, you will need to sync the results, not the overall action. This can be done by first setting the event to local. For every action you want everyone to perform, you will need to move the actions to a Custom Event, and broadcast that event. If you are dealing with data, another option is to use a synced float value, and handle checking what random action to take in the OnVariableChanged event for that float.