Overview
Doors are fundamental architectural elements that divide spaces and control player movement, making them an ideal gimmick as a first step toward bringing interactivity to your world. When doors open automatically or open/close through player actions, the world gains significantly more immersion.
This article explains the basics of animation, which is essential for implementing door gimmicks, and provides step-by-step instructions for creating the following two practical door types:
- Synced Automatic Door: Opens automatically when a player approaches and closes when they leave. The state is synchronized across all players.
- Synced Manual Door: Opens/closes when a doorknob or similar is clicked (
Interact), with the state synchronized across all players.
Step 1: Preparing the Door and Animations in Unity Editor
First, prepare the door model and animations to be controlled by UdonSharp.
1. Door GameObject Structure
- To make a rotating door work correctly, use a parent-child relationship for GameObjects. First, create an empty GameObject and name it "Door_Pivot." This becomes the door's rotation axis (hinge).
- Next, make the 3D door model a child object of "Door_Pivot." Adjust the local coordinates of the door model so that the rotation axis is at the edge of the model.
- By doing this, simply rotating "Door_Pivot" will make the door open and close realistically.
2. Creating Open/Close Animations
- With the
Door_Pivotobject selected, open the Animation window from Unity's menu: [Window] > [Animation] > [Animation]. - Press the "Create" button and create a new animation clip. Save it first as "Door_Open."
- Press the record button (red circle) to start recording the animation.
- At frame 0, register a keyframe for the
Door_Pivot'sTransform>Rotationproperty in its initial state (e.g., Y=0). - At frame 60 (1 second later), change the
Rotationto the door's open state (e.g., Y=90) and register a keyframe.
- At frame 0, register a keyframe for the
- Stop recording. You now have an animation of the door opening.
- Follow the same procedure to create a "Door_Close" animation (frame 0 is Y=90, frame 60 is Y=0).
3. Animator Controller Setup
- Right-click in the Project window and select [Create] > [Animator Controller], creating one named "Door_Animator."
- Double-click the created
Door_Animatorto open the Animator window. - Drag & drop the "Door_Open" and "Door_Close" animation clips from the Project window into the Animator window.
- In the "Parameters" tab on the left side of the Animator window, click the "+" button and select "Trigger" to create two triggers named "Open" and "Close."
- Draw an arrow (transition) from the
Entrystate toDoor_Close. This sets the door to be closed by default. - Draw a transition from
Door_ClosetoDoor_Open, select that transition, and set "Open" trigger inConditionsin the Inspector. - Draw a transition from
Door_OpentoDoor_Closeand set "Close" trigger inConditions. - Finally, add an
Animatorcomponent to theDoor_Pivotobject and assign the createdDoor_Animatorto theControllerfield.
Now you're ready to play the corresponding animation by calling the "Open" or "Close" trigger from UdonSharp.
Pattern 1: Synced Automatic Door
A door that opens when a player approaches and closes when they leave. When someone approaches, the door opens in all players' views through synchronization.
Trigger Setup
- Add a
Box Collidercomponent to theDoor_Pivotobject. - Adjust the size of the
Box Colliderto cover the area where you want to detect a player approaching the door (the space in front of and behind the door). - In the
Box Collider's Inspector, check theIs Triggerproperty. This makes it function as a sensor that detects entry rather than a physical wall.
Script: SyncedAutoDoor.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
public class SyncedAutoDoor : UdonSharpBehaviour
{
[Tooltip("Assign the Animator for the door to control.")]
public Animator doorAnimator;
// Sync whether someone is inside the trigger
[UdonSynced]
private bool isSomeoneInside = false;
// Locally count players inside the trigger
private int localPlayerCount = 0;
// Called when a player enters the trigger area
public override void OnPlayerTriggerEnter(VRCPlayerApi player)
{
// Only process if the local player entered
if (!player.isLocal) return;
localPlayerCount++;
// If you're the first one entering, take ownership and update state
if (localPlayerCount == 1)
{
Networking.SetOwner(Networking.LocalPlayer, this.gameObject);
isSomeoneInside = true;
RequestSerialization();
UpdateDoorState();
}
}
// Called when a player exits the trigger area
public override void OnPlayerTriggerExit(VRCPlayerApi player)
{
if (!player.isLocal) return;
localPlayerCount--;
// If you're the last one leaving, take ownership and update state
if (localPlayerCount == 0)
{
Networking.SetOwner(Networking.LocalPlayer, this.gameObject);
isSomeoneInside = false;
RequestSerialization();
UpdateDoorState();
}
}
public override void OnDeserialization()
{
UpdateDoorState();
}
private void UpdateDoorState()
{
if (doorAnimator != null)
{
if (isSomeoneInside)
{
doorAnimator.SetTrigger("Open");
}
else
{
doorAnimator.SetTrigger("Close");
}
}
}
}
Unity Setup
- Create
SyncedAutoDoor.csand assign it to the Udon Behaviour attached to theDoor_Pivotobject. - Drag & drop the
Animatorcomponent also attached toDoor_Pivotinto theDoor Animatorfield.
Pattern 2: Synced Manual Door
A door that opens/closes when the door or doorknob is clicked.
Script: SyncedManualDoor.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
public class SyncedManualDoor : UdonSharpBehaviour
{
[Tooltip("Assign the Animator for the door to control.")]
public Animator doorAnimator;
[UdonSynced]
private bool isOpen = false;
void Start()
{
UpdateDoorState();
}
public override void Interact()
{
Networking.SetOwner(Networking.LocalPlayer, this.gameObject);
isOpen = !isOpen;
RequestSerialization();
UpdateDoorState();
}
public override void OnDeserialization()
{
UpdateDoorState();
}
private void UpdateDoorState()
{
if (doorAnimator != null)
{
if (isOpen)
{
doorAnimator.SetTrigger("Open");
}
else
{
doorAnimator.SetTrigger("Close");
}
}
}
}
Unity Setup
- Create
SyncedManualDoor.csand assign it to the Udon Behaviour on the object you want players to click (the door itself, or a separate object created as a doorknob). - Verify that the object has a
Colliderattached and that the Udon Behaviour'sInteraction Textis set. - Drag & drop the
Animatorcomponent from theDoor_Pivotobject into theDoor Animatorfield.
Summary
- The core of door gimmicks is the integration of Animator Controller and UdonSharp. You call
SetTriggerfrom UdonSharp to play animations. - Automatic doors use
OnPlayerTriggerEnter/Exitand aColliderset as a trigger. - Manual doors use the
Interactevent. - In both patterns, by managing the open/close state with an
[UdonSynced]variable and callingRequestSerialization()when the state changes, you can synchronize door movement across all players.
Doors are an ideal subject for learning the key elements of UdonSharp gimmick creation: animation, triggers, and synchronization. By applying this knowledge, you'll be able to create various dynamic objects such as moving floors and hidden passages.