Skip to main content

2024.10.1b

This release of Hypernex brings a lot of small, but useful features for both developers, creators, and users! In this update, we also mainly focused on improving performance and will be continuing to work with that in the coming updates.

Changes

  • New Scripting API!
    • This brings a lot of changes to how events, objects, Player information, and plenty more is collected!
    • Most likely your code is broken, please be sure to read over the API changes and new documentation!
  • Added progress download for worlds and avatars!
  • Cameras can be used on Desktop!
    • Use Backspace to delete all cameras
  • Added PhysicsBody component
  • Added Light component
  • All TextMeshProUGUI components now have support for Emojis at runtime
  • Improved performance for AvatarCreator getting MainParameters
  • Improved performance for Volumes
  • Improved performance for Runtime
  • Improved GC for LocalPlayer
  • Improved GC for Init
  • Improved GC for AvatarNearClip
  • Added IPlayer interfacing for LocalPLayer and NetPlayer
    • This unifies some basic features such as Id and Download Progress
  • DefaultURLs now reference from default and your configuration
  • Fixed bug where you couldn't hear NetPlayers if they didn't have an avatar equipped
  • Fixed bug where audio would have a large delay to start
  • Fixed bug where NetCameras would not appear in world
  • Fixed bug where Unity would not follow 24hour clock settings
  • Fixed issue where Avatars would be placed far away from center
  • Fixed issue where Cobalt wouldn't download some media properly
  • Added Runtime.RemoveRepeatSeconds back
  • Added Player.Rotate back
  • Added Log(float, float) and Log(float2)
  • Avatar Scripts are now reloaded between GameInstance Join and Leave
  • Added Remove functions for Keyboard and Mouse
  • Added MessagePack Formatter for IL2CPP
  • Bumped Nexport to latest
  • Bumped kMirrors to latest

API Changes

Scripting API

The new scripting API optimizes how creators interface with Unity components. Here's an example difference

Before

// You would have to know the exact names
local items = [World.GetItemInRoot("myAudioPlayer1"), World.GetItemInRoot("myAudioPlayer2")]
for(let i = 0; i < items.length; i++){
let item = items[i]
// Get AudioListener #1
if(!Audio.IsValid(item)) continue
// Get AudioListener #2
Audio.SetVolume(item, 0.5)
// Get AudioListener #3
Audio.Play(item)
}
// Total GetComponents: 3 (calls) * 2 (items) = 6 calls

After

// Get the Handler
let world = instance.GetHandler("World")
// You can just cache and iterate through all children
let rootChildren = world.Children
for(let i = 0; i < rootChildren.length; i++){
let child = rootChildren[i]
// Get AudioListener #1
let audio = child.GetComponent(Component.Audio) // (or possibly new Audio(child) depending on poll result)
// If the component is null, the item doesn't have an AudioSource
if(audio == null) continue
audio.SetVolume(0.5)
audio.Play()
}
// Total GetComponents: 1 (calls) * [assume] 2 (items) = 2 calls

The new code makes it much easier to understand what each part of the code does, making it easier for new creators to start coding. There are also new features to Handlers to make sure that creators are given optimal methods and properties to work with. Finally, given the new component structure, the amount of GetComponent calls has drastically reduced. This is incredibly helpful for creators looking to optimize, especially when working with components in Update frames. Below is an example of before and after GetComponent calls, in a very basic way

Before

Runtime.OnUpdate(function()
UI.SetText(item, "Hello World!") --GetComponent called once every frame
end)

After

local Runtime = instance.GetHandler("Runtime")
local text = item.GetComponent("Text") --GetComponent called once
Runtime.OnUpdate(function()
text.SetText("Hello World!")
end)

Huge improvement for performance.

Disregarding Components, Handlers make many improvements to performance, especially with Garbage Collection and Disposals. For example, using Bindings before, they would never dispose the events, so once you created the event, it stayed. This was very poor, requiring the creator to (somehow) keep track of this. Now with Handlers, this is no longer an issue. For example, with Bindings, upon Reloading an Avatar, leaving an Instance, etc., events are automatically unregistered and properly disposed. This also heavily reduces memory usage, even more than we barely use.

However, with these changes come many breakages. All of LocalAvatar, UI, Runtime, Bindings, Audio, Video, Physics, NetworkEvent, ScriptEvents, and World have been replaced with components and handlers. Fortunately, it is easy to upgrade, lets take the following script which just sets the text to a user input on button click

Before

let buttonItem = World.GetItemInRoot("button")
let textItem = World.GetItemInRoot("text")
UI.RegisterButtonClickEvent(buttonItem, () => UI.SetText(textItem, "New Text!"))

After

// Copy the same code
// Create the World Handler with the same name
let World = instance.GetHandler("World")
let buttonItem = World.GetItemInRoot("button").GetComponent("Button") // Get the component
let textItem = World.GetItemInRoot("text").GetComponent("Text") // Get the component
// Change static to components, replace names (if needed), and remove item parameter!
buttonItem.RegisterClick(() => textItem.SetText("New Text!"))

All of the current docs have been updated, so be sure to check those out to make sure how to use the new scripting API! Happy upgrading!

Join Our Discord for More Support!

Here's a table of old classes and their corresponding handlers/components/classes

Old ClassNew ClassHandler or Component
LocalAvatarPlayers -> Player -> AvatarHandler -> Class -> Class
WorldWorldHandler
BindingsBindingsHandler
NetworkEventNetworkHandler
InteractablesInteractablesHandler
PhysicsPhysicsHandler
RuntimeRuntimeHandler
ScriptEventsEventsHandler
UIComponentsComponents
AudioAudioComponent
VideoVideoComponent
ReadonlyItemItemUse Item.IsReadOnly property
WorldPropertiesWorld -> PropertiesHandler -> Class