Frooxius Notes

From Neos Wiki
Jump to navigation Jump to search

Presented below are a section of notes copied from public conversations between Froox and the Neos community. They share useful hints and tips and answers to questions which may otherwise get lost. Eventually we will adapt these notes into full blown documentation but for now they may be helpful to you in the impromptu manner presented here. If you'd like to add/edit any entries please do so.


Render Queue Values

[11:04 AM] ToMo (DelVR): Heyo, doing some User interface design in Neos and in desperate need of render queue values, is this documented anywhere?

[11:06 AM] Frooxius: Hello! Neos is using the same Render Queue values as Unity, so you can use their reference for this.

[11:06 AM] ToMo (DelVR): Ah that's great! Cheers Froox

[11:06 AM] Frooxius: Essentially 2000 is opaque, 2450 alpha clip, 3000 transparent.

[11:06 AM] Frooxius: Some materials use a bit different ones though to get around certain issues.

[11:07 AM] ToMo (DelVR): Got it :poi_hisalute:

Computing Look Rotation

Frooxius on 2020-01-08: You can compute the rotation for look at very easily. Subtract global position of the looking object from the target, transform that as direction into the parent's space and then feed that to the LookRotation node to create a quaternion.

Driven Nodes Synchronization

The way Neos works is that anytime you make a change to any part of the data model (e.g. change position field or color) the change is synchronized from the person who changes it to everyone else.

However when you drive a field, you're essentially telling the system "Don't sync this value, it can be computed from other values/data that are synced", so everybody computes their own version on their end and saves a lot of network traffic.

Normally this works fine. But if you use the value itself in the computation (e.g. when simulating movement, you take the previous position and alter it), this is a problem, because you're using driven (non-synchronized) value to determine the new one. Any subtle differences in the computation will cause it to drift between users. This is a divergent feedback loop.

In such scenario you'd just use the write node to write a new value on the user controlling the vehicle for example and let Neos sync the new state to everyone else.

You can also have convergent feedback loops. SmoothLerp is actually example of one. It takes the existing value as input, new target and time. Even with subtle differences in calculation, it's still going to end up the same (new target, which is synchronized) value for everyone, so the feedback loop is ok in such scenario.

Gray Fog Volumes

