Inspiration

In many virtual worlds, lighting is static and lifeless. We were inspired by real-world smart home technology (like Philips Hue) and professional stage lighting controls. We wanted to give creators and players the power to change the mood and atmosphere of a space in real-time, directly within VR. Instead of a light just being a prop, we wanted to turn it into a dynamic tool for expression and interaction.

What it does

The Interactive Lamp is a fully functional, grabbable, and highly customizable light source for Horizon Worlds. A player can pick up the lamp and use their controller to:

  • Toggle Power: Turn the light on and off with a simple click of the index trigger.
  • Live-Edit Properties: Cycle through a menu of settings—including Hue, Saturation, Value, Intensity, Falloff Distance, and Spread—using the A/X button.
  • Fine-Tune Values: Adjust the currently selected setting by holding the B/Y button.
  • Activate Auto-Mode: A long-press on the trigger activates a beautiful, color-cycling "Auto Mode" that smoothly animates every property of the light for a dynamic ambiance.
  • Get Instant Feedback: All current settings are displayed on an attached Text Gizmo, which updates in real-time, serving as a user-friendly UI.
  • Auto-Return: If dropped or left behind, the lamp will automatically return to its original position, making it a reliable world asset.

How we built it

The project was built entirely within the Horizon Worlds platform, combining in-world objects with a powerful TypeScript script.

  • Core Components: The lamp is built from a parent Entity (made grabbable and physical), a child DynamicLightGizmo (the light source), and a child TextGizmo (the UI panel).
  • The Brain (TypeScript): The lamp.ts script is the heart of the project. It uses propsDefinition to create links to the light and text gizmos, allowing the code to control objects in the scene.
  • Event Handling: We used connectCodeBlockEvent to listen for player inputs like OnIndexTriggerDown, OnButton1Down, etc. This allows the script to react to the player's actions.
  • The Update Loop: A central function, onLight(), is responsible for taking all the script's internal variables (like Intensity, Hue, etc.) and applying them to the DynamicLightGizmo's properties using the API. This function is called every time a setting is changed, ensuring the light instantly reflects the new state.
  • Animation: The "Auto Mode" is powered by an async.setTimeout loop that repeatedly calls itself, slightly changing the light's properties each time to create a smooth, continuous animation.

Challenges we ran into

  • Complex Input Logic: Differentiating between a short press (toggle on/off) and a long press (toggle Auto Mode) on the same button required careful state management and the use of timers to detect how long the trigger was held.
  • UI in VR: Creating an intuitive menu system without traditional UI elements was a challenge. We landed on the "cycle-and-adjust" method using two buttons, which proved to be very user-friendly in VR. The real-time text feedback was crucial for making this work.
  • State Management: Juggling seven different editable properties and ensuring they looped correctly without going out of bounds required careful use of the modulo (%) operator and clear variable management.

Accomplishments that we're proud of

  • An Intuitive Control Scheme: We are proud of the single-trigger, dual-functionality (short vs. long press) that feels natural and easy to learn.
  • Creating an In-World "Property Editor": We successfully built a tool that allows players to edit the properties of an object in real-time, effectively creating a mini-editor within the world itself.
  • The "Auto Mode" Effect: The final color-cycling animation is visually stunning and demonstrates the power of simple, recursive functions for creating complex effects.
  • Modularity: The final product is a completely self-contained, drag-and-drop asset that other creators can use in their own worlds with minimal setup.

What we learned

This project was a deep dive into the DynamicLightGizmo API. We learned how to manipulate every scriptable property of a light source, from its on/off state to its color and shape. We also gained significant experience in advanced event handling, creating intuitive VR user interfaces with limited tools, and managing complex states within a script. Most importantly, it solidified our understanding of how to bridge the gap between editor-placed objects and dynamic, scripted behavior.

What's next for the Interactive Lamp

We see a lot of potential for expanding this concept:

  • Color Presets: Add a new setting to cycle through pre-saved color schemes like "Sunset," "Forest," "Cyberpunk," etc.
  • Audio Reactivity: Integrate the lamp with the audio system so it can pulse or change color in time with world music.
  • World Triggers: Allow the lamp to be controlled by other world events, such as a player entering a specific area or completing a task.

Built With

Share this project:

Updates