#archived-code-advanced

1 messages · Page 50 of 1

untold moth
#

Hmm

lament salmon
#

My declaration looks similiarcs public sealed class NightVision : CustomPostProcessVolumeComponent, IPostProcessComponent { public ColorParameter tint = new ColorParameter(new Color(0.25f, 1f, 0.5f), true, true, false);

#

And I can control the parameters just fine

ancient rivet
#

Even though the material is null, you can update the properties?

#

And they take effect?

warped galleon
lament salmon
# ancient rivet And they take effect?

Yes. This makes my colors go wild:

if (nightVisionVolume.sharedProfile.TryGet(out NightVision nightVision))
{
    nightVision.tint.Override(UnityEngine.Random.ColorHSV());
...
ancient rivet
#

Interesting, I wonder if there is some strange magic going on with volume components... let me try

lament salmon
#

Well, that's the correct way of changing properties on your PP component

#

Just forget about the material, it's private for a reason in the default HDRP post process

karmic surge
#

tho, there is a chance I can use ONNX model inside unity and ditch the entire python application (hopefully!)

ancient rivet
junior nest
#

Is there a way to write a script that replaces a Type name in code to some other name? That Type can be referenced in multiple scripts. Would i have to scan through every .cs file to replace it or is there a smarter way?

sly grove
#

use it

tiny pewter
#

He need to rename multiple source files

sly grove
#

Here's the rename feature in Rider

junior nest
#

i need it for an editor tool where the user can create and rename some types.

#

essentially i want to replicate that refactor -> rename feature

sly grove
#

Unless you're doing code generation I don't understand what you're trying to do

junior nest
#

i am doing that

sly grove
#

Just change the name you are generating

junior nest
#

but the user of my tool might have written some code that depends on the previous type. his code would break if id just "overwrite" my own file

sly grove
#

Is that a huge problem? What is this tool supposed to be?

junior nest
#

Its a tool to create an AI without any code. Essentially a gamedesigner could create AI all by himself. A coder might then use some of the AIs internal data to write his own Debugger or something. This Debugger would then break if the designer decides to rename stuff

#

Id really like to reduce the errors that could happen through a lack of communication

sly grove
#

I mean I'm thinking about something like the input system's Input Action Assets.
If you use the generated code and rename your input actions, your code will break too.

#

It's not a big deal

#

I also get really nervous around an editor script that's going to modify my source code

#

modifying its own generated scripts is fine - but messing with user code? That's a little... odd

junior nest
# sly grove modifying its own generated scripts is fine - but messing with user code? That's...

no its not messing with usercode. but the user could decide to mess with it. to extend tooling or get very specific data out of the AI. The AI is essentially a closed pipeline with Userdata as input and a decision as output. but it generates intermediate values that could be useful to some users. each of those intermediate steps is identified by a Type that is generated and named like a scriptable object the user is defining in the editor. So now if the user renames the Scriptable Object the type in code is not correct anymore. maybe i should just let it break

#

On a side note: currently my system allows for the coder to rename anything as he sees fit because codegen would never overwrite it. which might also be nice to have. the fact that ScriptableObject and generated Type name will not be easily connected to each other just bothers me.

#

oh i forgot to mention that that generated type is referenced in other generated files... without that "refactor name" feature id need to codegen everything from scratch after a rename. until now i can do everything incrementally.

#

im probably ovethinking this though.

sly grove
#

Regenerating from scratch is much simpler

junior nest
#

i guess so. i wanted to rethink my incremental approach anyways. currently im generating way too many single files. if id combine them in a few big ones its probably for the best. Nice Sourcecontrol workflows might be at risk though

#

Problem with AI is that it will get changed a lot and also by multiple people compared to say inputs.

sly grove
#

Maybe consider refactoring the way the code works to be more data-driven with fewer classes

#

That's obviously really broad and hand-wavy

#

Because I don't know any details here

junior nest
#

yeah its the most reasonable thing to suggest first anyways 😄
the issue is that im using DOTS and that has some very specific requirements regarding that

compact ingot
junior nest
# compact ingot I think what you describe is best handled by some sort of runtime you build whic...

yes totally agree with you on that. Users AI is actually already just data defined in a ScriptableObject graph which could easily be interpreted in a generic way without any Codegen needed. my problem again is DOTS and the kinda incomplete API. To Query for Components i need to define entityqueries with specific known Types. so to get the Data into my "runtime" (which then again is generic) i need types...

#

(sry for delayed responses im not at home rn)

novel wing
#

Given a NativeArray can I somehow make a NativeReference point at an index in that array?
I have a job that outputs a NativeArray<T> of results, but another job uses NativeReference<T> so I want to give it a ref to Array[0];

shrewd bear
# untold moth Hmm

Hey sorry to ping you again. But since you seemed to have good info. Is it possible that not having the world camera assigned to the canvas may have caused this issues?
In reproducing the error, I noticed it only fires when the cursor is unlocked and the mouse is on screen. It stops once I get out of range and the other player is destroyed, which means the canvas is destroyed.
The only thing I struggle with is the unreliability of making the error happen and calling it closed.

#

This is the stacktrace in the editor for reference.

MissingReferenceException: The object of type 'TextMeshPro' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
UnityEngine.Component.GetComponent[T] () (at <c6b52566f59b49fc861a7812a1ea2f6b>:0)
UnityEngine.UI.Graphic.get_canvasRenderer () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Graphic.cs:444)
UnityEngine.UI.GraphicRaycaster.Raycast (UnityEngine.Canvas canvas, UnityEngine.Camera eventCamera, UnityEngine.Vector2 pointerPosition, System.Collections.Generic.IList`1[T] foundGraphics, System.Collections.Generic.List`1[T] results) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/GraphicRaycaster.cs:335)
UnityEngine.UI.GraphicRaycaster.Raycast (UnityEngine.EventSystems.PointerEventData eventData, System.Collections.Generic.List`1[T] resultAppendList) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/GraphicRaycaster.cs:236)
UnityEngine.EventSystems.EventSystem.RaycastAll (UnityEngine.EventSystems.PointerEventData eventData, System.Collections.Generic.List`1[T] raycastResults) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:263)
UnityEngine.EventSystems.PointerInputModule.GetMousePointerEventData (System.Int32 id) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/PointerInputModule.cs:295)
UnityEngine.EventSystems.StandaloneInputModule.ProcessMouseEvent (System.Int32 id) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/StandaloneInputModule.cs:540)
UnityEngine.EventSystems.StandaloneInputModule.ProcessMouseEvent () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/StandaloneInputModule.cs:526)
UnityEngine.EventSystems.StandaloneInputModule.Process () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/StandaloneInputModule.cs:280)
UnityEngine.EventSystems.EventSystem.Update () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:501)
untold moth
sage radish
# novel wing Given a NativeArray can I somehow make a NativeReference point at an index in th...

Sounds like a reasonable requirement and should be technically possible, but I don't see any options in the NativeReference API to not allocate new memory. It doesn't have an unsafe utility method for creating one from existing data like NativeArray does. I don't think it's intentional, just forgotten.

The only workarounds I can think of would be to use Reflection to change the internal pointer (you could also use the asmref trick to get access to the internal pointer without Reflection)

shrewd bear
untold moth
shrewd bear
untold moth
shrewd bear
# untold moth It's not great practice to have the text receive raycasts. Better have a backgro...

Okay. I think I figured out how to reproduce it. And I got a slightly different error.

MissingComponentException: There is no 'CanvasRenderer' attached to the "Float Number(Clone)" game object, but a script is trying to access it.
You probably need to add a CanvasRenderer to the game object "Float Number(Clone)". Or your script needs to check if the component is attached before using it.
UnityEngine.UI.GraphicRaycaster.Raycast (UnityEngine.Canvas canvas, UnityEngine.Camera eventCamera, UnityEngine.Vector2 pointerPosition, System.Collections.Generic.IList`1[T] foundGraphics, System.Collections.Generic.List`1[T] results) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/GraphicRaycaster.cs:335)
UnityEngine.UI.GraphicRaycaster.Raycast (UnityEngine.EventSystems.PointerEventData eventData, System.Collections.Generic.List`1[T] resultAppendList) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/GraphicRaycaster.cs:236)
UnityEngine.EventSystems.EventSystem.RaycastAll (UnityEngine.EventSystems.PointerEventData eventData, System.Collections.Generic.List`1[T] raycastResults) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:263)
UnityEngine.EventSystems.PointerInputModule.GetMousePointerEventData (System.Int32 id) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/PointerInputModule.cs:295)
UnityEngine.EventSystems.StandaloneInputModule.ProcessMouseEvent (System.Int32 id) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/StandaloneInputModule.cs:540)
UnityEngine.EventSystems.StandaloneInputModule.ProcessMouseEvent () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/StandaloneInputModule.cs:526)
UnityEngine.EventSystems.StandaloneInputModule.Process () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/InputModules/StandaloneInputModule.cs:280)
UnityEngine.EventSystems.EventSystem.Update () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:501)
#

So i think it is the float text prefab

#

When I click on the where the canvas is on the player

untold moth
#

Hmm... Is it a canvas without a canvas renderer?🤔

#

Or a ui object outside of a canvas?

shrewd bear
#

Oh

#

Yeah. The text floats up

#

It would be outside of the bounds of the player cavnas

untold moth
#

No, I mean outside like not parented to a canvas

shrewd bear
#

No it is parented.

untold moth
#

And the canvas has a canvas renderer?

shrewd bear
untold moth
#

looks like it doesn't have it

#

Wait, it should be on the text object

shrewd bear
#

Yeah. That is what i was thinking

#

The text object didn't have one

novel wing
untold moth
shrewd bear
untold moth
shrewd bear
#

Yeah

untold moth
#

Then it doesn't need to be on the canvas afaik. Perhaps that's the issue.

shrewd bear
#

Not sure but i've got some testing to do. Thanks for your help.

undone coral
shrewd bear
undone coral
#

are these little UIs floating out in world space? what is the gameplay?

#

it's telling you what the error is. it sounds like you have prefabs that you have built incorrectly and you are instantiating them into hierarchy where it doesn't make sense to have them

#

In reproducing the error, I noticed it only fires when the cursor is unlocked and the mouse is on screen. It stops once I get out of range and the other player is destroyed, which means the canvas is destroyed.
this is all a red herring

#

it sounds like there are a lot of flaws.

#

the existence of a "Billboard" script is really concerning

#

sort of. you can look at keijiro's examples and ffmpegpipe.

#

without doing
Inter-process communication.
i don't think you mean this

#

hmm... it sounds like you have a lot of issues with this codebase, and based on this snippet, you have a lot of stuff going on

#

have you looked at edy's vehicle physics / vehicle physics community edition / vehicle physics pro?

#

anyway, if i recall you had a deadline that should be coming up in a week or two. if i were you, i would probably ask for more time

fair hound
livid kraken
#

I'm tired and need help guys. I have two arrays of the same length. Array A has values in it. In array B I need to store at each index the sum of all previous elements from A up to that index. I.e if A is [1,64,3] B needs to be [1,65,68]

sly grove
sage radish
undone coral
#

Is there a way to tap into every event EventSystem executes?

#

it doesn't look like there is. does anyone have pre-existing code to hack this in?

kindred remnant
karmic surge
shrewd bear
shrewd bear
upbeat path
#

yes

thin mesa
misty glade
#

