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.



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.