Yeah, but it's 2026 now so it's betterer. :D
Anyway...
Personal Pen
- Players can now spawn a personal pen to draw anywhere with various customization options such as thickness, smoothness, and visibility
- The Pen color syncs with your chosen player color
Chatbox now supports multiple languages!
- We've updated the fonts used in chatbox (and a few other places) with more languages, including:
- Japanese
- Korean
- Simplified Chinese
- Traditional Chinese
- ...and Emojis
- If your language is not supported, please let us know!
Dynamic Bone & Magica Cloth 1/2 Improvements
- Wind interaction is now unified across all bone movement solutions for worlds with Wind Zones (Unity, Magica 1, Magica 2)
- Bones with either component applied to them will no longer snap or jitter when teleporting as well
YouTube now works again in video players
- ...until it doesn't (thx yt)
- Some players may still be affected by ongoing changes to YouTube over time - we will continue to address these as much as possible
Prop Distance Hiding
- Props may now be hidden at a distance - configurable in Content Filter > Prop Filter
- Both Avatar and Prop distance hiding is now available at the top of their respective pages for easy access
Pointers & Triggers
- The collision system for Pointers and Triggers has been entirely replaced
- This solution should provide more performance and reliability overall
- Existing content will be automatically converted at runtime
- Read more on these changes below the General Changes section
General Changes
- Added continuity versioning to player movement packets and handling for avatar dynamics (Dynamic Bones, Magica Cloth 1 & 2)
- When teleporting or respawning, dynamics on your avatar and remote player movement will no longer simulate or interpolate from the prior position to the new position
- This should result in a seamless "snap" to the new position without any observable in-between movement
- This only happens if the teleport was called with interpolate set to false
- When teleporting or respawning, dynamics on your avatar and remote player movement will no longer simulate or interpolate from the prior position to the new position
- Added Copy Avatar button to player selection page,
- Added HUD voice disconnected message for now
- If you encounter this message please let us know! We're hunting bugs!
- Added Movement Lock Toggle to SteamVR bindings
- While active, movement and look inputs will be ignored, and your body heading rotation will stick
- This is primarily for laying down in Half-body when you don't want to move by accident via joystick or by turning your head and having your body swing out
- Added Prop Distance Hider to Prop Filter page
- To ensure things hide as-expected, each "part" of a Prop has bounds associated which is used for distance sampling
- This means the distance to hide a Prop takes into account how big the Prop is
- Note: Some Props may misbehave when hidden as they weren't built with it in mind. The hiding logic does its best to forward playback of components like Animators and Audio Sources to prevent desync, but this hand-holding behaviour may be removed if it proves to cause more issues than it addresses.
- To ensure things hide as-expected, each "part" of a Prop has bounds associated which is used for distance sampling
- Added retrying to load videos when they fail to load, it will retry 5 times 1 second apart. This should address a lot of old YouTube Error: No Error
- yt-dlp was being able to resolve the videos properly, but the AVPro for some reason sometimes is failing to load them
- Added "Show Own Gizmos" in runtime gizmos settings
- Added support for batched voice server flow control (more betterer)
- Adjusted scaling of splash screen to hopefully fit better on all displays
- Adjusted the min limit for voice falloff distance to 1 meter
- Changed dropdown hover colours, they'll now use player colours if enabled
- Changed texture updating from our implementation to VLC-Unity's TextureHelper
- Changed the CVR Utilities page to Toolbox page
- Cleanup unneeded player join/leave event registration for UILib on first world join (UILib mod leftover)
- Corrected TTS audio slider tooltip
- Deleted Fish <><
- Fixed an issue where a Dynamic Bone with multiple roots defined would only apply dampening, elasticity, stiffness, inert, friction, and radius curves to the first root
- Fixed an issue where the video player would stop loading videos completely after attempting to load a URL that would result in too many videos and would time out
- Fixed an issue where Unity UI would no longer receive input events if you last interacted with your left hand prior to VR-switching to Desktop
- Fixed an issue with ContentCloneManager.MakeReadableMeshCopy exploding when encountering mesh which vertex stream dimensions total bytes was not a multiple of 4
- This sort of mesh is completely fine until you want to generate it at runtime...
- Fixed AvatarVoicePoint reference transform generating at the wrong location (was sampling the view position)
- Fixed comms sending Flow Control packets before we're authenticated
- Fixed continuing a transition that hasn't started, something something nak problem lol
- Fixed Ctrl not force showing the overheads when close to the player
- Fixed current state of the video player description not showing the Loading Video and Playback Finished states
- Fixed CVRWindZoneManager leaking tracked zones when they were destroyed
- Fixed instance group selection dropdown not scrolling and not closing when clicking the top
- Fixed LibVLC not changing hardware decoding on setting change
- Fixed LibVLC not respecting hardware decoding setting at startup
- (Thanks to Kneesox for noticing these issues)
- Fixed live streams on the Video Player wrongly triggering the Finished Playing event right after triggering the Start Playing
- Fixed material instantiation being broken
- Fixed onsettingschanged callbacks being fired on startup when loading saved settings from disk unintentionally
- Fixed personal mirror not writing to settings when toggling world anchored
- Fixed remote avatar pointers and dynamics colliders generating incorrectly if the avatar animators default state animated the avatars scale away from the initial scale
- Fixed settings being wiped when they fail to apply at startup
- Fixed soundcloud audio on the video player stuttering every 10 seconds
- Fixed the inconsistency on the Underlay across the newly added CJK ChatBox fonts
- Fixed the jitter that sometimes could be seen on player's ChatBoxes above their heads
- Fixed the VideoPlayer displaying Error: No Error when there was an actual error (although AVPro made the errors so generic that is basically the same as not having them)
- Fixed UILib menu header not changing properly if mods don't have a set menu title/subtitle
- Fixed wind interaction for Dynamic Bones
- Fixed YouTube videos not working
- Hopefully improved handling of voice connections breaking
- Implemented the first iteration of the Personal Pen, available from the Toolbox page in the Quick Menu
- By default, you will only see pen trails from friends, and your trail will use your player color (this will become configurable in the future)
- Each trail point is explicitly synced to ensure drawings are the same across all clients
- The Personal Pen Configuration page allows adjusting the Trail Visibility Radius, which limits how far from a pen its drawing will be visible to reduce intrusive drawings or visual clutter
- Players which you have force-disabled Props for will also have their trails disabled
- The Quick Menu allows undoing segments or clearing all trails, and the back of the pen can be used as an eraser
- Further development will continue after GS2 is completed due to several networking-related blockers
- (this feature is being merged now so it is easier to integrate into GS2 during development)
- Made Avatar Advance Settings profiles save with pretty print to make them easier to modify in a text editor
- Made GS connection actually track and handle ping timeouts
- Made the local "grab" pointer logic the same as remote clients
- Now the left hand grab pointer will activate in Desktop mode for example, as it is based on gesture value instead of grip input locally
- This matches the behaviour that it has always been on remote clients
- Moved init for bunch of systems until after game settings load
- This fixes PropDistanceHider and PenTrailManager settings not applying on startup
- Moved the Custom Shaders filter dropdown to under Removables category
- Moved where Avatar Advanced Settings profiles are stored
- The folder has moved from your game installation to AppData/LocalLow/ChilloutVR/ChilloutVR/ alongside your game configs,
- Profiles will be migrated to the new folder at startup and smartly merged to prevent duplication or issues with differing profiles among multiple game installs
- Refactored post processing handling in Worlds:
- Fixed an issue where post processing effects which were disabled at build time would be re-enabed by the user configurable post processing graphics settings
- This would cause effects which the world never intended to actually utilize to be force enabled
- Post processing effects which are incompatible with the multi-pass rendering legacy mitigation are now force disabled while the mitigation is active
- Fixed an issue where post processing effects which were disabled at build time would be re-enabed by the user configurable post processing graphics settings
- Removed the Wind Interaction setting as it only applied to Dynamic Bones
- You can still filter Wind Zones in the Content Filter
- Removed Touch Triggers from Avatar/Prop filters
- Removed Unity Wind Zones from Avatar whitelist
- Reverted taskification of LibVLC VideoUpdate function as it didn't do anything useful
- Reworked internal nameplate and chatbox logic, this will cause some mod incompatibilities!
- Significant refactor to content filtering
- Filtering internally is significantly cleaner, please check your content and let us know if something explodes!
- Fixed some unity events not being properly sanitized
- Added internal tool to detect and prevent newly unsanitized events from being exposed
- Big thank you to Benjamin Zehowlt for bringing this issue to our attention!
- Stop voice server reconnection from running endlessly
- Reconnection attempts abort after 30 tries, gradually backs off every 5 attempts
- Swapped portals and video player to NotoSans with CJK fonts
- Tweaked the finger curl measurement for driving the grab pointer to be less strict and take into account more fingers
- Tweaked Viseme Loudness lipsync measurement to address 2s bounce after stopped speaking
- Unified existing wind components for Magica Cloth 1, Magica Cloth 2, and Unity Terrain
- When loading existing content if one of these existing wind components are found a CVRWindZone will be created and best-effort match the existing configuration
- The CVRWindZone handles making the wind work across Magica Cloth 1, Magica Cloth 2, Dynamic Bones, and Terrain
- For Dynamic Bones the CVRWindZone will try to replicate Magica Cloth 2 wind force accumulation behaviour
- The zone with the smallest volume will apply a base force and up to three additive zones will apply an additional force (depending on registration order)
- Updated default settings for ChatBox and graphics options
- Updated default settings for portal drop notification and pen trail visibility
- Updated library acknowledgement splash screen
- Updated to latest LibVLC for Unity release
Pointers & Triggers
The collision system backing pointers and triggers has been replaced with a new system which does not depend on Unity colliders. This should provide noticeable performance and reliability improvements while also giving us the ability to expose new functionality in the future.
To spare the technical details, here are the most important things:
- Existing triggers and pointers will automatically be best-effort converted to the new system. For testing purposes you can disable this conversion in the Experimental settings.
- Changing this setting will require you to reload all affected content to generate the original Unity collider-based pointers and triggers.
- Breakage of some unintended setups is expected, but some of these setups will be converted as well due to how widespread their usage was.The following setups will be converted:
- Pointers without a collider on the same object, or ones with a Sphere, or Capsule collider added.
- Box colliders or Mesh colliders will be best-effort wrapped in a Capsule collider.
- Triggers without a collider on the same object, or ones with a Box, Sphere, or Capsule collider added.
- Mesh colliders will be best-effort wrapped in a Capsule collider.
The following unintended setups will break:
- Pointers and Triggers on same game object which wouldn't interact with each other unless the GO layer changed during asset filtering.
- This hack was used prior to the local interaction option being added to triggers, and depended on component order, as well as the layer the GO was uploaded on.
- Triggers & Pointers using mesh colliders or multiple colliders which only worked due to being built on Unity's trigger system.
- Adding your own collider shape to a Trigger was never an intended use-case and usually introduced unexpected behaviours.
- Internally, it still generated the box shape (even when scaled 0,0,0), leading to you receiving OnEnter/OnExit/OnStay events for every collider you touched on that object.
- Adding your own collider shape to a Trigger was never an intended use-case and usually introduced unexpected behaviours.
- Pickups or Interactables which depended on the generated collider from a Pointer/Trigger to function will no longer work as Pointers/Triggers do not generate Unity colliders anymore.
- Explicit pickup/interaction colliders on the same object as a Pointer/Trigger, which would end up being used by the Pointer/Trigger likely by accident, may also not function as before.
As part of this conversion any Unity collider on the same object of a converted Pointer/Trigger will be disabled. In the case of a collider likely being shared between a Pointer/Trigger and an Interactable/Pickup/PhysicsInfluencer, the Unity collider will stay enabled. If you believe you have an intended setup which does not convert properly please report it on the issue tracker.
That all sounds like a mess, so here are the cool things this brings:
- Added new auto-generated pointers:
- Head: Head
- Torso: Torso
- Left Hand: Hand, LeftHand, Grab (when grabbing)
- Right Hand: Hand, RightHand, Grab (when grabbing)
- Left Foot: Foot, LeftFoot
- Right Foot: Foot, RightFoot
- Voice Point: Mouth
- Left Fingers:
- Index: Finger, LeftIndex
- Middle: Finger, LeftMiddle
- Ring: Finger, LeftRing
- Little: Finger, LeftLittle
- Right Fingers:
- Index: Finger, RightIndex
- Middle: Finger, RightMiddle
- Ring: Finger, RightRing
- Little: Finger, RightLittle
- You may notice how each one has multiple tags you can look for, which can be exposed in the future :D
- Improved the fitting of the auto-generated pointers
- Made collision tags not case sensitive
- Tweaked the anti-sync fighting checks for Spawnable Triggers:
- If the pointer colliding with the trigger is on a Prop:
- Will apply sync value if we are either actively syncing or the last person to sync the prop with the trigger on it
- Actively syncing means we are holding a pickup have an active attachment
- Will apply sync value if we are either actively syncing or the last person to sync the prop with the trigger on it
- If the pointer colliding with the trigger is on an Avatar:
- Will always apply sync value if this sender is on our own avatar
- If the pointer colliding with the trigger is part of the World:
- Will apply sync value if we are the one that is the sync owner of the prop with the trigger on it
- Additionally, this new collision system returns only one collision event in the case of multiple overlapping pointers
- This means that all clients, as long as they see the same collision result on their side, will correctly figure out who is meant to apply the synced value
- This only works as expected if all users in the instance who have the prop shown have the new collision system enabled!
- This means that all clients, as long as they see the same collision result on their side, will correctly figure out who is meant to apply the synced value
- If the pointer colliding with the trigger is on a Prop:
- Triggers will now update every frame instead of in physics tick
- This will be best observed locally as the end result still needs to be networked with the current implementation
- OnExit trigger tasks will now reliably fire
- Performance in heavily packed Gravity/Fluid Volumes, (or other setups which spam Unity colliders), should now be much better due to Pointers/Triggers no longer spam-triggering them
- There is also a bunch more additions/improvements already built and functional that can be exposed in the future
Due to implementation reasons, some new limits on Pointers/Triggers are needed. These limitations have been made as flexible as possible to accommodate the usage of Pointers/Triggers we found.
- Introduced a dynamic per-content limit for Pointers/Triggers:
- Avatars are limited to 256 active at a time
- Props are limited to 64 active at a time
- The rest are allocated for the World up to the 4096 total scene limit
- These limits may be changed in the future, so please let us know if you run into any issues with uploaded content!
- Introduced a 16-type limit on Pointers/Triggers
- Specifically, this applies to the types or specific pointers set for filtering on Triggers
- Particle pointers will only evaluate two particle collisions a frame (and also count as 2 active pointers)
- These still need to generate a Unity trigger collider due to how they work and are expensive, please use these sparingly
Game Server 18.5.6
- Extensive cleanup and refactor of voice server
- Changes are still very much ongoing with this and will be touched as things happen
- This rework was started mainly to prep voice for the changes needed for GS2, but it made sense to bring em here!
- Adjusted handling of flow control packets when user first connects, this may resolve flow control packets going missing in some cases
- Fixed an issue where reconnecting could put you into a half connected state where others can hear you but you can't hear them
- Mitigated issue where GS can get into a state where users fail to authenticate properly and aren't cleaned up correctly
UILib Changes (for mod developers)
- Fixed AddCustomEngineFunction building a new function and registering an engine.on for functions it already handled
- This would lead to an exponentially-growing hitch when UILib would regenerate these elements
- Fixed CustomElement not marking itself as generated
- Fixed CustomElement not unregistering itself as a SubElement of its parent
- Fixed UpdateIcon setting the BackgroundSize/BackgroundRepeat when it wasn't needed
- Made OnOpenedPageEvent and OnBackActionEvent change the menutitle/subtitle if it's not null
- Made QMUIElement properties only send to cohtml if the value is different
- Removed all click and hover sound handling from Quick Menu JS and made the common Scroll Handler JS handle it instead
- This fixes elements in the Quick Menu not using the template system not having hover or click sounds (as it would throw due to undefined function)
- Fixed UILib not calling OnPageClosed and OnPageOpen when switching tabs
- Added Page.IsThisPageOpen to UILib
- This check will ONLY be true if the given page is visible
- IsVisible checks if the root page is open which isn't useful in some situations
- Fixed root pages having no default MenuTitle
- Fixed empty MenuSubtitle not applying to the menu header
- UpdateTitle now sets a default "No Title" and empty subtitle if the respective variable is null or empty (0 length)
- Added cycle button component to UILib
- Added OnHeld support to ToggleButton component
- Moved OnHeld action to QMInteractable base class, if you used this you will need to recompile your mod!