I've recently imported Unity.Notifications.Android and realized that I can't use capital letters in my Large icons. Fine, rename all the files, re-link them in the dialog box, but .. unity seems to have created and copied files to the \Library\Bee\Android\Prj\IL2CPP\Gradle\unityLibrary\src\main\res\drawable-hdpi-v11 folders (for each of the resolutions) and I can't get through a build.

Is there a way to force an import of these graphics assets again? Or do I have to rebuild my library (something I don't want to do because it takes forrrrrrrrrrever)

#

(files in the build directory have the old filenames with capital letters - although in the unity project and file system these are renamed)

misty glade
#

update: rebuilding the asset library didn't even fix it, I just had to go into these directories and manually prune all the files.. but that worked and now my game has nice little notifications with context sensitive icons

misty glade
#

thanks

vernal furnace
#

With TextMeshPro assets, is it possible to write a dynamic string output with colour values per line?
IE. Title of the section in red, body of section in green.
IE. Name of stat in one colour, stat value in another

I'm understanding I need to use the vertex colour, but am I forced to parse each line dynamically as well to change just that text?

I'm trying to avoid using the inspector or stacking a bunch of prewritten textmesh assets into a heirarchy, instead push it all through one output.

Thanks

misty glade
#

Is there a way to disable unity doing stuff with ADB? It keeps disconnecting my other window with logcat running, and it also keeps popping up these console windows doing who knows what every few minutes (like 5 times, instantly appear/disappear).

mellow plinth
#

I'm trying to learn how to use PlayableGraph, but I'm kind of lost.
How can I attach an Animator to a PlayableGraph, and then (after a while), unattach it and return it to the normal system?
I think in order to attach it, I must do:

AnimationPlayableOutput animationOutput = AnimationPlayableOutput.Create(graph, graphName, animator);
AnimatorControllerPlayable ctrlPlayable = AnimatorControllerPlayable.Create(graph, animator.runtimeAnimatorController);
animationOutput.SetSourcePlayable(ctrlPlayable);
animationOutput.SetTarget(animator);
animator.runtimeAnimatorController = null;

Right?
But how can I deattach it later?

#

My intention is to optimize animators that are far away from camera by updating them less frequently. I know that animator has an update method, but that doesn't use batching and so it's single-threaded.

#

But I heard that PlayableGraph supports batching the animators.

barren stump
#

I have these 2 lines of codes: Debug.DrawRay(transform.position, -transform.up * 100f, Color.red); Debug.DrawRay(transform.position, new Vector3(0f, 0f, -transform.localEulerAngles.z - 15f), Color.red);

#

The first ray is being drawn, but the second is not

#

The only difference between the two is the direction in the second one

#

Why is it an invalid direction? Why doesn't it work?

#

I realize that -transform.loc... can be -356 or something and subtracting 15 can cause it to be less than -360, but even the -tranform.loc... is something like -14, the code still doesn't work

lament salmon
#

Have you logged the value of -transform.localEulerAngles.x - 15f?

barren stump
#

its .z, I copy and pasted the wrong thing

lament salmon
#

Also you can put it in a nice -180..180 range with angle = Mathf.DeltaAngle(0, angle)

barren stump
#

Personally I simply just find it harder to work with that range

#

this is the value of transform.up: (0.00, 0.00, -0.12)

#

This is the value of the other direction: (0.00, 0.00, -15.12)

lament salmon
#

Are they being drawn on top of each other perhaps

#

Maybe add a slight offset (or use a different axis) and different color

barren stump
#

I tried that

#

Figured it out

#

For anyone wondering, drawray doesn't use euler angles, it only uses the vector angle thingy that transform.up returns

#
Vector3 direction = new Vector3(-Mathf.Sin(angleInRadians), Mathf.Cos(angleInRadians), 0f);
Debug.DrawRay(transform.position, direction * 100f, Color.red);```
lament salmon
#

I mean... It's a direction, I thought youre aware of that

#

And just visualizing the angle or something

barren stump
#

Yes they both are directions though, but only the vector direction works

lament salmon
barren stump
#

I feel you, I'm pretty much a beginner ;/

lament salmon
#

Like transform.up is a direction
transform.eulerAngles is an euler rotation
transform.rotation is a rotation

barren stump
#

Hmm

lament salmon
#

The first two are vectors, but euler angles isn't a direction

#

Just pointing it out for future reference 👍

barren stump
#

Got it, thank you

sly grove
barren stump
#

I considered rays to be a more advanced topic than a beginner one, that’s why I asked here

#

I might be wrong though.

sly grove
undone coral
# sly grove what's the goal?

making it easier to do things like

when i click this card, put it in the spellcasting state
when i click anywhere else that isn't a target, cancel
daring topaz
#

Hi all! Today is the 3rd day as I'm trying to deal with zenject.
Such a question, if the projectContext itself automatically appears on the stage and cannot be added manually, which means I can’t just drag the necessary dependencies onto it, how can I throw global dependencies into it? Through delegates? What if the sceneContext is loaded along with the scene in the prefab?

sly grove
sand acorn
#

Hello there, does anybody know about an algorithm that allows the use to draw mesh mesh edges with some given vertices?

#

I basically would like to connect all the vertices of a mesh in a uniform way, not like the way on the image

undone coral
dry bridge
#

Hi all! I don't know if this is the right channel for this but I'd just like to ask how UnityEngine.XR is able to identify a certain part of a VR device (e.g. Head, Left eye, Right eye, right hand, left hand etc.) as either left eye of the VR device, Left hand of the VR device etc. by means of using the InputDevices.GetDeviceAtXRNode() ? The thing I'm working on now entails creating a device similar to that of common VR device available (e.g. Oculus, HTC Vive) and am currently trying to understand what unique identifier such functions look into.

modest needle
# sand acorn I basically would like to connect all the vertices of a mesh in a uniform way, n...

You'd have to use the Triangle.NET library for this code
https://hastebin.com/share/yojumameva.csharp
1 - Attach the EdgeGenerator script to a GameObject in your scene.
2 - Assign a material to the edgeMaterial field in the EdgeGenerator script using the Unity Editor.
3 - Set the lineWidth value to control the width of the mesh edges.
4 - Add your vertices to the vertices list in the EdgeGenerator script using the Unity Editor or create the list programmatically in the script.

modest needle
dry bridge
modest needle
#

Oh I see I see I actually tried to peek

sand acorn
cerulean minnow
#

Does anyone know how to get a facebook profile image url?

public void FbGetPicture(IGraphResult result)
    {
        if (result.Texture != null)
        {
            ProfilePicture.sprite = Sprite.Create(result.Texture, new Rect(0, 0, 128, 128), new Vector2());
        }
    }
undone coral
#

are there examples combining kinematic character controller with navmesh agent?

#

and any authoritative docs for runtime navmesh updating? or is it aaron granberg still for the most flexible stuff? is his engine on burst yet?

gaunt mantle
#

i've seen setups using navmeshagent to move an invisible object to navigate and the character uses physics to try to stay follow the object while reacting to physics

dapper cave
#

did physics change a lot in 2022? when I transform.Rotate in 2021- = no problem, now i get all stutters

#

more of a physics question but that board is super dead

#

ah it's the simulation mode that changed, wow that broke a lot of stuff

sly grove
dapper cave
sly grove
dapper cave
#

rb.MoveRotation lacks Space.Self so I've never bothered with it

timber flame
#

You can see navigation line (white line) for each dupe in oxygen not included game. I want to know which algorithm they have used. It seems it finds all path to every task (here digging)
What do you think? They have used a star from a dupe to every task point?
Even there is no task like under water, you see white navigation line.
It returns all reachable points where a dupe can move towards

gleaming jewel
# dapper cave define wrong - it's always worked

To get accurate and bug-free physics you need to play by the physics engine's rules and use Rigidbody methods to move a rigidbody
Changing Transform properties directly skips the physics engine

dapper cave
dapper cave
timber flame
#

In A star or dijkstra you have a source and destination

#

In the above picture, we have one source and one target?!

#

I think of flood fill

dapper cave
timber flame
#

It returns all reachable tiles and connect them

dapper cave
timber flame
#

I want something like it for 3d world (voxel based)
Flood fill is really expensive in 3d

dapper cave
dapper cave
#

I'm doing what you're talking about, in the evaluator of the utility AI

#

and, like you, in voxel. fully procedural voxel environment too so I also need graph rebuild to be super fast.

#

or at least not show up in the main thread

timber flame
#

My problem is not about implementation of a star

#

I have implemented it, it is also burst compatible

#

More, I would like to know what exactly they do when there are many tasks in different places.
Another issue is for each task, they show if it is reachable (white icon) or not (gray icon)

#

I do not think they run a star from each dupe to each task

honest agate
#

so i have a ping pong paddle mesh. I need to put a hole in it as if a ping pong ball went clear through it, for my game.

#

i understand i need to play around with things like mesh.triangle

#

but i am struggling to find info on it

#

i need to (in this order)
add a ring of new vertices each equidistant from the point where the ball collided
delete the triangles in the middle of this ring
connect each ring on either side to connect the two holes

undone coral
undone coral
#

use the asset instead

honest agate
undone coral
honest agate
#

this one?

#

ok thx

undone coral
#

is there a robust package to export a prefab with its script dependencies? as opposed to the default unitypackage exporter

sly grove
mellow plinth
#

I'm trying to optimise the performance cost of several Animators, by updating them X times per seconds rather than on each frame, depending on the distance towards player.
However, using the Update methods of Animator is single-threaded.
So I read that I can use PlayableGraph to batch multiple animators at the same time using multi-threading.
However, when doing so I notice that the PlayableGraph.Evaluate method's internal jobs are waited, leading to dead-time in the main thread... is there a wait to prevent that?

untold moth
severe grove
#

I'm trying to make a pixel writing job more efficient but it is throwing an error. ```
[BurstCompile]
public struct SetPixelsByIndexJob : IJobParallelFor
{
public NativeArray<Color32> Data;
public NativeArray<int> Pixels;
public Color32 Color;

    public void Execute(int index)
    {
        var p = Pixels[index];
        Data[p] = Color;
    }
}``` ```System.IndexOutOfRangeException: Index {0} is out of restricted IJobParallelFor range [{1}...{2}] in ReadWriteBuffer.``` I assume there is an issue here with the index in execute not working how I think it should but I don't know how to fix it.
#

Here is the job in question public void TextureFill(Texture2D texture, Color32 color, int[] indices) { Debug.Log(indices); var data = texture.GetRawTextureData<Color32>(); var pixels = new NativeArray<int>(indices, Allocator.TempJob); var job = new SetPixelsByIndexJob { Data = data, Color = color, Pixels = pixels }; job.Schedule(pixels.Length, Math.Clamp(data.Length / 4, 1, 128)).Complete(); texture.Apply(); data.Dispose(); pixels.Dispose(); }

#

Alright. So there are restrictions in place to prevent race conditions in parallelfor jobs. that means that only the member of the collections at that index in available. I had to do [NativeDisableParallelForRestriction] public NativeArray<Color32> Data;

#

I don't think it will be an issue because the pixel array is generated from a hashset so no double values.

tropic vigil
#

Is it the correct way of measuring the size of this struct?

public struct Data : INetworkSerializable
{
  public Tile.TileData [] tiles;
  public GridMode boardGridMode; // enum

  public int GetSize()
  {
    int size = Marshal.SizeOf(this);
    size += Marshal.SizeOf(typeof (Tile.TileData)) * tiles.Length;
    return size;
  }
}
abstract hill
#

Hi everyone, just a quick question. I'm working on some custom inspector code right now and quite often in tutorials I see people inside both OnSceneGUI and OnInspectorGUI do things like

if (_someEditorUtility == null) _someEditorUtility = Initialise()

What I am wondering is why are these things not just done on the Editors OnEnable function. What are the cases where the editor will trigger these render functions but will not have previously set its base state with OnEnable?
Is putting this sort of code on enable fine, or is just doing the null checks a safer way of doing it?

austere jewel
tropic vigil
abstract hill
#

Ah brilliant, thank you @austere jewel and @tropic vigil, I'll do it the OnGUI way then, I'll see about having a play around and getting my head around exactly when things are called and not but its good to know that there is valid reasons to put the tests outside of OnEnable. Thank you both.

versed oasis
#

What is the latest unity networking please?

tropic vigil
versed oasis
#

Thanks

#

Is there a way to download raw text of the netcode docs please?

brazen geyser
#

Does anyone know how to remove the clones after I shatter an object to pieces? https://gdl.space/hufewosaba.cs I added some logic in the beginning, but it won't simply destroy the objects for some reason.

gleaming jewel
sly grove
brazen geyser
brazen geyser
sly grove
frank peak
#

I'm building a digital circuit simulator and have a question.
What data structure would best represent a circuit? a linked list of the component gates, considering the way circuits are sort of in a loop? or? I was also suggested to just save the state of the circuit as a struct and pass that about but I'm curious what y'all thought.

#

tho maybe I don't even need a list of the components or how they connect, and I just save the state as a struct, or simpler, as a variable called signal that literally tracks if its 1 or 0 at some given point and update as the simulation runs. big hmm lol.

dusty wigeon
# frank peak tho maybe I don't even need a list of the components or how they connect, and I ...

Well, depending on your needs and specification, I would use standard classes with the help of polymorphism to construct the representation in a graph shape. This way, you would have high flexibility to accommodate any extra needs such as UI, editing tool, etc.

That being said, if you plan of having to deal with high numbers of circuit and you require performance, you should definitely try to come up with a representation that holds all the data sequentially. I do not know the specifics of digital circuit, but it would not be strange if you could express all of the require information in a tight representation with little to no "building" blocks such as how NP complete problems can be resume in [Variables, Not, Or, And, Parentheses]. Such representation could be easily hold in sequential data structure with the help of a little bit of work.
(But like, I said, I do not know your needs nor the subject you are simulating, which make it hard to find an appropriate solution)

Here a link of the first thing I found on the subject: https://codeahoy.com/learn/analysisofalgorithms/ch27/

frank peak
#

it feels classic how this all leads back to np-completeness lmao

#

and ofc my idea of a signal variable is basically a statemachine with punch tape returning 1 or 0 looool

#

is circuit satisfiability really np-complete?

dusty wigeon
#

I think so. I've not really studied NP-Completude, I can not really help you there.

frank peak
#

there is those millenium math problems from the clay math institute, but thats a bit tangential to this channel. anyway, thanks for the lead

compact ingot
frank peak
#

perfect

compact ingot
#

note that all graphs can be serialized to an array representation, an architecture where a each node is an object will be the worst case for performance but best case for abstraction/UX

#

you should maybe set a rough performance target and find an implementation that can potentially achieve that target, then don't worry about performance until the thing works.

frank peak
#

yeah good point lol

fair plank
#

Does anyone know how I would save & load instantiated prefabs and their transform values with JSON? I made my own JSON saving system but I'm struggling to find any answers online to this.
In my game you put down stickers that are instantiated which can be moved, resized and rotated. How would I save them with JSON?
I'm assuming it would be something like saving a unique ID per instantiated prefab together with their position, scale and rotation in a list which instantiates them on load but I'm struggling to do it in practice as I'm pretty new to JSON and saving in general.
Any pointers or examples would be super helpful 🙂

raw arrow
#

Create a data structure to hold the prefab and its transform values:

#
[System.Serializable]
public class StickerData
{
    public int id;
    public Vector3 position;
    public Quaternion rotation;
    public Vector3 scale;
}```
#

Instantiate your sticker prefab and populate the data structure with its transform values:

#
GameObject stickerPrefab = Resources.Load<GameObject>("StickerPrefab");
GameObject newSticker = Instantiate(stickerPrefab, position, rotation);
StickerData stickerData = new StickerData();
stickerData.id = newSticker.GetInstanceID();
stickerData.position = newSticker.transform.position;
stickerData.rotation = newSticker.transform.rotation;
stickerData.scale = newSticker.transform.localScale;
#

Add the data structure to a list and serialize it to a JSON string:

#
List<StickerData> stickers = new List<StickerData>();
stickers.Add(stickerData);
string json = JsonUtility.ToJson(stickers);
#

Save the JSON string to a file:

#
string path = Application.persistentDataPath + "/stickers.json";
File.WriteAllText(path, json);
#

To load the stickers, you would read the JSON string from the file, deserialize it back into the list of StickerData objects, and then instantiate the stickers using the saved transform values.

dusty wigeon
#

@raw arrow answer works pretty well. If you want to push a bit further, you can also create and inherit from a custom interface and then use the said interface for the initialisation of all MonoBehaviour that inherits from the interface.

Here is a following pseudo code that manage the serialisation of both, scene and instantiated objects. There is multiple way of doing this, each with pros and cons. Notable alternative would be: Usage of struct (DTO), Usage Attributes (Reflection), Usage of BaseClass (Instead of Inheritance), etc.

public interface MyNameSpace.ISerializable
{
  public string InstantiatedPrefabID(); //Null if object is SceneObject
  public string Id();
  public Dictonnary<string, object> Serialize();
  public void Deserialize(Dictonnary<string, object> values);
}
public class MyComponent : MonoBehaviour, MyNameSpace.ISerializable { ... }
public class MyNameSpace.Serializer
{
  public void Serialize() {
    //For all MyNameSpace.ISerializable
    //Serialize
    //Add InstantiatedPrefabID and ID to the serialize data
  }
  public void Deserialize() {
    //For all Data
    //Find all MyNameSpace.ISerializable
    //If data has an InstantiatedPrefabID associated then
    //Instantiated the corresponding object and deserialize
    //Else then
    //Deserialize into the corresponding object
  }
}
scenic forge
#

And source generators of course 😄

hardy sentinel
scenic forge
#

Source generator just generates code for you depending on input, so really you can use it whenever you want to generate any code, especially repetitive ones.

dusty wigeon
#

Depending on what you mean by source generator you could use one for:

  • Reducing Boilerplater Code
  • Adding Functionality
  • Optimise Code
  • Maintain Code
  • etc.
#

That being said, in most case, you are better without it.

scenic forge
#

What's mentioned above of adding attributes then using runtime reflections to inspect the attributes to de/serialize data, could be done exactly the same: adding attributes but instead using source generators to generate code that does the de/serialization, so you get the best of both worlds, simple code and no slow runtime penalty.

hardy sentinel
#

Are you suggesting one would be able to bypass the reflection then by using a source generator?

dusty wigeon
#

What do you mean bypass ?

scenic forge
#

Yes, you can generate literally any code.

hardy sentinel
#

Not use it

scenic forge
#

Why use reflection to access a property, when you can just generate code that does the accessing directly?

#

😉

dusty wigeon
#

Yeah, you won't need reflection. You could use it for Generating Code though

#

Code Generation is whole world in itself which can sometimes lead to unpleasant things.

scenic forge
#

Not necessarily

dusty wigeon
#

"can sometimes"

fair plank
scenic forge
#

Source generators can only add code, but never edit/remove existing code, that constraint by itself is enough to make it much less error prone than things like C++/Rust macros.

#

IL weaving on the other hand, does allow you to modifying existing code, and that's when things can get ugly really fast.

dusty wigeon
#

Code Generation add a "Magic" effect to codes as the user might not understand exactly how the engine works.
Code Generation can sometimes fail, which can lead to a whole bunch of issues.
Code Generation requires maintenance through the whole project.

elfin tundra
#

i have a bunch of coroutines basically functioning as timers that wait until a certain object has collided with another object. is there a performance difference between doing yield return null and yield return new WaitForEndOfFrame or can i just pick whichever since it isn't doing anything in the meantime?

scenic forge
#

I wouldn't say it's very magical, everything it generates can be inspected.

#

It's not like Update where it's magically called, code generated by source generators exist in your IDE and you can look it up.

raw arrow
# fair plank Thank you for your answer. I got your example to work the best except how would ...

To update the transform values of a sticker during runtime, you would need to find its corresponding data in the sticker data list and update its values:

StickerData stickerData = stickerDataList.Find(data => data.id == sticker.id);
if (stickerData != null) {
    stickerData.position = sticker.transform.position;
    stickerData.rotation = sticker.transform.rotation;
    stickerData.scale = sticker.transform.localScale;
    // You can also update any other properties of the sticker data here
}```
dusty wigeon
# elfin tundra i have a bunch of coroutines basically functioning as timers that wait until a c...

yield return new WaitForEndOfFrame creates and Object each time it is invoke which could slow down considerably if the coroutine is called a lot. It can be prevent by caching the object. But, as far as I know, yield return null and yield return WaitForEndOfFrame have the same results.

That being said, I would try to come with alternative if the coroutine is something that is used often. I've seen ugly usage of coroutine. StateMachine and Update (with Time.time) can most of the time works correctly.

scenic forge
#

I do agree debugging source generators sucks though, it's still one of the biggest DX pain points.

elfin tundra
dusty wigeon
scenic forge
#

And you can't reference a SG project directly in Unity, you have to rebuild the project and copy over the dll every time you make changes, which is also a pretty significant downgrade to how SG works in regular C#.

dusty wigeon
#

Which makes the process of introducing new team member harder.

scenic forge
dusty wigeon
#

It is magical, I wont say otherwise, but at least it is pretty well know and documented which is not the case for most Code Generation solution made InHouse.

young wraith
#

Hi can someone help me

dusty wigeon
scenic forge
#

If you see a .Serialize() method that doesn't exist on the class, you can just click it in your IDE and it takes you directly to the code that's generated and you can inspect it, your source generators can also directly document there "this is generated by XYZ because you decorated the class with GenerateSerialization attribute"

#

I do see your point though, you can expect new members to already know Unity has magical Update, whereas inhouse SG needs to be introduced, and inhouse stuffs tend to lack docs.

dusty wigeon
#

And yes, you can always make the whole process of Code Generation clearer. Unfortunately, we sometime do not have time/resources for that.

scenic forge
#

I think SG is under utilized, source generation sounds scary but people using other languages routinely work with them daily; just like any power feature, it comes with great responsibilities, anything can be abused if you are evil enough.

#

If anything though, if you have editor scripts that generate source code, that's potential place to be replaced with SG.

dusty wigeon
#

I tend to prefer solution that requires less engineering from my part. If I wanted to make an engine I would have done that instead of a game.

scenic forge
#

There are places where it makes sense to use, the original question is a very possible use case where you have to choose between verbose source code or runtime performance penalties, but SG can get you both.

fair plank
young wraith
dusty wigeon
# young wraith Sorry I cant understand can you check again my post

The error means that the value you assigned to your MemoryStream is being changed (Increased) by the usage of cryptoStream.Write which is an operation that is not supported to this particular Stream. To resolves your issue, you probably want to, first, evaluates Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(GameLevelBuilder.GameLevelWithDefaultValue())) then create your MemoryStream with the appropriate size which would prevent the "increase" of the MemoryStream.

#

That being said, I have no directly knowledge on the usage of CryptoStream and pretty limited usage of MemoryStream. I have applied simple deductible reasoning from the given codes and Google Research results and not tested it myself.

young wraith
undone coral
#

"Entities☕ "

kind sigil
#

oh right, didn't see my room was switched. Apologies.

undone coral
#

"having a working game doesn't matter"

novel plinth
undone coral
#

i'm not sure it is supported

#

the way you are setting this up seems odd

#

you are not using a canonical key format

#

which means you might not know what you are doing

#

you are doing something very strange

#

why did you call it decryptionStream

undone coral
#

there's good preëxisting literature on this

#

have you lööked at it?

#

maybe there's an open source circuit sim

#

something something, EAGLE

undone coral
raw arrow
#

Assuming that you have a list of StickerData objects and you want to update the transform values of a specific sticker with id, you can use this line of code to retrieve the corresponding StickerData object from the list.

#

Once you have retrieved the corresponding StickerData object from the list, you can update its transform values with the values from the sticker game object.

novel plinth
sullen jetty
#

Can anyone point me to the settings Unity uses to get the paths to its assembly references?
I have a project that uses one path in Assembly-CSharp and another path in any projects created by my asmdef files.
C:\Program Files\Unity\Hub\Editor\2022.1.0f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\mscorlib.dll
vs
C:\Program Files\Unity\Hub\Editor\2022.1.0f1\Editor\Data\NetStandard\compat\2.1.0\shims\netfx\mscorlib.dll

#

If it makes a difference, I started this in a 2021 LTS release and changed the editor version in Unity Hub to launch with 2022.1

#

Of course: as soon as I posted that question, I found the field I wanted. Edit -> Project Settings -> Player -> Other Settings -> API Compatibility Level. I switched it from .NET Standard 2.1 to .NET Framework, and Unity rebuilt the C# solution to use the newer assemblies

#

That explains why my asmdef projects got the 2.1 assemblies, but I'm still confused about how Assembly-CSharp got the newer assemblies at all 🤔

frank peak
#

O.O <- mfw looking at the cost of EAGLE lol

#

also ofc theres games like Retro Gadgets that I could model my digital circuit sim after, but idk, I don't feel like thats as a cool as some like say...

#

I really want to use procedural generation to like... create circuits that have to be fixed but THEN i'm basically workin on an algo for circuit satisifiability lol

weary stag
#

So I'm trying to use a pool of objects.

#

To avoid instantiating and destroying objects during runtime.

#

I've done this basically.

#

Now the "terrainFloor" Game Object has multiple children.

#

It seems the children are just not moving when I change the position of the TerrainFloor.

#

Red gets moved, Blue doesn't.

tropic vigil
weary stag
#

Sadly that wasn't the case. It ended up being that the objects under Grass and Fence had a weird Static (-) flag. @tropic vigil

tropic vigil
weary stag
#

Huh?

#

Array size has nothing to do with struct size afaik?

#

Since arrays are stored by reference.

weary stag
tropic vigil
weary stag
#

Yeah but arrays in the struct are stored by reference.

#

The struct just stores the reference to the array.

#

sizeof for structs only works in unsafe context anyways last I checked.

tropic vigil
weary stag
#

I'm not saying you can send references.

#

I'm telling you how structs work in C#. What you're instead looking for, if you're trying to send the whole struct, is to use a NetworkStream.

#

Write the data of the struct to the stream.

#

On the recipient side, read the data of the struct from the stream.

tropic vigil
weary stag
#

is Board.Data a struct?

#

or a class?

tropic vigil
# weary stag I'm telling you how structs work in C#. What you're instead looking for, if you'...

I'm using INetworkSerializable in this case. Works well for ClientRpc as long the data isn't huge.

 public struct Data : INetworkSerializable
 {
    public Tile.TileData [] tiles;
    public GridMode boardGridMode; // enum

    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
      serializer.SerializeValue(ref tiles);
      serializer.SerializeValue(ref boardGridMode);
     }
novel plinth
weary stag
#

Mate, arrays have nothing to do with struct sizes. In fact, I can create a struct with an array in it for you right now, and it'll figure out the struct size, because arrays are always stored on the heap in C#.

struct X {
    int n
    int[] k
}

The above struct has a fixed size: 4 bytes for the integer, 8 bytes for the reference to an array. 16 bytes total (4 bytes for padding).

novel plinth
#

Marshal.SizeOf works on instances and runtime types

#

so just use that

tropic vigil
weary stag
#

Yes. That's true.

#

Which is why I suggested you a better solution entirely.

#

And one that is used more popularly for game development and everything else.

#

NetworkStream

#

This code compiles.

#

This is the ASM.

#

This is output.

novel plinth
#

but that requires to enable unsafe mode in the editor, but should be fine

tropic vigil
weary stag
#

Huh? I literally made a struct just like you did...

tropic vigil
weary stag
#

I didn't declare a type either?

#

I declared a struct.

novel plinth
#

aight Im a bit lost here.. you both can continue 🥳

weary stag
#

I'm just as lost...

tropic vigil
#

I need to get the size of an instance, because every instance has different size, so I need to calculate size of each instance individually, so I can't simply check the size of a type.

weary stag
#

Yeah, what you're doing this isn't a solution for.

#

I'm correcting you where you said since every struct has a different size.

tropic vigil
#

I ain't gonna declare 16 byte buffer for an array that has size 1000.

weary stag
#

Because structs don't have different sizes. Size of a struct is fixed, and determined at compile time.

#

What you're trying to encode is an array.

#

Arrays are not structs, and it's best not to confuse them with structs either.

tropic vigil
weary stag
#

Arrays are objects, which means the struct only contains a reference. Therefore, what you should instead do is this:

#

Is Tile.TileData a struct?

#

Can you show me that ^?

tropic vigil
# weary stag Is `Tile.TileData` a struct?

Yes. A serializable struct with instructions on how to serialize, thats is why serializing Board.Data works and I can receive properly serialized struct on another client.

weary stag
#

Okay, can you show me what TileData has?

#

Like take a screenshot and post it here.

#

I can give you a solution to finding the serialized size.

tropic vigil
#
[Serializable]
public struct TileData : INetworkSerializable
{
  public int id;
  public int x;
  public int y;

  public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
  {
    serializer.SerializeValue(ref id);
    serializer.SerializeValue(ref x);
    serializer.SerializeValue(ref y);
  }
}
weary stag
#

nice. good.

so in your Data struct's NetworkSerialize<T> method, serialize the size like so:

unsafe {
  serializer.SerializeValue(tiles.Length * sizeof(TileData));
}
tropic vigil
#

And what's it supposed to do exactly?

#

How is it anyhow related to my original problem?

weary stag
#

It'll let you get size of Data

#

which is what you wanted

tropic vigil
weary stag
#

For one thing, I have no clue why you have Data as a struct. Because it gives 0 performance benefits to having it as a struct instead of a class when you literally throw an array inside it.
Secondly, the only reason I imagine you wanna get the size of it (including the array referenced inside), is so that you can send it over the network so the other side knows exactly how much data to read. Which is what this does.

tropic vigil
weary stag
#

IF for whatever reason you don't want to send it, then here you go:

public unsafe int SizeOf() => sizeof(GridMode) + tiles.Length * sizeof(TileData);
#

Use this then ^

#

This will give you full size (in bytes) of public struct Data : INetworkSerializable

tropic vigil
weary stag
#

still considered XY problem, and I gave you solution up there.

tropic vigil
#

Your solution returned 19204. Mine returned 19216. Definitely one solution has to be wrong.

weary stag
#

Are you wanting to encode the data and the reference? Or just the data? (You mentioned you don't wanna send the reference)

#

If just the data, then mine is correct. If you want reference too, then 12 bytes (8 for reference, 4 for padding) added on top of mine = 19216

weary stag
#

Marshal.SizeOf(this) includes the reference size as i mentioned (8 bytes) = 19212 ... and then since you have a 64-bit computer most likely (reads in registers of 8 bytes), 4 bytes are added as padding (will be zeroed out bytes).

#

in terms of actual data you wanna send over the network, 19204 is the correct amount of bytes.

fluid totem
#

I would like to ask in a bullet hell game (lets say more than 100 bullet at the same time), which approach would you guys implement to detect collision of bullet to achieve maximum performance? 1. trigger collider 2. raycast 3. constant check of each bullet distance from enemy. Anyone has such experience?

tropic vigil
weary stag
#

The number you needed was 19208 because of padding.

#

You could just get the size, take 8 - (size mod 8), and add that on top of that, and bingo you got padding.

weary stag
#

Collider is next, but depending on speed of bullet, certain things will need to be enabled to make sure it properly detects collisions in Unity.

#

Checking distance is the slowest.

#

By raycast, I mean calculating vector in the direction of the bullet, and seeing if it intersects the character.

#

Not whatever other raycast one may think of ^^

sly grove
#

That sounds even worse than distance checking

sly grove
fluid totem
#

my thought on raycast is the Physics2D.Raycast

sly grove
#

"raycasting" is also vague

#

From what to what and why

#

Trigger Collider is also vague. Simply having colliders is not a complete collision detection strategy

#

So you'd have to be more specific

weary stag
#

It isn't. It's very simple math. You have the bullet's velocity vector, find two points from the velocity vector, formalize a line, and see if you (bullet's target) fall on that line (check if by substituting your x, you get the necessary y).

For 100 bullets, this code would at max take 500ns.

sly grove
weary stag
#

this happens once

sly grove
#

?

fluid totem
sly grove
#

Assuming the player never moves

weary stag
#

Again, the assumption is the bullet is so fast that the player never gets the chance to move.

sly grove
sly grove
#

Weird assumption to make

weary stag
#

No, I haven't. Which is why I specifically stated that assumption in the answer.

fluid totem
tropic vigil
#

The gameplay of bullet hell games is all about dodging the bullets.

sly grove
#

They are games with slow moving dodgeable projectiles

tropic vigil
#

Spherecast seems to be more suited to this genre since bullets are usually quite big and slow.

sly grove
#

That requires iterating over every bullet

#

Not ideal

weary stag
# fluid totem normal speed, which player can dodge

Then, raycast isn't maximum performance. As Praetor mentioned, the best thing you can do there is check distanceSquared. No need to take the sqrt, if you're going to collide, distanceSquared will also be 0.

tropic vigil
#

I know unity physics system has some optimizations included. I would suggest simply implementing different solutions and then comparing performance with the profiler.

fluid totem
#

Be more specific in 3, this is used in FixedUpdate ()

GameObject[] bullet = GameObject.FindGameObjectsWithTag("Bullet");
float cRadius = cs.property.hitRadius;
                    
Vector3 dis = bullet[i].transform.position - character[j].transform.position;
                    
                    if (Mathf.Pow(dis.x, 2) + Mathf.Pow(dis.z, 2) <= Mathf.Pow(bRadius + cRadius, 2)) { hit();}"
sly grove
weary stag
#

XD yep

fluid totem
fluid totem
weary stag
#

my god...

#

Usually, you'd have an array of bullets and reuse that.

#

To avoid instantiating them and then destroying afterwards.

fluid totem
#

I know, i have object pooling

weary stag
#

In which case, then the distanceSquared solution I mentioned would be best.

fluid totem
#

just want to be more specific on how to calculating distance

weary stag
#

It allocates an array that'll need to be deallocated right after.

#

Making the method a GC nightmare.

#

If you store a list/pool of all the bullets and just pass the list instead, you could have much faster code.

tropic vigil
#

Btw, Vector3.Distance seems to be optimized, so it can be used as an alternative to .squaredMagnitude:
https://youtu.be/Xd4UhJufTx4?t=182

Find what common Unity optomizations truly make a difference. In this video I go over a bunch of interesting optimization tips as well and give you my recommendations on each.

Keep your code running fast with as little garbage allocation as possible by learning from these important concepts.

Benchmarks (let me know if you get weird results!):...

▶ Play video
weary stag
#

And use my distanceSquared approach.

#

how is Vector.Distance more optimized than distanceSquared?

#

to calculate the distance, you literally have to sqrt(distanceSquared)

#

which is an extra step no matter how you try it

#

even with the fast sqrt approximation code.. it still is extra instructions

tropic vigil
somber swift
muted pilot
#

hi, i'm looking for an open source news feed to add to my unity social platform, does anyone know if i can get a completed project on this ??

normal lagoon
#

looking for a way to create local co-op in unity without the new input system
need a way to make it so each player prefab only accepts input from 1 input source, so the specific controller i somehow assign to it

dusty wigeon
dusty wigeon
# muted pilot hi, i'm looking for an open source news feed to add to my unity social platform,...

There is a lot of API for well know media outlet. If you want access to a special news feed, you will need to find out if they have an API. If they do not have or do not want to give you access, you will need to make a sort of Web Crawler for the specific site. Beware that such practice could be unethical (even illegal) depending on the usage you do with the information. https://en.wikipedia.org/wiki/Web_crawler

https://developers.facebook.com/docs/?locale=en_US
https://developer.twitter.com/en/docs/twitter-api
https://www.tumblr.com/docs/en/api/v2
https://discord.com/developers/docs/intro
https://en.wikipedia.org/wiki/List_of_news_media_APIs

frank peak
#

So I asked ChatGPT for help on my digital circuit sim and its answer was suprisingly sound lmao. this whole.. ai assistant thing could slap

frozen imp
#

@frank peak Please don't post off-topic here.

frank peak
#

sorry

weary stag
#

whatever benchmarking utility you use is flawed FYI

#

or your testing case is flawed (constant propagation, assembly determinant, etc.)

flint sage
#

Tip #1 is to not trust benchmarks posted here 😛

sand acorn
#

Hello there, does anybody know of an algorithm for checking between mesh vertices distance? I want to basically check if a vertex is close enough to another and then perform my logic

sly grove
#

Doesn't seem like an advanced topic.

flint sage
#

I'm guessing they're looking to optimise checking through all vertices in a mesh

sly grove
#

You'd have to explain the access patterns.

flint sage
#

Quadtrees might be helpful for you

sly grove
#

If you are doing this query over and over on a single mesh, and want to do something like get all vertices close enough to a given position, you can build a spatial acceleration data structure like a QuadTree

flint sage
#

Or looking up triangles edges and check those edges first sinec in most meshes those would be the closest

sand acorn
sly grove
#

if (distance < threshold) DoStuff();

#

again not an advanced topic

sand acorn
sly grove
#

what kind of iteration are you looking to do

#

which vertices are you wanting to comparing to which?

sand acorn
sly grove
#

some specific vertex?

#

Some specific position?

#

All other vertices?

sand acorn
sly grove
#

The fast way to do it is a quadtree

#

the slow way is a nested n^2 double for loop

sand acorn
#

on start

sly grove
#

ok so...

#

just a nested for loop

somber swift
sand grail
#

is there in the world any reason to use dijkstra instead of A*?

#

like i know A* is basically dijkstra that's greedy

sly grove
sand grail
#

but nonetheless i find dij useless

sand grail
#

as i know and have written A* takes only the shortest vals

sly grove
#

A* is little more than Dijkstra with a heuristic function and a specific target node

sand grail
#

ye

sly grove
#

it must

sly grove
#

since it builds ALL shortest paths

sand grail
#

i said it wrong

#

goes trough

#

but for shortest path i mean

#

since finding the shortest path is what people need most of the time

sly grove
#

Djikstra is very useful in a situation where your graph doesn't change often but you want to get the shortest path many times

somber swift
#

I dont think it needs to check every node either

sly grove
#

You can run djikstra and cache "signposts" to the next node on each node

#

then it becomes O(1) to do navigation from any given node

#

this is more or less how I do navigation in my tower defense game

sly grove
#

it's much faster than doing a full A* run for every enemy every time

sand grail
#

yea, that's where i wanted to get

#

for my npc's or enemies i am using A*

#

and i am doing an A* every time

#

for them to catch the player when he is in radius

#

so you sayin dij is faster for changing graphs?

#

@sly grove

sly grove
#

No the opposite

#

if you have to re-do dijkstra because your graph cahnges that's a heavy cost

sand grail
#

yea

#

that's what i thought

#

i was cofused caused i read your sentence wrong 😛

tiny pewter
#

for graph and target both are not change, just run djikstra once and store direction to target at every nodes

sand grail
#

yea, alr

#

i thought A* was better for both non changing and changing graphs

#

guess i was wrong

sly grove
somber swift
# weary stag this isn't true.

As I said the difference is very negligible, so it was in the video the other guy posted. Feel free to test yourself and not just say its not true because ”distance requires one more step”. If you expand the sqr distance check down to float math, it will be about 30% faster than distance but having to do Vector3-Vector3 somehow makes them about equal in speed. I dont know what exactly is causing that but maybe it has something to do with making copies of the struct values or something like that. Vector3 functions like Distance avoids doing vector operations because: current scripting backends are terrible at inlining

sand grail
#

curious

sly grove
weary stag
#

return Mathf.Sqrt(x) is slower than return x.

#

You should use an actual statistical library to do proper benchmarking.

#

I can give u the assembly too for the benchmarks if you'd like

#

and you'll realise it's 2 extra instructions.

#

sqrtss & add

somber swift
dusty wigeon
obsidian glade
dusty wigeon
#

Maybe, did not really follow. I just know that some people are obsess with these facts and I had to find out myself to clarify it with one of my colleague. I'm relaying information that I found while having a similar discussion.

The conclusion is:

  • Define Style Guide Rules for these situation. (Readability-Debuggability vs Performance)
regal olive
#

Hello everyone, I have an issue I cannot comprehend as it only occurs for one player that I know of. (The game is on Steam and was added as a zip file)

I have a slider to select value from min to max
The script is in two parts (normally linked as .txt) :
LinearValueSelectMain
LinearValueSelectValueLimited (which inherits from LinearValueSelectMain)

Here the value is between 0 and 1.
To show the selected value, the script checks how many digit after the period there is in the correct value. So for 0,21, it will show all value as x,xx.

It has always worked until a player told me they were only seeing 0 or 1. I have absolutely no idea why it would work for most people but one?

I asked the player to send me the log file which made me wonder if it could be possible if the correct value could be "lost"?

(I forgot to add the correct value in Debug.Log, I may ask the player to get me the log again if needed)

So, normally, the log should look like this :
PathDrive : GetValuesMinMax()
PathDrive : GetValueMinMaxPathDrive(), digit after , 2
PathDrive : update with new value : 0 as : 0,00

But for this player, it looks like this :
PathDrive : GetValuesMinMax()
PathDrive : GetValueMinMaxPathDrive(), digit after , 1
PathDrive : update with new value : 0 as : 0

The theory I have at the moment is that data got lost (because why would the script works for some, but no all?). If the correct value is lost, it will be at 0, so it would show nothing after the period in the selected value. Is it possible?
What could it be? (modifié)

weary stag
undone coral
#

i understand there is a bug with it

#

there might be many bugs, it's very complicated

#

it has bad starch

#

also what do you mean "normally linked as .txt" ?

#

it sounds like you are trying to author a slider that is interactable in fist person 3d / VR

#

can you show a screenshot?

#

is it used as part of a puzzle game?

#

why is there a rotationdrive?

regal olive
# undone coral this code is really complex. what are you trying to do?

The way it should work is:
it has a min value : 0, a max value : 1.
The correct value is given from the inspector : 0.21.
The player select the value by dragging the slider, from 0 to 1.
To show the selected value to the player, the script takes into account the number of digit in the correct value, here 2, and show that much of the selected value (so instead of showing 0.454511354, it filters to 0.45)

It worked for all the testing I did, it worked for 5 players that played from steam (on different computer, etc).
But, one player, told be they would only see 0 or 1
I really have no idea how the script could not run the same way for 1,

the normally linked as .txt was for to inform the big scripts where linked at the end

It is a slider for VR and non-VR, using SteamVR scripts (from the log I got from the player, it gets the update linear value as it should)
It is indeed a puzzle game, an escape game

And this script is for the PathDrive (inherit LinearDrive from SteamVR) and Rotation Drive, that's why it's there too, but will be ignore as the object only has a as pathDrive component

I'll send a screenshot in a sec, just time to make it

fresh salmon
#

They might be using a computer which does not use the comma as a decimal separator

#

Which is, most of the computers in the world

#

Values can be rounded culture-agnostic using a format string you pass to ToString. num.ToString("F2") - the number denotes the number of decimals, adjust to show more or less

#

Or, if you need the value as a number instead, say you need two decimals, multiply the number by 10 (to shift the decimal sep by two places), round to the closest integer, then divide by 10 to get the original number back, rounded

#

@regal olive

regal olive
fresh salmon
regal olive
dusty wigeon
# weary stag The point is that it's a slower operation than just returning the value. And the...

It is negligible... A modern CPU does more than 30'000 Million Instruction per seconds. Adding 1 instruction that does not require to load memory won't change anything. In fact, it is near 30 instruction per nanoseconds which means that it is negligible.

That being said, it is true, that adding an instruction will always be slower than not adding one. That being the case does not mean that adding an instruction is not negligable.

Most people say to avoid SQRT because, in the past, it was a lot slower. This is not the case today.

In my opinion, for a gameplay developer (not Engine, not Graphics), such decision are of the nature of code style and should be treated as such.

https://en.wikipedia.org/wiki/Instructions_per_second
https://developer.arm.com/documentation/uan0015/b/

autumn locust
dusty wigeon
compact ingot
#

any piece of code in a shader also (potentially) runs 495072000 times per second

autumn locust
#

just for the curious, its good to know if you're writing shaders

somber swift
# weary stag I have tested it myself.

I'd actually love to see how you implemented the test. So far I haven't found any way to "properly" benchmark my C# code in unity, with console applications BDN is really helpful but it won't work with unity. I'm really curious to know if there is some way to make proper benchmarks in unity relatively easily (this just shows that the ways I have been doing my tests isn't really the right way. I didn't mean to say that using Vector3.Distance is faster in general, just that the difference according to my tests (which may be flawed in many ways ikik) is so small that it sometimes was even faster)

weary stag
# dusty wigeon It is negligible... A modern CPU does more than 30'000 Million Instruction per s...

For one, it is not directly comparable to the throughput of division. That was a misconception you had.

On modern CPUs, and The latency typically ranges from 10-20 cycles, and the throughput ranges from 2-4 cycles. On older CPUs just as far as the 7th generation (2017 CPUs) Intel, the latency goes down to 28 cycles on certain ones, and the throughput up to 8 cycles.

Overall, that's as slow as a branch prediction miss, which has been a well known as an optimization target when optimizing game. The discussion isn't whether it can be just left in the code or not. The discussion is whether it should when a simpler, faster alternative is available with 0 added complexity. And that's frankly, a rhetorical question.

If you care about performance, remove it. It's practically an always occuring branch prediction miss. If you don't care about performance, then why are you even optimizing? Why would you even think of what is faster? Just make your code a performance nightmare, and as long as it works, it's fine.

weary stag
somber swift
dusty wigeon
# weary stag For one, it is not directly comparable to the throughput of division. That was a...

Did you even look at the documentation I gave you ? It clearly shows that FSQRT and FDIV are similar in both Latency and Throughput. It is true that on older generation CPU, SQRT might be worst, but you need to go far to actually see a difference where it starts to matter from a Gameplay perspective.

There are valid reasons why you would want to do the SQRT:

  • Increase Readability (Whenever you mean to calculate a distance, you should calculate a distance)
  • Increase Debuggability (Whenever you are keeping logs or even just inspecting variable, it is way easier to understand the content of what you are dealing with)

It is not about not caring about performance, it is about what actually matters or not. Whenever you are doing Gameplay, not Graphics not Engine or any other form of high computation programming, you should not care about performance that are negligible and should instead care about readability and maintainability. Also, when ever you have performance issue, you profile. And 100% of the time, not even an exaggeration, it is going to be because of something else. Removing a SQRT won't even be noticeable in the profiling of your game.

At the end of the day, the difference in both readability and performance is negligible and if you really care, you should define what is better for you in the code style of your company to keep an uniformity across your code.

https://www.quora.com/How-do-computers-calculate-square-roots
https://www.agner.org/optimize/instruction_tables.pdf
https://developer.arm.com/documentation/uan0015/b/

weary stag
# dusty wigeon Did you even look at the documentation I gave you ? It clearly shows that FSQRT ...
  1. You provided ARM documentation, which isn't the same platform for every CPU chip. It isn't the case for every CPU chip. And no you don't need to go much far, just go as far as the 7th generation Intel Chips and the overall speed decreases by 50%.
  2. The valid reasons are complete bullshit. As far as readability is concerned, you can just add comments explaining and every other future developer will know just as well. And as far as debug-ability goes, you can log the square root of the values. Most IDEs allow you to evaluate expressions when using the debugger, and say you use "Debug.Log" for debugging, just have it log the square root of the values.
  3. And it does MATTER. It doesn't matter to you because you don't really wish to optimise your code. Branch prediction failures, which take the same amount of time, are something developers of world-renowned game studios optimise away and notice at times massive speedups in their games. The same thing such as vector math, which will likely run before/after every frame in your game, would give you a huge speedup if you properly optimise it. Hence, why it does matter.
#

And stop linking me these documentation when they're literally useless to what we're discussing. Especially Quora documentations.

dusty wigeon
weary stag
#

That's exactly my point. 1 SQRT removal could save you 30ms.

dusty wigeon
#

No, not in gameplay

weary stag
#

and it could also only save you 10ns.

#

Yes, it can.

dusty wigeon
#

No, because you won't have this amount of SQRT.

weary stag
#

Yes, you will.

dusty wigeon
#

What you would do to have this amount of SQRT ?

weary stag
#

That's exactly what I'm telling you, you're so far in your head with your own experience that you disregard every other possibility.

dusty wigeon
#

I'm not even talking from experience.

#

What you would do to have this amount of SQRT ?

weary stag
#

Unity's OnUpdate() method runs every frame - on a device that can keep up a FPS ratio of 244FPS, that's a new frame every 4ms. Say your CPU has a clock speed of 4GHz (a very good clock speed), every CPU cycle would take 0.25ns. Moreover, lets assume you are doing about 100 SQRT operations for distance calculations per frame (usually there are more happening in games - and this is just gameplay, I haven't gotten into the engine/graphics area). That's about 500-1000ns added time. Given they are happening each frame every second, they're slowing your game by 122-244μs every second. Over the course of 5 seconds, your game has slowed down by 0.61-1.22ms.

Now, since we're considering FPS, 4ms + (122-244μs) = 4.122-4.244ms. So instead of your game running at 244FPS, you're now losing 2-6 frames and running at about 242-238 FPS. Have more of this stuff in maybe a loop, and that's even more frames you lose (just for gameplay reasons).

#

Not to mention, the above calculation was with consideration of a fixed clock speed (and a really good clock speed) and using CPU-cycle count for modern CPUs (Intel 13th Gen). Consider how much worse it would be with a CPU running at 2GHz on average and using CPU-cycle counts from older CPUs (Intel 7th Gen).

#

Small optimisations like these, whether that be in the engine side of things, graphic side of things, or the gameplay side of things are the reasons some games hit really high FPS on even low-level hardware really easily and why some struggle even on high-end hardware, when they're practically the same thing.

#

Nobody is telling you to think of every optimisation you could possibly do while you're making your game. In fact, that's a bad idea! It's known as premature optimisation. But simple stuff like this should be the foundation of good code. Don't add extra ops. if you don't need to (comments exist for readability).

austere jewel
#

As with most of these optimisations, they matter in hot paths where you might be running them repeatedly. The difference between Vector3.Distance and .sqrMagnitude, or math.distance and math.distancesq are measurable and not insignificant when in a tight loop

#

They are not at all comparable to a disk read or a Find call, but those things will not be found in tight loops, but you can find spatial queries using distances all the time

#

As for readability, once you understand what it is I find sqrMag/distancesq communicates more information, often indicating to me that you're comparing distances and don't need a literal distance at the end

dusty wigeon
#

Where I do agree that if you are working on device that are aiming at 244 FPS it is in fact non negligible if you have substantial amount of SQRT every frame,
I would argue that for every extreme situation where you want better performance, you have extreme situation where you want better readability.

One such situation would be the usage of event in a High End Console. Consider the following event:
public System.Action<float, ...> OnDetected;

If the first parameter is suppose to represent the distance, would you use the sqrDistance or not ?

austere jewel
#

You're if dealing with one value, not a tight loop, it's irrelevant. Also I would not write code with a random float in an action called OnDetected, that seems to be the problem with the code.

autumn locust
#

i have a O(n^2) algorithm for populating a space with asteroids, it has to measure + compare distances for that a lot.
sqrMagnitude is a real deal here

#

just to give a real world example

weary stag
#

If you write a method that returns say a tuple or a struct, you can either have documentation for the method to ensure the end user knows what it is returning, or have variable names accordingly in the struct.

#

Readability really isn't an issue. Neither is debug-ability.

dusty wigeon
#

Like you said, it is irrelevant. And more than irrelevant, it could decrease the usability of the code, forcing people to do SQRT operation. This is the extreme.

A tight loop, is not considered tight on every platform/scenario. Always preferring SQRT operation results in issue where it does not increase performance and could pay a price in unclean code where one would include both sqrDistance and distance signature for a function or event.

austere jewel
#

Another real-world example, I have a selection preview that gets the closest 3D line that is under your cursor. As there could be many many lines in the scene, it's all just square distances, clearly labelled

weary stag
austere jewel
dusty wigeon
#

There is no cost associated with such operation because of the nature of it. The distance has more utility than sqrDistance.

weary stag
#

There is cost associated with it though? It's cost of the SQRT op.

austere jewel
#

Of course it has more utility, but it has the exact same utility in the cases we're talking about swapping it for

#

and there is a cost associated with it, the cost is easily measurable

weary stag
#

Let me remind you: squaring a number is faster than taking square root of a number.

dusty wigeon
weary stag
#

That's the whole point.

dusty wigeon
#

It is.

#

That is the whole point.

weary stag
dusty wigeon
#

🤦

austere jewel
#

It's negligible in many situations, and you can choose where that threshold is for you and your projects.

dusty wigeon
#

Hence why you use style guide.

weary stag
dusty wigeon
weary stag
#

Yeah because they run at lower FPS due to performance issues.

#

So optimizing would give more frames.

dusty wigeon
#

No, it wont. Because most game are aiming at 30 FPS or 60 FPS.

#

Where it is negligible.

austere jewel
#

There's really no need to argue about this, it's a square root, you can measure it and make your own judgement calls

weary stag
#

Apparently most games in 2023 aim for 60 FPS. First time I heard that.

sly grove
#

Is this still the Distance vs SquareDistance argument lol?

weary stag
#

yeah because there are some delusional takes on what games in 2023 are aiming towards.

#

Like literally—60Hz+ monitors exist for no reason I guess if games aim only for 60 FPS.

warped galleon
#

Gotta find something else for everyone to argue about. Here's one - on Friday, my coworker insisted it's faster to compile implicitly typed variables (eg var) than explicitly typed ones (eg int). My stance was 25% doubt / 25% indifference / 50% code readability objections. Didnt have the time or will to benchmark. Thoughts?

austere jewel
#

sounds like nonsense to me

#

I highly doubt that something that has no structural implications would be relevant to compilation speed

dusty wigeon
#

Why would it be faster to compile implicitly typed variables ? Sounds non-sense to me too.

sly grove
#

Isn't there a whole extra step where the compiler has to infer the type with var whereas an explicit type skips that entirely?

flint sage
#

Yes

regal olive
#

hello all, i am having a problem with my level select because I have it ready and done but the fade in/out animation is not working, there is no error in my console and I dont know whats wrong

regal olive
#

i dont think this is beginner

sly grove
#

You are a beginner, it is obvious from the "there is no error in my console and I dont know whats wrong"

#

more experienced programmers know how to debug their code.

warped galleon
#

His line of reasoning was that the compiler doesnt trust the developer anyway when they use explicit typing. So there is still some unavoidable type-checking step. Never really explained why that would make it slower than var, but this was already one rabbit hole deep so I didnt push.

sly grove
#

benchmarks! ¯_(ツ)_/¯

flint sage
#

I mean there's always type checking

#

There's just not always type inferring

austere jewel
#

The compiler creates complex graphs and reorganises code, transforming it completely between representations, interpreting var or int isn't gonna factor into this

random dust
arctic lake
#

Is there a way I can turn off microphone permissions for unity so I can test if my code to request permissions works

sly grove
arctic lake
#

Thanks

warped galleon
#

I was hoping at least one person would take his side lol

weary stag
#

var based code takes longer to compile.

#

as compared to T based code.

#

It's my fundamental belief that var was the worst thing the .NET team came up with.

#

The IL doesn't even have anything known as var (afaik), which means it's always gonna be an extra step & hurts code readability when reading code outside of an IDE — say on GitHub.

scenic forge
#

I assume var has to be slower to compile, during the lowering step it has to be replaced with explicit type; but like I don’t think anyone really cares about compile time and the impact is probably minimal, people just take coffee break while stuffs compile anyways.

random dust
#

.NET Compilation time in general is very quick so var is nothing to worry about

#

So yeah, strong disagree, this is all purely opinionated at the end

scenic forge
#

var is definitely not the worst thing in C#, this language feature is not just in C# but also C++, Java, Swift, Rust, and basically every single new programming language these days

#

Just the sheer amount of languages that has this features should tell you how successful it is.

errant plinth
#

Isn't there something about you have to use var for some LINQ use cases?

scenic forge
#

Don’t think so, but LINQ gets pretty hideous to type explicitly if you stop at an intermediate step; and the bigger thing is that anonymous objects cannot be typed at all, which LINQ code used to use (which I would argue tuples more or less have replaced)

worthy lodge
errant plinth
sly grove
scenic forge
sly grove
#

oh - this is a feature I've never seen

#

It doesn't seem that useful to me though

scenic forge
#

It’s not, that’s probably why you never used it 😄

#

For intermediate types, tuples more or less have replaced it.

#

And anonymous objects can’t cross function barriers because they can’t be typed other than by var, so they are limited to be used only as intermediate types.

fresh salmon
#

I used anonymous types quite a few times (not in Unity) but I quickly replaced them with record and record struct types, which can be declared in one line and the compiler does the hard work for you

misty glade
#

Unity (or android OS?) appears to fire OnApplicationPause after 4 minutes of the app being in the background. Do I have any control over that?

#

Oh, actually, nevermind, it looks like I just accidentally fired that myself by tabbing back to the app exactly 4 minutes later

#

Hm.. not sure how to solve this problem.

Basically I have an idle game, the client updates game state locally and sends a save file up to the server every 60 sec or so. The server sends a keepalive to the client every 15 seconds. I'm encountering issues where the client has had the app in the background for hours but the server doesn't disconnect the client. When the client brings it to the foreground, then the connection is disconnected, but the server thought the client was connected the whole time, so it awards offline progress of "0 seconds".

Do I just want to disable the app from running in the background entirely (so it doesn't respond to keepalives in the background and the server can properly disconnect the client)? I suspect that experience is less than ideal since the player would have to login any time they tabbed out, even if it were for just a moment...

I think maybe what I'd like to have happen is the app (in the background) disconnects from the server if it's been in the background for >60 sec?

#

(Although I seem to recall that having unity apps quit themselves on mobile devices is not easy/normal)

#

I don't get the OnApplicationQuit event if I close the app using the Android OS - but the server successfully disconnects instantly

undone coral
misty glade
#

ordinary

undone coral
undone coral
misty glade
#

nah that'd be bad

#

TCP yeah

#

I just tested it out and a connection stayed alive for a full 6 minutes before dropping

undone coral
#

windows and linux have different tcp options

#

are you sure it's 6 minutes and not 5

#

also when you say keepalive, do you mean SO_KEEPALIVE

misty glade
#

it's allright.. I'm .. just hacking together something potentially stupid that I'll regret later.. having both server and client send keepalive packets and on the server, tracking the amount of time since the last I got from each client and manually disconnecting them if it's above a threshhold

undone coral
#

all of this stuff is kind of why tcp is horrible

#

not in some

misty glade
#

not sure it's 5 minutes, just pen-and-paper'd it

undone coral
#

you know, small brained sense

#

i mean that you have a lot of application specific knowledge

#

that doesn't map exactly to using tcp connections as sessions

misty glade
undone coral
#

and the client and server, including the network stack on phones which is not ordinary

#

interact in strange ways

misty glade
#

yeah i'm just surprised that the ... network connection stays alive but unity isn't doing anything anymore (in terms of update() and game loop stuff)

undone coral
#

in your backend, do you listen to tcp "disconnect" or "closed" events?

misty glade
#

the keepalive from the server doesn't require a response so .. the client just happily receives the networking message and ... does nothing

#

yeah, but that's the problem - the client remains connected even though the game is inactive

#

happily connected, might i add

#

it's ok.. i'm nearly complete with the above solution 👆 so .. 🤷‍♂️ i'll just do it that way, even though i hate it

#

it's probably not that big a deal sending 4 bytes and back to a few hundred people every 15 seconds but it still feels wrong

undone coral
#

(1) use udp, which are connectionless. use your own logic for when a session starts and ends, such as heartbeats
pros:

  • almost identical behavior across all platforms
  • few surprises
    cons:
  • you must adopt a real udp-based protocol. authoring your own is kind of stupid. too many details, too many bugs.
  • very rarely blocked altogether on some networks, like public wifis
    (2) use http. when the client needs to send a message, it posts to a well known url. the server streams events (server push)
    pros:
    - well documented support and behavior on all platforms
    - good support for scaling, SSL, operations like observability
    cons:
    - cantankerous
    - you must read the docs for numerous gotchas
    (3) use grpc.
    pros:
    - identical behavior on all platforms, since the code is exactly the same
    - well documented
    - compatible with most things that support http, like load balancers, for ssl, observability, etc.
    cons:
    - lots of faff to get started in unity
    - not compatible with web browser out of the box like http
    - backend server support can be weak
#

@misty glade you are using nude tcp with your own ad hoc wire format

#

which has none of the pros of any of these and only cons:

  • different behavior on every platform
  • poorly documented which features are supported where in unity and dotnet, for example how socket options differ between server and client on windows, linux and ios
  • poorly compatible with load balancing and observability
#

all you're going to wind up doing is reinventing udp on top of tcp

#

for example, you are trying to make tcp connectionless to work around the behavior of mobile devices, which is complex with tcp connections

plush hare
#

Generally for online games, writing your own RUDP transport is pretty bonehead easy. Nobody really uses TCP or any other hacky communication protocols unless you're specifically trying to talk to a web server (useful for authentication)

#

All you really need is a way to send unreliable UDP packets, and reliable UDP packets and you're set.

#

Obviously the RUDP shouldn't block the standard UDP packets on retransmission

undone coral
#

people use tcp because they use http

plush hare
#

Are the clients on web browsers?

undone coral
#

anyway, this comes from my experience making multiplayer mobile games

undone coral
#

PCs, phones

plush hare
#

If they're all machines running executables, then UDP is the way to go.

#

Nobody uses TCP for realtime stuff like this.

undone coral
#

udp is a bad choice for a lot of reasons

plush hare
#

Ok tell me

undone coral
#

okay imma take you on a little journey of deduction

#

in this journey, tell me, what game are you making?

plush hare
#

It shouldn't matter.

#

The only reason I could think of using TCP would be on a browser where I can't access UDP sockets

undone coral
#

hmm

#

@misty glade i guess this should tell you everything you need to know about this particular conversation lol

plush hare
#

If you're making a card game where players have 10 second turns, then sure, you could get away with using TCP

#

Nobody is going to use TCP for realtime shooters.

undone coral
plush hare
#

You have your state updates, which sit on the unreliable transport.
And then your actual reliable messages, which sit on the RUDP transport.

plush hare
#

I could probably name hundreds more

undone coral
#

rust is a shooter?

#

that's still just 1

plush hare
#

no its a card game

undone coral
#

so tarkov

#

any others?

plush hare
#

Considering rust is on top 10 steam charts, and tarkov is probably close behind, why the hell would I need to name any more?

undone coral
#

so 2 games?

plush hare
#

You are terrible at arguing

#

Considering you think "rust isn't a shooter" I'm convinced that this isn't even worth my time

#

Rust is one of the most innovative games in the past 10 years

#

There's a reason it sits consistently at the top of the steam charts

#

I still have no idea what you're trying to argue

undone coral
#

anyway you've shipped a multiplayer game and it works with tcp @misty glade. the biggest gotcha with mobile clients is that, using tcp alone, their answer for what is the state of the connection will very frequently disagree with what the server thinks

plush hare
#

ah yes, the old "I'm right, and I don't need to prove myself, so I'm going to ignore you"

#

wonderful

misty glade
#

whoa stepped away for a moment and le poo hit le fan 🙂

undone coral
#

yeah i don't know i'm just focusing on your issue

#

heartbeats have the side effect of resetting all sorts of timeouts

#

which in one sense is good

misty glade
#

lemme catch up one sec

undone coral
#

because they are arcane

misty glade
#

just fighting some fires

undone coral
#

the bad part is that you can easily get in a situation where your server leaves connections "open" that should really be closed

misty glade
#

the heartbeat thing is fine since it's not every frame, it's every 15 sec (or really configurable to be more - i don't think there's any load considerations)

undone coral
#

yeah yeah none of that matters

#

you could send a heartbeat every frame

#

this isn't a performance issue

#

i'm not talking about that i don't care about it, it will literally never come up

misty glade
#

the open connection thing isn't even really a problem.. the "problem" if any is that the client maintains the connection, but the server determines how much offline progress to award the client based on their last connected heartbeat

undone coral
#

well the performance issue is thread per connection, if you are doing that, but not like, how many packets you send or whatever

#

that isn't going to matter

misty glade
#

if they maintain connection the server thinks they're advancing in their game (which they aren't since the client is background-ed) so they connect and lose 5 minutes or so of progress

#

it's not a huge deal but it's .. annoying

undone coral
#

are you asking how to know when the app is backgrounded?

misty glade
#

guy plays a game, starts some missions, does some taps, etc, tabs out for 10 minutes, comes back and has lost half of that

#

nah, i can know that on the client but not on the server

#

i mean, sorta

undone coral
#

the client simply sends heartbeats to the server as long as the app is in the foreground

misty glade
#

it's OK, the heartbeat solution is in place and .. seems fine enough

undone coral
#

not the other way around

misty glade
#

yeah, that's what i'm doing

undone coral
#

ah

#

you shoudl be sending it every 400ms though

misty glade
#

well the server sorta needs to as well to kill truly dead connections

undone coral
#

not every 15s

misty glade
#

eep why that often

undone coral
#

why not that often.

#

sometimes i wanna rip my hair out

#

over these dogmas

misty glade
#

1000+ concurrents, hopefully

undone coral
#

but you will hit a resource wall with 1,000 concurrents only if you are doing thread per connection

misty glade
#

i mean, i suppose even at that load 1000 concurrents * 4 bytes for a header every 400ms is still trivial

undone coral
#

it has nothing to do with number of packets. you can literally process like millions of packets a second

#

if not 1b

#

1,000 threads * 4MB stack per thread is an example real limitation

misty glade
#

i'm actually using two threads per connection 😛

undone coral
#

but i don't know if you're doing thread per connection

#

well

#

i mean 1,000 concurrents is a lot. and 8GB of RAM is not expensive

#

but listen, if you wanna make your own session

#

that's just something you gotta do

#

it's unavoidable when dealing with mobile clients and notions of connectedness

misty glade
#

it's already done and.. hopefully live on android in canada later today 🙂

undone coral
#

the phone doesn't neatly map to what TCP ships with

#

the connection will be reset (RST) and therefore closed literally all the time

misty glade
#

yeah, the .. manual keepalive thing isn't great but .. I think my little project has been around long enough that I can call some decisions locked in stone and legacy 😛

undone coral
#

as the person is moving around and whatever

#

manual keepalive is great

#

i'm trying to say that you must write your own session, it can't be tied to whether or not a tcp connection is "alive"

misty glade
#

I pretty much get OnConnect OnDisconnect and OnData

undone coral
#

hmm.. but how does it decide when a user disconnects?

#

do you see what i am saying?

#

it's murky

#

that idea doesn't map neatly onto tcp and phones

#

if a user is playing your game on the subway, and happens to lose internet for 15s, and then comes back, and they've been foregrounded the whole time

#

do you see what i mean? OnDisconnect is really OnAdversePossiblyNotActionableNetworkEvent(NetworkEventType someTime)

misty glade
#

currently 4 situations:

  1. server is shutting down (forcefully disconnect all users)
  2. client disconnects voluntarily (user quits - not backgrounds - the app)
  3. server sends a keepalive to the client and socket reports that it's now disconnected
  4. client fails to send a keepalive for 60 sec
undone coral
#

and TCP has many of these, whereas UDP has almost none

misty glade
#

i mean actually i have to manage this shit anyway because our production server gets hammered with spoopy connection requests every few seconds

#

that's my staging server even, the DNS has only been allocated a week and it's already getting those all the time (on the game port!!)

undone coral
#

if the user foregrounds Messages for 16s, then foregrounds back your app, it was actually possibly all still running

#

and it changes

misty glade
#

that's fine - as long as they foreground it from time to time, that's 👍 .. it's when they background the app and never come back to it - the server thinks they're connected and advancing game state, but they're not, so they lose 5 minutes of progress

undone coral
misty glade
#

yeah

undone coral
#

what's frustrating is that this thing gives you an object you must now wrap

#

the lifetime of that socket object or whatever it gives you has nothing to do with the lifetime of the player's session

#

in clash royale the player's session simply lasts all 3 minutes

misty glade
#

essentially this

undone coral
#

it's divorced from network connectivity

#

uh oh, "timeout"

#

timing out what? there are like 3 kinds of timeouts in tcp, and 4 in linux

misty glade
#

not sure but i only get that one event from Telepathy

#

without going to deep into their stack, i only get 'OnDisconnected" for any/all disconnect events

#

I'm not gonna dig right now how it works .. would have to scour their codebase to see how the events are put into that receivepipe object

undone coral
#

there's

  • idle connections being closed (idle timeout)
  • tcp native keepalive (keepalive timeout)
  • start connection timeout (syn timeout)
  • unreachable host timeout (multiple things interact with this)
#

the first three are affected by any loadbalancer/termination you have, such as azure load balancer

#

this is to say that telepathy does some wrapping around these and presents them all as a disconnect event

#

lemme give you some actionable knowledge lol

#

@misty glade the absolute best way to test these issues is to exactly test them with real hardware. however, since that's hard to automate, the best thing i've used is ToxiProxy

#

toxiproxy can simulate all the different kinds of real network failures effectively

#

for example, telepathy probably correctly gives you "connection reset by peer" if you force quit the client application (equivalent to a background kill), but it will give you nothing if the client's LTE connection gets spotty for longer than 15s

#

which will happen all the time! it's a mobile game

#

people will literally play on LTE at home, where they have 1 bar

#

and they will be unable to do anything because the connection is too poor, but your server will think this connection is lasting forever and they actually disconnected a while ago

#

here's what really happens: the player is on the subway, the connection gets spotty, then they do something else

#

ios background kills the app while they have 0-1 bars, and the reset packet is never received by your server

#

the connection is never restored

#

another thing that happens: the player is on the subway, the connection gets spotty for more than 60s, and the server thinks the user has disconnected because the user didn't reply to a keepalive. then all the queued up network traffic the user has been sending those 60s arrives, including keepalives. now the client, which abruptly receives a reset, is very confused. AND it's impossible to know how telepathy handles this without reading the source code, because an "unexpected reset" is different than seemingly asking the connection to close gracefully, as you do in the code when a keepalive isn't received in time.

misty glade
#

These are all already handled - the player can't really play the game with a crappy/invalid network connection - nearly everything in the game requires some connection to the server.. but the one thing that they can do that I wanted to cover was idle completely - even with the app in the foreground this requires a connection to the server (ie, "check for a rare spawn" or "get a list of how many players are waiting in the queue for battles")

undone coral
#

hmm

misty glade
#

if a player is actually disconnected for more than 15 seconds then they aren't having a very good time

undone coral
#

well i think you are in for a lot of surprises

#

i could only prove that my game servers deal with these issues correctly using toxiproxy

#

and grpc has a good general model for sessions, one that's so good it's become WebTransport (i.e. rpc for http/3, which is "just" grpc over quic)

#

honestly i don't think the telepathy guys would know either

#

why would they? they don't make or play mobile games

#

they are the people in the audience in blizzcon booing diablo immortal and listening to that guy say "do you not have phones?"

undone coral
#

use toxiproxy if you want to fix this stuff

misty glade
#

it sends a packet, the packet fails to send and the client connection OnDisconnects

undone coral
#

are you doing await SendPacket()?

misty glade
#

I'll check it out but so far (a month on steam) we haven't had any issues with connectivity/etc

undone coral
#

but that's steam

#

that's PC

#

that's broadband internet

misty glade
#

fair, but also starlink sucks 😛

undone coral
#

nobody is going to have spotty connectivity in that situation. every single phone has spotty connectivity

#

lemme ask you this

#

let's say you do await SendMessage()

#

is this what you do?

misty glade
#

we're also on phone too fwiw, but limited users there

undone coral
#

something that looks like that?

#

or is it await SendMessage(timeout: 15f)

misty glade
#

on the client? i send them synchronously

undone coral
#

okay same diff

#

so you send it synchronously whatever

#

what happens?

#

do you handle a TimeoutException?

#

do you configure the WriteTimeout? the default is "infinity"

#

whichi s what is going to happen on a spotty connection

#

so it won't throw an exception, and it will hang forever, and it never finds out if the packet failed to send

#

because there are many situations where that is unknowable for a long period of time including possibly infinitely*

#

and unfortunately those situations happen a lot in phones

#

and your game logic that queued a message to be written by your networking thread

#

will happily churn along

#

a message possibly never sent

misty glade
#

sorta - i have a timeout on the client socket polling (150ms)

errant plinth
#

When I worked on an Android app that had a BLE connection to a peripheral I encountered a bunch of issues with different Android phones handling background processing differently. Not sure if the case is same for data/wifi connections.

undone coral
#

do you interrupt the writing thread?

#

what do you mean client socket polling?

#

you only have one connection

#

you could be stuck on sending the heartbeat message lol

#

so WriteTimeout (a real timeout) versus your heartbeat, they are different things

#

in fact if you do this right, you'll want to be sending a lot of heartbeats, because it is much simpler to deal with those failing to send within a specified time (i.e. failing to receive an ACK from the server) versus game logic messages

lyric bay
#

Is anyone free for a sec to help me out with some neural network stuff?

austere jewel
lyric bay
#

So I have a simple neural network that I have pieced together from a couple of tutorials... I am using TanH activation and Xavier weight distribution to train against the pokemon type matchups, which I have in a CSV.. First few rows of the dataset are here...

TypeA,TypeB,Immune,Not Very Effective,Neutral,Super Effective
Bug,Fire,0,1,0,0
Bug,Grass,0,0,0,1
Bug,Fighting,0,1,0,0
Bug,Poison,0,1,0,0
Bug,Flying,0,1,0,0

In my code, the types (Bug, Fire, etc) get turned into an integer and then normalised before being passed into the net. The network at the moment has 2 input nodes, 3 hidden layers with 17 nodes each, and 4 output nodes (for each of the outcomes... Originally it was only one output but it seemed logical to have 4 for each of the categories). I am using mean-squared difference to adjust the weights of the nodes.

For some reason, after training for 1000 iterations (which I know isn't a lot, but 5000+ takes 5 minutes because it's not multithreaded yet) with a learning rate of 0.03, all of the outputs are the same for every type match up that I test so something is going awry... I have never really touched this before so I am a bit lost lol. Let me know if I can give you any more info

undone coral
dusty wigeon
undone coral
#

it's not clear what you are trying to do

placid shell
#

Wondering how i would get a position in Ulam's spiral (aka the square spiral) given an index? (Trying to generate blocks in a spiral around the player)

dusty wigeon
placid shell
dusty wigeon
#

I mean, what is the size of the spiral you are working with

placid shell
#

i do not know I'm afraid, i have an excel spreadsheet i could screenshot if that would help?

dusty wigeon
#

What are you doing ?

placid shell
dusty wigeon
#

Yeah, you gotta put a limit on those blocks...

#

Unity is not magic, nor computer.

#

What you want to do ?

placid shell
#

I'm afraid i don't understand

dusty wigeon
#

Is it a graphical effect ? A gameplay mechanic ? A simulation ?

placid shell
#

oh ok, so basically I have a 2d randomly generated terrain type game, and i want to the terrain to generate in a spiral around the player rather than just a large box, cause it would be more performant, the way i plan to do this is for every frame the player has not moved, add 1 to a counter, then grab the spiral position by using the counter as in index into the spiral, and generate that block

dusty wigeon
#

It wont be more performant. But I can see the aesthetic.

#

So, is it only for the aesthetic ?

placid shell
#

nope, performance, I've tested the performance by switching to choosing a random position, and it is more performant, the spiral just makes it so the stuff closest to the player generates first

dusty wigeon
#

That is not how performance works.

#

What did you measure ?

placid shell
#

sorry, I've done a poor job explaining what I'm doing exactly. Let me retry:
so scenario 1, the current way is to take a 100 by 100 area around the player and check each spot to see if it is generated, if not then generate it.

scenario 2, generate 1-5 blocks every frame in a spiral pattern, meaning that insanely large areas can generate without having to do everything in 1 frame

dusty wigeon
#

It has nothing to do with the fact that you are generating in a spiral manner.

placid shell
#

performance is technically the same, but scenario 2 will feel much smoother, to test this i used picking 5 random positions each frame and generating them, and yes it does feel smoother

dusty wigeon
#

You choose to do so for aesthetic reason.

placid shell
dusty wigeon
#

Generating on multiple frame instead of 1 is common optimisation.

dusty wigeon
#

There is multiple way of doing so. Chunk and Distance by example.

#

So, now that I know what you are trying to do.

#

I now that you do not require random access.

#

And that you can simply use simple incremental algorithm.

placid shell
#
for (int i = 0; i < BlocksToGeneratePerFrame; i++)
{
    GenerateBlock(SomeFunctionToGetPositionFromIndex(FramesSinceMovement + i));
}
``` essentially
dusty wigeon
#

I would try to exploit the architecture in this way

#

This way, you know whenever you need to * turn *.

placid shell
#

something like that yes, I just can't work out how to go from an index to a position in that spriral, I'm not good enough at maths

dusty wigeon
#

I mean it is not math... To be honest, I would use trial and error and not try to come up directly with the answer.

#

It is only finding the correct imbrication for.

placid shell
#

I have been using trial and error, nothing works, there is no info on the internet about any of this

dusty wigeon
#

Just exploit the architecture I presented you.

#

I won't do it for you.

#

There may be a better way to do it.

placid shell
#

I've been trying to do that for days... Nothing works, unless i want to manually create a lookup table, and that is slow and tedius, but I'll keep trying...

#

i need to find a pattern somehow, some relationship between the index and when to turn, and how long the side length should be, but i suck at pattern recognition....

dusty wigeon
#

I gave you the pattern...

#

"when to turn" is litteraly there

#

See how every scare is a scare

#

1, 4, 9, 16

placid shell
#

no?

placid shell
#

I'll keep looking for a pattern, i hope I'll find one

dusty wigeon
#

Do this for every step

#

Then extrapolate the algorithm

placid shell
# dusty wigeon

fascinating, I'll try understand this, but it will take me a while, as i don't understand where you got 16+1 from, or any of the other numbers, sorry I'm not clever

dusty wigeon
#

1+1 Turn
1+(4-1)/2 = 3 Turn
4+1 Turn
4+(9-4)/2 = 7 Turn
9+1 Turn
9+(16-9)/2 = 13 Turn
16+1 Turn
16+(25-16)/2 = 21 Turn

placid shell
#

fascinating, still don't understand where you are getting those numbers from, but I'll continue trying to understand it...

misty glade
#

You should generate your terrain using noise (Perlin Noise, for example), not try to reinvent the wheel..

dusty wigeon
#

Previous Sqr + 1 Turn
Previous Sqr + (Next Sqr - Previous Sqr)/2 Turn
Increment Sqr

placid shell
dusty wigeon