@GearBell Switch it from Additive to Alpha. Then set the base color to gray with zero alpha (e.g. [0.5, 0.5, 0.5, 0] and the accumulation color to just alpha (e.g. [0, 0, 0, 1]). That way you have a static color whose alpha is being accumulated.

Child Order and Order Offset

@LeonClement Neos doesn't guarantee child order unless you specifically force it to. You can use the OrderOffset property to shift them around for now, make sure they all have one assigned, otherwise it'll default to sorting by allocation ID's when order is requested. Alternatively you need to specifically scan for the child you want, rather than depending on it being one with particular index.

PBR Material Textures

Aegis 2019-12-16:

   The metallic roughness map is comprised of the metallic which ranges from white(metallic) to black (non metallic), 
   the roughness using the alpha channel is from completely transparent(rough) to opaque(smooth)

Frooxius 2020-01-29:

   If you're using the PBR workflow then a lot of it will translate, but you have to make sure they're correct. 
   In Neos specular maps are combined with the gloss map, which is in the alpha of the specular.
   If you're using roughness map then you need to invert it to get smoothness.

Asset Reuse and Deduplication


Yes. The assets are hashed. If there's already one with the same signature uploaded, then it won't upload it again. This applies for caching too. E.g. two worlds by different creators who share assets will use the same cache entry. [1]

World Overwrite

From the patch notes for build 2020.5.10.1362

- Reimplemented world overwrite functionality with the new context menu - simply hold a world orb and click on another world orb (that you can write permissions for) and it will offer overwrite option (requested by @Nexulan)

Color Tooltip uses camera


The color tooltip is using a camera to average out color, so it's a bit expensive approach. It's only rendering 4x4 pixels, but it'still doing scene culling and processing the geometry, so I'd be careful with using that, the performance will degrade if that's used in a complex world on many avatars. [2]

KFC Opt-Out/In

From the patch notes of (September 1, 2019)

- Added way to opt out of KFC (requested by @GearBell )

-- To opt out, open your friends list and send message /KFCoptOut to the Neos account. You will receive message when successfully opted out

-- To opt back in send /KFCoptIn to the same account

-- Opting in/out will be later integrated into the user profile UI, this is temporary


Complex Types within Components / Logix

H3 wanted to use IAssetProvider<AudioClip> within a Dynamic Impulse. Here's how that's done with some other background data:

   [12:04 AM] Frooxius: I'd strongly discourage using raw RefIDs, as that's fragile and will likely break in the future or cause unintended bugs.
   [12:11 AM] H3BO3: then how can I pass an iassetprovider for an audio clip through a dynamic impulse then?
   [12:12 AM] H3BO3: or if there's something else I should be passing through
   [12:12 AM] Turk: There should be a type for it no? Typically you want to pass the actual type/object it should be just that and you'd write into a ref field of some sort.
   [12:13 AM] Turk: Because it should just be something like FrooxEngine.AudioClip I'd think
   [12:14 AM] Turk: You don't want to typically mess with the Interface classes as that can make stuff a little janky as you have to destep/do more effort then you need.
   [12:14 AM] Turk: Lemme see if I can find it.
   [12:14 AM] H3BO3: trying to copy the clip from one into another via dynamic impulse
   [12:15 AM] Frooxius: Use this: 
   [12:15 AM] H3BO3: thanks
   [12:15 AM] Turk: Ah okay! I forgot because you can't technically do ` in the keyboard.
   [12:15 AM] H3BO3: well shoot
   [12:15 AM] Turk: You need to paste it from Keyboard but I don't see why we wouldn't be able to from the normal one in game.
   [12:16 AM] Turk: But figured that was always a security thing.
   [12:16 AM] H3BO3: why doesn't FrooxEngine.IAssetProvider<AudioClip> work? could it?
   [12:16 AM] Turk: Ah because your calling 2 different classes I'd think right?
   [12:16 AM] Frooxius: You can copy and paste the thing. The ` simply wasn't added to the virtual keyboard.
   [12:17 AM] Turk: Ah okay!
   [12:17 AM] H3BO3: what does the `1 mean?
   [12:17 AM] Frooxius: FrooxEngine.IAssetProvider<AudioClip> doesn't work for two main reasons. It uses the wrong type FrooxEngine.IAssetProvider, you technically need FrooxEngine.IAssetProvider`1, which is the generic type and the nested type isn't fully qualified, so it's ambiguous, as it doesn't know which namespace/assembly to search.
   [12:17 AM] Frooxius: `1 means that it has 1 generic argument.
   [12:18 AM] H3BO3: ah
   [12:18 AM] Frooxius: You'd see `2 for types that have two.
   [12:18 AM] H3BO3: interesting
   [12:18 AM] Frooxius: Also < > are specific syntax to C#, but the actual qualified type names use [ and ] instead, which is defined by CLR.


Flag bones to be ignored by IK with <NoIK>

June 24th, 2020: "There's actually a thing you can add, if you add <NoIK> to the name of any bone the IK will ignore it always." [5]

Dynamic Bones and the difference between Inertia and Inertia Force

	chemicalcrux: I need to work out exactly how "inertia" and "inertia force" differ
	[7:48 PM] chemicalcrux: I've been having problems in general with dynamic bones being way too floppy when walking around
	[7:48 PM] chemicalcrux: I fixed it in one case by just driving the stiffness really high while moving
	[7:51 PM] Frooxius | CTO: Inertia is how much the bone moves with you. E.g. at 0.2 if you move 1 meter to the right, the bone will act as if moved 0.2 m to the right with you.

	InteriaForce is how much of the movement translates into a force applied to the bone from the movement.
	[7:51 PM] chemicalcrux: hmm, that roughly lines up with what I was seeing for inertia, yeah
	[7:52 PM] chemicalcrux: wouldn't those have the same meaning, then? Or is there some nonlinearity there
	[7:54 PM] Frooxius | CTO: No. Inertia doesn't translate into force on its own.
	[7:56 PM] Frooxius | CTO: E.g. if IntertiaForce is 0 and intertia is 0.2 (20 %), then the bone will just be just "pulled" by the motion. With IntertiaForce it will be accelerated with you.

	E.g. if you suddenly stop, with IntertiaForce set to 0, it'll just end up being pulled, but probably won't overshoot much. With stronger force, it'll end up "overshooting" as it keeps moving even if you've stopped.
	[7:56 PM] chemicalcrux: ah, I see. that makes sense, thanks!
	[7:56 PM] Frooxius | CTO: You can do interesting effects when you invert it too (use negative force), where the movement ends up pushing it the other way.
	[7:57 PM] chemicalcrux: high inertia makes the bone just follow along; high inertia force actually makes the bone want to keep going after you stop
	[7:57 PM] ohzee: huh, that actually explains a lot, I also got massively confused on it
	[7:57 PM] chemicalcrux: and does this apply to motion from both locomotion and non-locomotion?
	[7:57 PM] chemicalcrux: not sure if there'd be a distinction
	[8:00 PM] Frooxius | CTO: It doesn't care where the motion comes from. All it tracks is how much has the root of the bone moved within the simulation space.
	[8:00 PM] chemicalcrux: I had gotten it in my head that it was related to that somehow
	[8:00 PM] chemicalcrux: probably because walking is so fast compared to moving around your playspace normally


The difference between Get Active and Get Active Self

[6:50 PM] Parker: Does anyone know the difference between, the LogiX nodes, "Get Slot Active" and "Get Slot Active Self"?

[6:55 PM] Frooxius: The active gets if it's currently active at all within the hierarchy. It can be inactive because one of its parents is inactive. The Active Self is more direct, tells you whether the slot it set to active or inactive itself.

Fire On True / On Changed User Input Handling


[9:12 PM] Frooxius: @H3BO3 If the Fire on True doesn't have an user, it will try to use heuristics to determine for who has the change occurred. This works ok in most cases, unless the changed value depends on something that updates out-of-sync, like a stream or is local value that differs for everyone. [9:12 PM] Frooxius: If Fire On True is under an user, it will use that user for detecting updates. That way when it's on an avatar or it's an item or tool, it will also work well without plugging a particular user.

On Search Depth


0 means 0 search depth. Use -1 for infinity.


Using the "Hover" option with two separate touchable components

"can the hyperlink component have a checkbox to register if you are hovering over it? An item cant have both a hyperlink and a touchdata component on the same thing because a hyperlink technically counts as a button function itself. I just want to add a visual effect for when you hover over the thing that has the hyperlink, but the touchdata blocks it, and you cant have a layered quad to set off the vfx by Hover cause then that thing's collider blocks the hyperlink button. Long story short - can the hyperlink have a Hovering checkbox? maybe even a Touch checkbox?"

"@GearBell Use TouchEventRelay. You put that on the top of your object, then put the hyperlink and other touchables as children (with no colliders on them) and add them to the list of "TouchableTargets" of the TouchEventRelay."

What is "Unresolved References" and why does it have so many items?

See, this issue for more information. Essentially, do not worry too much about it though.