#archived-code-advanced

1 messages ยท Page 122 of 1

echo coral
#

I use async a lot in mobile games and i dont tank the game this bad.

untold moth
#

Well, that could potentially be the cause.

untold moth
echo coral
untold moth
#

But perhaps it's not the cause. Take a screenshot of the whole profiler

#

It's weird that the player loop doesn't show anything.

slate spoke
#

though... I think I fixed it a bit..? a lot of the functions use NativeArrays, and I had them all using Allocator.Persistent

#

after changing them to Allocator.Temp though, seems like something broke along the way

untold moth
#

Why are you using native arrays?

slate spoke
#

Some of the things I'm using only accept native arrays, such as the indirect mesh renderers

slate spoke
#

I am so far out of my depth here I swear lmao

echo coral
#

im more confused with each message what you are actually doing ๐Ÿ˜
async will make using the profiler hard so use Stopwatches to time specific things

slate spoke
#

I'm gonna have to pause work for tonight but I'll figure out how stopwatches work in the morning and get back to y'all

slate spoke
# echo coral im more confused with each message what you are actually doing ๐Ÿ˜ async will mak...

the overall idea of what I'm trying to do is parse a 600k point dataset (that has arbitrary XY coordinates) into a landscape where each datapoint is represented as a plant. To make that work logistically, the plan so far has been to procedurally generate the terrain chunk by chunk, with each terrain chunk having it's own compute shader that renders only the plants that fall within the coordinate range of that specific chunk

#

I already know that it isn't the mesh generation that's super performance costly, at least not with how it's configured currently

untold moth
#

What is this set to? It's not the default option, is it?

#

Your profiler hierarchy is weird atm

slate spoke
#

currently set to inverted hierarchy, this is how it is with the normal hierarchy

untold moth
bleak citrus
#

are you starting thousands or millions of tasks all at once...?

untold moth
#

Or just logging a lot of messages

slate spoke
slate spoke
untold moth
#

Reducing logs to not print every frame would help too

slate spoke
# untold moth Fix all these and profile again

I'm not entirely sure how to fix that currently. I guess I'd need to start it with the indirect mesh renderer component on each chunk disabled by default and enabled once it has a nativearray of coordinates, but I can't figure out the logistics how to actually do that

#

This is the function responsible for when that render actually happens, for context ```C#
public async UniTaskVoid GetChunkPlantData()
{
while (parq.kdTree == null)
{
await UniTask.Yield();
}
Vector2 rangeMin = await parq.GetCoordinateBoundMin(chunkIndex, parq.plantMapSampleScale);
Vector2 rangeMax = await parq.GetCoordinateBoundMax(chunkIndex, parq.plantMapSampleScale);
df = await parq.GetTerrainChunkDataFrame(rangeMin, rangeMax);
if (df.Rows.Count >= 1)
{
rawCoordinates = await parq.GetCoordinatesAsNativeArray(df);
rawCoordinates = await parq.ScaleCoordinateArray(chunkIndex, rawCoordinates, rangeMin, rangeMax, chunkScale);
rawCoordinates = await GetPlantHeights(rawCoordinates);
kdTree = await MakeChunkKDTree(rawCoordinates);

        coordinatesForRendering = await DoubleInstanceCount(rawCoordinates);

        UniTask.Void(StartRender);
    }
}```
untold moth
slate spoke
#

yeah fair lol

#

I think I might've figured that out just now though thankfully, realized that I should be checking if df exists in the Update loop as well as within this function

#

Yeah, there we go. For some reason the 1.3 million alloc calls are back though

#

at least the indirect mesh renderers are working again

untold moth
#

And possibly, allocating garbage in them as well(which might be hidden by the async implementation). I'd start from reverting all the async methods back to normal methods.

austere jewel
#

UniTask shouldn't be a huge allocator

#

Just properly profile it and you'll see what's allocating

untold moth
#

Yeah, but it probably hides the real allocations

austere jewel
#

There's almost no chance UniTask is allocating 2.8GB

scenic forge
#

According to the screenshot, there are 1.3 million calls to GC.Alloc

untold moth
#

I bet the native arrays that they mentioned earlier are the real cause.

scenic forge
#

That's very suspicious. Do a deep profile to see what exactly is allocating.

scenic forge
austere jewel
#

Perhaps a loop over vertices

#

I'm just guessing, but if so, calling mesh.vertices.Length or similar is allocating the entirety of the array just to read the length for each iteration of a loop

untold moth
#

When unity naming conventions for properties bite you...

scenic forge
#

More so that it shouldn't have been a property in a first place. It being a method like GetVertices() would make it very clear that for (var i = 0; i < mesh.GetVertices().Length; i++) is not a good idea. Or other properties like .material creates a copy that you need to destroy. All the hidden footguns ๐Ÿ˜ข

slate spoke
scenic forge
#

Do a deep profile and see what's allocating.

untold moth
#

And that can happen anywhere where the GC pleases.

slate spoke
bleak citrus
#

it's an option in the profiler

#

it's equivalent to slapping profiler markers on EVERYTHING

bleak citrus
#

O(no)

bleak citrus
#

If you have a vague idea of where the allocations are, manually inserting profiler markers will be a lot nicer

slate spoke
#

I'll try that tomorrow, I'm off the clock for now

novel plinth
#

High perf + Async-await doesn't get along too well, that's not the point of the current async-await.

#

just saying, thread switching ain't free

untold moth
#

Sure, there might be a solution that is more performant, but you also have to balance out the costs vs the actual gains.

novel plinth
#

async + perf will hardly, unlikely be a perf

#

note, that I'm not disagreeing with you here

untold moth
#

Again, it depends on the use case. It would be totally fine for offloading file reading/writing or some other work to a background thread. Of course, you wouldn't use it for computations(unless you're fine with them taking some time).

#

Which is arguably part of game performance, because if you were to do it on the main thread, it would kill it.

crisp temple
#

On the topic of threading, how does everyone here run their jobs if you want to start a job at the beginning of the frame, let other stuff run, then only force complete by the end of the frame? Seems like something that should be simple but the examples I've seen so far add tons of boilerplate vs. just doing all the job management in a single method like Update()

echo coral
echo coral
#

oh right. well i would not use this because if it takes longer than your target frame rate time its gonna look shit.
Id either try to await the completion/have some code to run on completion

crisp temple
#

Yeah it doesn't, I've got it all in Update() at the moment and it works fine, but I don't need the results til the end of the frame so trying to optimize further

echo coral
#

Well in reality you are just waiting for it to be ready at some point during some frame and then using the results which is a good way to do it.

untold moth
#

Or you could wait till the next frame.

echo coral
#

there is no guarantee the thread/job gets executed soon enough but if the work is small it probably will. But then the question arises as to why use a job/thread if its that quick ๐Ÿค”

abstract hill
#

Hi everyone, I'm working on a pattern check in my chunk genration system where it iterates over a cell and its neighbours and determins if it fits specific patterns.

I "could" have 4096 cells in a chunk and virtually an unlimited amount of patterns to check (though more realistically it will be closer to ~16 to ~64 cells, and ~20 patterns). This check will be done once on chunk generation, what I was wondering is this:

How would I best go about converting this to a job, right now I have a ParallelFor job that takes in the cell coordinate, its neighbouring cells and then iterates over all patterns checking which fit given the current data.

This works great for parallelising the pattern / structure checks, but it doesn't solve the other issue that I also need to perform this check for many other cells. This intern basically turns into a nested for loop.

foreach (cell in cellList)
{
  neighbourData = get the current cells neighbours 
  foreach (pattern in patternList)
  {
    do the pattern check with neighbourData.
  }
}

The current implemententation is this:

foreach (cell in cellList)
{
  neighbourData = get the current cells neighbours
 
  IParallelForJob check all patterns....
  Output first pattern that fits....
}

So specifically, my question involves how best to work with nested loops, given that jobs cannot be called from within other jobs. I know I could create a large dataset and then pass it all in as one massive loop but that setup time would take more time then its worth parallelising it. Any thoughts on the subject would be great!

untold moth
echo coral
untold moth
#

Other than that, maybe your approach is fine. Is there any actual issue with it?

abstract hill
# untold moth Well, one thing you could do is have the data always in a form that is ready for...

The main issue is that I want to scale this up, right now it works but has some performance dips, that said it works with only a couple of pattern checks in very controlled enviroments. I want to be able to have this system be much more in depth and for that I need to be able to get rid of the main cause of the slow down.

The main reason I cannot have the data always in a form that is ready for this is because it may need information from chunks surrounding itself. Though with that said, I could pass in the chunk data from those.

#

Thank you, I may give that a try, and format the loop so I don't actually need to pass in the neighbouring data.

untold moth
ebon abyss
#

Having a fun one. _currentSpell is throwing a missing reference exception. It's an interface, but the underlying type inherits MonoBehaviour.
This is called during an animation callback.

#

Also attempted this to get the proper Object lifetime check but that either isn't the issue, or it doesn't work that way

sage radish
sly grove
ebon abyss
#

Yep. AimTarget is never changed.

sage radish
#

Nothing in that line can throw a MissingReferenceException, except for aimTarget.position if aimTarget is a serialized field that is unassigned.

Is the exception coming from inside EndCast?

sly grove
#

so you need to do this:

if (_currentSpell is not UnityEngine.Object uo || uo != null) {
   
}```
#

oh yeah which line is throwing it btw

ebon abyss
#

That one ๐Ÿ˜„

#

transform doesn't exist

sly grove
#

yeah ok so _currentSpell was destroyed

echo coral
#

I often add a gameobject get property to interfaces for this purpose (if i know its for component use only)

#

is annoying how unity do their native object destroy checking via Equals though :/

sly grove
#

UnityEngine.Object.IsObjectDestroyed(UnityEngine.Object o) and similar would have been lovely.

ebon kraken
#

Hello i have a game manager for a dice game that controls the flow of the game, once the dice have stopped moving (meaning they landed) i trigger a dotween animation that sends an event when its finished so that the game logic can continue (let player roll again) I just wanted to ask if this is the best way of handling the animation or if theres a better way

private void Start()
    {
        diceAnimator.OnMoveDiceToCamAnimationComplete += DiceAnimator_OnMoveDiceToCamAnimationComplete;
        diceAnimator.OnMoveSingleDiceToCam += 
DiceAnimator_OnMoveSingleDiceToCam;
    }

    private void DiceAnimator_OnMoveSingleDiceToCam(object sender, DiceAnimator.OnMoveSingleDiceToCamArgs e)
    {
        if (playerDice.Contains(e.dice))
        {
            e.dice.GetLastLandedFace().TriggerFaceAction();
            playerScore += e.dice.GetLastLandedFace().GetValue();
        }

        else
            computerScore += e.dice.GetLastLandedFace().GetValue();

    }

    private void DiceAnimator_OnMoveDiceToCamAnimationComplete(object sender, EventArgs e)
    {
        gameState = GameState.WaitingForPlayerInput;
        DetermineWinner();
    }

    private void Update()
    {
        if (gameState == GameState.WaitingForPlayerInput && Input.GetKeyDown(KeyCode.Space))
        {
            RollDice();
        }
    }




    private void RollDice()
    {
        foreach (Dice dice in playerDice.Concat(computerDice))
        {
            dice.UnlockRigidbody();
            dice.Roll();
        }
    }



    private void OnDiceStopped(object sender, Dice.OnDiceStopRollingArgs e)
    {
        diceStoppedCount++;
        if (diceStoppedCount >= playerDice.Count + computerDice.Count)
            StartDiceAnimation();

    }

    private void StartDiceAnimation()
    {
        gameState = GameState.AnimatingDice;
        diceAnimator.StartMoveDiceToCamAnimation(playerDice, computerDice);
    }```
regal lava
#

sounds fine to me. If it's a linear sequence then there's not much you can do wrong

#

personally I just calculate the animation time beforehand and await that duration instead of relying on the animator, but if this works it works

misty glade
#

Ok, I'm about to off myself. Memory issues are back. Context: I've got a (finished) webgl product that I've built in release mode which (often-ish) crashes with out of memory errors and no useful information (it's a javascript stack trace and a bunch of unnamed function pointers in my code).

In dev mode, I cannot make it crash.

I've updated to the latest 6000 unity build since there was a note in a recent release about a bugfix potentially related to this: https://unity.com/releases/editor/whats-new/6000.0.30#notes

  • Web: Fixed WebGL errors when heap is larger than 2 GB. (UUM-85702)

I have no issues with a windows build and editor play. I started down the memory profiler, but I'm not convinced this is a memory issue since the dev build works just fine.. it's only the brotli compressed build that's having issues.

Looking for guidance. I have two links handy if anyone wants to try this out on their own (itch.io).

dusty wigeon
misty glade
#

I do have the chunk of code where it seems to be failing - it's some pathfinding code, but it works and doesn't soak memory in the editor, so I'm not sure it's the active culprit - but just rather a part of code where allocations need to happen.

#

2gb memory limit

#

(the game does have quite a few models, animations, sounds, textures, etc - it uses a lot "normally")

dusty wigeon
#

And how close are you from this limit ?

misty glade
dusty wigeon
#

Memory varies a lot, sometimes you need a good buffer you prevent crashes.

misty glade
#

HexPoint.TryGetPath() is my code

#

but the actual failure is just on adding a member to a list - not even a big list, but I'm exploring it just to make sure

dusty wigeon
#

Yeah, with OOM it is kinda hard to know if it is the actual code the issue.

#

But you should be able to see it growth.

#

Also, I've never developed on WebGL, but it seem that the garbage collector behavior varies in the web compare to the desktop. The situation describe could potentially be something you see in your Pathfinding algorithm.

https://docs.unity3d.com/Manual/webgl-memory.html

misty glade
#

that page has been up on my screen for the last week ๐Ÿ˜›

dusty wigeon
#

You could try to put manually more pressure on the memory to see if you can make it crash in a development build.

#

But again, it is strange that you are not seeing any change in memory.

untold moth
# misty glade

There must be a way to output a crash dump and also debug symbols(even in a prod build). If you have the two, you could open it in VS and investigate the callstack/variable values.

misty glade
#

what you see in the screenshot is all i got.. the debug symbols are in it so I have a rough stack trace but... it's just failing on a list.add

#

I've even just added this:

#

and the "oops" message is never seen

#

(that's the only .add() call in the method)

echo coral
#

well we can see in the stack the list tries to change its capacity and it causes the crash

#

remember a list can resize up or down and must relocate each time

misty glade
#

yeah... I mean.. I suspect there's a bug here in my pathfinding code but .. it's so odd that there's no spike in memory on my machine, and the method works just fine

dusty wigeon
#

The last time I had to investigate a memory crash that was not showing in profiler (because it was native memory), I had to try to disable each feature one by one to see which one was responsible. But I knew it was a memory leak though.

dusty wigeon
echo coral
misty glade
#

lemme see if I can tell.. I don't have the windows module and memory profiling package on this version of unity but I can get it

#

like, there's a lot of List.Add() in that code - but it's "normal" (ie, pathfinding needs to enumerate each hex in the path)

#

code like this for 15 units is over 1000 calls

#

but like, it's fine

echo coral
#

you could replace the list with a static native list with a large capacity? something to prevent constant reallocation on the heap

misty glade
#

each unit is doing what it's supposed to - like, their logic is "find the closest good guy" which means it has to pathfind to every one of 5 good guys (times 15 bad guys)

dusty wigeon
#

It could quickly become a lot of memory if it is not freed in the frame.

misty glade
#

i could, yeah.. i mean, that would save several thousand add() (and check for capacities) beforehand but.. this still should be small .. like 10-20kb

#

not 2gb

#

lemme just add a quick static counter to check

dusty wigeon
#

You are busting by 2g ?

#

Because, sometimes you really are closer to the actual limit. I flirted with the upper bound of memory for the switch a lot.

#

(Also, logs potentially can add GC alloc)

misty glade
#

1100 adds in the frame (but there should be adequate time to GC)

#

there's no logging on the server production build

compact ingot
misty glade
#

I have to reinstall it (I updated unity today) - i don't have the package in the project atm

echo coral
#

it cant happen whenever

misty glade
#

hm, ok, that's useful.. although these adds are for very small structs

#
    public struct HexPoint : IEquatable<HexPoint>
    {
        public readonly int X { get; }

        public readonly int Y { get; }
    }

echo coral
#

but the list resizing will move to a new array and the old array wont get deleted

misty glade
#

essentially just that

compact ingot
#

are you just guessing where the problem is or do you know this list is the problem?

misty glade
#

oh also those 1100 adds aren't in one frame - that's over like 10 seconds

#

I'm just guessing but I have a stack trace in this method that says the add is where the malloc fails

#

I can paste the entire pathfinding code but .. it's not light reading :p

compact ingot
#

ok, but thats most certainly not the culprit

#

it just surfaces the out of memory

misty glade
#

it is where it crashes consistently so.. at least that's progress

compact ingot
#

yes, that is likely, because its a very dynamic point in the code, but you likely have a leak someplace else

#

not even a leak, maybe you just have a lot of memory usage by accident

#

maybe a single native shell of a texture your're keeping around

misty glade
#

ok memory profiler back in the project.. I'm not an expert with this tool - do I want a snapshot before/after the incident? or is there a way to record a few frames with it

compact ingot
#

or a copy of a vertex array

dusty wigeon
#

You want to snapshot at two distinct point in the same scenario.

misty glade
#

this pathfinding code has a lot of recursion in it - i honestly wouldn't be surprised if it's temporarily using a huge bite of memory, which would be a problem, if not the problem

compact ingot
dusty wigeon
compact ingot
#

might be an idea to remove the recursion or make it tail recursive

dusty wigeon
#

If you ever doubt it is the issue.

misty glade
#

happy to have you take a peek ๐Ÿ™‚

#

this is my static hexpoint class - it just contains x and y, with a whole host of utility methods

#

the method in question is TryGetPath down near the bottom

#

A* pathfinding for hex grids.. so.. yeah, it's a bit dense but .. hopefully? it's readable

#

i kinda hate the syntax highlighting on pastebin.com - lemme know if you want to read it and prefer another site's styling

dusty wigeon
#

I'm not sure I see the recursive though

misty glade
#

yeah I don't either.. ha.. I thought it was. I guess it's just a while loop

compact ingot
misty glade
#

I'm looking over the snapshot now.. i couldn't get it close enough to the "event" so I'm trying again

#

here's the baseline though:

dusty wigeon
#

You need to snapshot before it crashes though

#

(You need both*)

echo coral
dusty wigeon
#

Also, you captured the editor

misty glade
#

I can't get it to crash in editor - only for production builds in the browser (since there's 2 gb heap limits in the browser, i imagine)

echo coral
#

yea cus anywhere else it will GC whenever it wants

misty glade
dusty wigeon
#

I know, but Editor Memory Capture are terrible to distinguish correctly what is happening.

misty glade
#

how do i capture memory snapshots in browser builds? I wasn't aware that was even possible

dusty wigeon
#

No idea, but you can do it in a standalone build.

#

It will be more representative

misty glade
#

i couldn't get the crash in a standalone build

#

(I can't even get the crash in dev builds)

#

dev builds on web gl, to be clear

dusty wigeon
#

No need to make it crash, just to see if you can spot something growing.

echo coral
#

so again when you go to pathfind and have your list grow and grow... BAM crash

misty glade
#

yeah but i mean, only only allocating like... 20? 30? adds per frame, nothing unreasonable

echo coral
#

but you dont give your lists a starting size so they may re allocate a few times

misty glade
#

even if it were 1000 adds per frame (with the struct with two ints) that seems like it should be .. fine?

#

fair, I mean, I can add that (and it's a good idea) but .. I'm not sure it's the issue

echo coral
#

I see a big grid and i dont know how many pathfinding operations you perform at once but I think its a potential cause.

misty glade
#

snapshot comparison in editor wasn't insightful

echo coral
#

If the issue is heavy heap allocation before gc it will never happen on other platforms

misty glade
#

Lemme at least start with this - making some cached and presized lists and see if it still crashes in the same place

#

i'll report back in .. 15 minutes :p

echo coral
#

Its good practice anyway to make a list with a smart capacity. e.g.:

List<int> myList = new(10);
for(int i = 0; i < 10; i++)
{
  myList.Add(i);
}

we know we need space for 10 elements so we start at this size and avoid a wasteful list resize (where a new array is allocated and the contents is moved)

misty glade
#

yeah i'm combing through my hexpoint class and finding every new() and presizing to 20 - which is pretty much the upper bounds on a path in my game

#

but the pathfinding i'll probably use... 50

echo coral
#

The lovely ideal way would be you share 1 list over many executions like you can do with physics overlaps (the no alloc versions)

misty glade
#

yeah, agreed, although that would be a pretty big change (i'd have to change the api surface so the caller could cache a list)

#

but i can do that if this isn't helpful

echo coral
#

do what you said first so you dont go doing lots of work for no benefit ๐Ÿ˜†

misty glade
#
        public static int GetPathCost(this List<TerrainType> path) => path.Sum(x => x.GetMoveCost());

does this alloc?

thin mesa
#

an enumerator and delegate are allocated

misty glade
#
    public static class TerrainBehaviourExtension
    {
        public static int GetMoveCost(this TerrainType terrain)
        {
            return terrain switch
            {
                TerrainType.Normal => 1,
                TerrainType.Difficult => 2,
                TerrainType.Shrouded => 1,
                TerrainType.Impassable => TerrainBehaviour.Infinite,
                TerrainType.Hazardous => 1,
                TerrainType.NoLineOfSight => 1,
                _ => throw new NotImplementedException(),
            };
        }
    }

(that's the getmovecost method - just a lookup extension)

echo coral
#

Linq often can (but often has specific handling for lists)

misty glade
#

that might be a problem... I imagine that GetPathCost() is being called hundreds or thousands of times per frame in the pathfinding

#

since my nodes aren't all 1 "unit"

echo coral
#

id avoid all linq with this project ๐Ÿ˜†

misty glade
#

perhaps, but it's just so damn convenient

#

i suppose i can also optimize this since if ANY tile is impassable the entire path is infinite cost

echo coral
#

haha too bad for you, best to do it yourself with a for loop

misty glade
#
        /// <summary>
        /// Path cost for a list of terrain types.
        /// </summary>
        public static int GetPathCost(this List<TerrainType> path)
        {
            int cost = 0;
            int tileCost = 0;
            foreach (TerrainType t in path)
            {
                tileCost = t.GetMoveCost();
                if (tileCost == TerrainBehaviour.Infinite)
                {
                    return TerrainBehaviour.Infinite;
                }
                cost += tileCost;
            }
            return cost;
        }

foreach ok? or does that allocate an iterator that I don't need

#

like, i still need an iterator to get the length, don't i?

#
        public static int GetPathCost(this List<TerrainType> path)
        {
            int cost = 0;
            int tileCost = 0;
            int pathLength = path.Count;
            for (int i = 0; i < pathLength; i++)
            {
                tileCost = t.GetMoveCost();
                if (tileCost == TerrainBehaviour.Infinite)
                {
                    return TerrainBehaviour.Infinite;
                }
                cost += tileCost;
            }
            return cost;
        }

or is this meaningfully better

#

oops syntax error - path[i] instead of t but you know what i mean

echo coral
#

on new c# id trust foreach on a list wont use the enumerator ๐Ÿค”

misty glade
#

tbh i really don't know since this is run through mono/il2cpp anyway, right? like, internally it should end up as a normal for loop without all the c# bounds checking and stuff? or will that bound checking get embedded into the loop?

#

optimization is black magic ๐Ÿช„ ๐Ÿ’€

#

I'll use the second approach and pray.

echo coral
#

mono is old so even though its converted to cpp if the produced IL is shit then we get shit cpp

misty glade
#

OK added all the new presizing and am doing a production build.. will let you know in 15 min or so how it shakes out.. thanks for the eyeballs

#

i have this message in my console that I can't recall seeing before.. is this meaningful?

echo coral
#

well are you using native arrays?

misty glade
#

what do you mean.. like NativeArray? or int[] thing

#

I'm not using any of the former

echo coral
#

persistent ones need manual disposal.
yea NativeArray. int[] is managed

misty glade
#

i am doing some texture swapping in the app but I'm pretty sure I'm just doing managed arrays and assigning it to the .materials property... are there NativeArray uses there that I need to be aware of?

#

I'm definitely not using it in my code intentionally

#

oh, yeah, after looking at the API, I'm not using any of this

echo coral
#

perhaps do as is says and enable to get stack traces for them

misty glade
#

k well it'll have to wait until after this build.. shakes fist at dialog box

echo coral
misty glade
#

moving around old ones

echo coral
#

should be fine. Ill be off soon but as the others pointed out. You really want to get a memory capture of the webgl player which will require you to enable auto connect profiler.

misty glade
#

InvisibleMaterial and NormalMaterial and NormalGunMaterial are all linked in the inspector and static (not static but unchanging)

#

yeah I'll have to learn how to do that.. I wasn't aware it was possible

#

In any case, thanks for the help and leads

echo coral
#

Yea unity say webgl cannot accept incoming connections hence it needs auto connect enabled to work

misty glade
#

here's how i know I'm cooked - 6 purple links when i googled

regal lava
#

Could also be webGPU related since that's still not officially released

misty glade
#

this is a webgl build - although I'm tempted to try out that 6.1 thing.. they're different, right?

#

(webgl and webgpu)

regal lava
#

webgpu enabled most GPU supported stuff like instanced animating and other compute shader methods that unity uses

#

vfx graph too

#

I guess the animating stuff is already done in the shader, but I think compute shader operations are quicker or something?

#

that's one* of the features they were promoting with it lol

misty glade
#

OK... got a crash so @echo coral our solution wasn't successful [enough]. ๐Ÿ™‚

#

I'm gonna try the chrome memory profiler again and see if it goes bananas at the point where the allocs happen

regal lava
#

Ah, ok yeah. WebGL does gpu skinning in the shader, but WebGPU supports compute shader which actually is a quicker operation than doing it on a per vertex basis

misty glade
#

(fwiw I did have to reload/try to crash it 6 times, which is more than usual but still not acceptable)

echo coral
misty glade
#

crash is in the same place too so.. that's actually good news.. having a line of code that I can optimize is infinitely more useful than "the app crashes and I have no idea where"

#

these paths never get above 19 - and most of the time they're <5

regal lava
#

oh yeah that stuff is a pain in the butt to debug. Any time I get some browser errors I just throw my hands in the air and start disabling everything.

echo coral
#

Hmm then don't always make them be the max. If you can infer a good size each execution use that

misty glade
#

even in the pathfinding code - the units all have movement budgets of like... 3-4 so .. they don't go farther than that.. the only place they'll get above 19 is when the bad guys are trying to find the closest good guy to move towards

#

but 20 is fine.. 20 allocs should be nbd

echo coral
#

Hmm well have a think what else could be improved on, any new arrays or other objects

regal lava
#

Wasn't the last time texture related? Are you preloading all these assets at the start? May need to bundle them out and load only what's necessary

misty glade
#

This is the chrome alloc timeline but.. I don't know how to read it, and don't see anything obviously bad about it (numbers are in bytes, not megs)

#

There was some heavy texture use but ... there are a lot of textures in the game, so that seems expected

#

but the stack trace on the OOM failure is in the same spot so I'm .. really thinking there's a bug in the pathfinding code

#

but I just can't... figure out how to debug it because it works perfectly (and sane-ly) on my machine and in the memory profiler locally

#

the line that it crashes on is just a run of the mill Add() call - and there aren't even that many in a single frame (5? 10?)

echo coral
#

Could just be many many things building up and that's just what gets it each time.
You ideally need to get a mem snapshot of the webgl build

misty glade
#

yeah i'll dig into that thread and add the memory profile emscripten parameter.. and see if i can figure it out

echo coral
#

All heap allocations are there uncollected after all

misty glade
#

i mean honestly I might just need to rework the API of my hexpoint class to do 0 allocations and cache all that shit elsewhere

#

i'm just dreading that work though because .. obviously in a hex based game there's a lot of calls into path finding and hex distances!

#

In this stack trace - is there a way to get more granularity (ie, which line) the issue happened?

#

i'm pretty sure I have the right add() call narrowed down but i'm not 100% sure

echo coral
#

It may help but I could also be wrong and unity is able to do GC more frequently between managed code use. Hard to know but we do know it is going to be less frequent.

misty glade
#

OK. I added some more verbose add logging and tracked which frame the adds were happening, and it's definitely the source of the issue. ๐Ÿ˜ฆ

#

it's not out of control for a desktop build, but 1000 adds in a frame (even though the sizes of the lists are small, I think) is probably putting a lot of pressure on the heap

#

I'm gonna add some code to check capacity and count before every add and see how much my presizing helped.

fresh tangle
#

Ok guys, I got a really weird one for you. Are there any circumstances where calling RemoveAtSwapBack(int index) on a TransformAccessArray could freeze Unity? Not crash it, because of course it could, but hard freeze. Somehow, in some rare code path in my project, calling this function on index zero of a valid access array (with multiple elements in it) causes both the Unity Editor or the build to hard freeze

#

Attaching the debugger just says Unity is waiting for this line of code to finish executing: _ownerTransformAccess.RemoveAtSwapBack(index);

#

Im honestly stumped, as this is a core piece of our infrastructure that has been working fine for several years now.

fresh tangle
fresh tangle
#

100% this issue. Damn. That was a wild time

echo coral
mental hazel
#

Hello, I am trying to create a load/download level system. Let me explain. I want to have a scene with just a plane and then I would like to load a level that my friend created (for example) into my game. Creating a new door in the main scene with the plane that takes me to the new level. Similar to how creative works in fortnite? I am not so sure as I have not played it that much. But that is mainly the idea, be able to load different levels and create portals in the main scene to go those levels. I have no idea how to start with it and I would like to get some guidance, I do not want the main answer. Just some guidance. Thanks in advance! ๐Ÿ™‚

echo coral
tall ferry
mental hazel
#

In game mainly. Create a level creator/editor tool and then download it and send it to someone

tall ferry
#

It sounds like you're aware at least of what to do, are you stuck on a certain part?

mental hazel
#

Not really, I think I need a lot of work to do and investigate before saying if I really need more help. This should work for now. Thank you!

tall ferry
#

The code for saving a custom level should be pretty simple, I think most of the work here would be making the actual level editor in unity

#

UI and setting up whatever prefabs

mental hazel
#

Okay I will try to dig into level editors and probably a lot of questions will come up and might come back again haha. Appreciate the help! ๐Ÿ™‚

misty glade
# echo coral Hopefully by re using some lists or by making use of the unity native collection...

Still debugging this issue but I've found something interesting.. I added some logging to check if the list.capacity == list.count when trying to add items.. and check it out.. a bona fide bug!

So that's super encouraging because.. bugs I can fix.

Now the question is.. why can't I repro this in dev/editor builds? What could possibly be different between these environments?

The part of code in question is the backtracking path finding. Basically I stamp each hex with a "parent" from the origin (and increment the path cost) until I find the target - then I backtrack until I get to the origin. Why can't I get this to fail in dev?

            path = new(30);
            PathNode backtrackCurrent = _closed[to]; // Shouldn't fail.

            while (backtrackCurrent.Parent != None)
            {
                path.Add(backtrackCurrent.Location);
                backtrackCurrent = _closed[backtrackCurrent.Parent];
            }
#

for reference:

        private class PathNode : FastPriorityQueueNode
        {
            public HexPoint Parent;
            public float F;
            public int H;
            public int G;
            public HexPoint Location;
        }
#

Basically each node contains a parent and a location (and some A* details: F, G, and H)

#

And the first node is created with parent = none:

            PathNode node = new()
            {
                Parent = None,
                F = F,
                G = G,
                H = H,
                Location = from,
            };
            _open.Enqueue(node, F);
gray creek
#

How do I remove an entry from a StringTableCollection for every locale in script? In other words, how do I delete the entire row?

misty glade
#

Parameterless struct constructors aren't allowed (in the unity ecosystem), and property initializers also aren't allowed. I have a struct that might be (accidentally) created somewhere without initializing it properly.

How can I find it?

#

This is what I want. Am I gonna cause issues by changing the langversion to 10?

slate spoke
#

not sure how to set profile markers but running the deep profile, it seemed to get caught up on this function:

    public async UniTask<NativeArray<Vector3>> GetCoordinatesAsNativeArray(DataFrame df)
    {
        DateTime startTime = DateTime.Now;
        float frameBudget = 0.01f; // max amount of time to do work per frame

        Debug.Log("Converting coordinates from DataFrame into NativeArray");
        NativeArray<Vector3> array = new NativeArray<Vector3>((int)df.Rows.Count, Allocator.TempJob);
        // these index values are specific to the trctestimonies.parquet dataset
        // TODO: make these values less arbitrary somehow
        int xColumnIndex = 10;
        int zColumnIndex = 11;

        for (int i = 0; i < df.Rows.Count; i++)
        {
            // System.Convert.ToSingle firmly tells unity that this var is in fact a float so it doesn't panic
            float x = System.Convert.ToSingle(df[i, xColumnIndex]);
            float z = System.Convert.ToSingle(df[i, zColumnIndex]);
            // "0f" is a placeholder for the y axis coordinate, which is calculated later
            array[i] = new Vector3(x, 0f, z);

            TimeSpan timeElapsed = DateTime.Now - startTime;
            if (timeElapsed.TotalSeconds > frameBudget)
            {
                // reset the start time and wait a frame
                startTime = DateTime.Now;
                await UniTask.Yield();
            }
        }

        Debug.Log($"Returning NativeArray of XYZ coordinates (y is still 0)");
        return array;
    }```
lament salmon
slate spoke
#

Well, damn, that didn't seem to fix it

#

I guess I'll look out for similar things tho

lament salmon
#

What type does df[x,y] return?

slate spoke
#

object

#

I think it's arbitrary because the types between columns varies

lament salmon
#

What exactly happens in the indexer of df?

slate spoke
lament salmon
#

Is DataFrame your own class? You are using an indexer [,] with it so I suppose you have the indexer defined somewhere

#

I'm just suspecting that some boxing is happening there

slate spoke
#

Ah, no

#

the actual values in the dataframe are pulled directly from the .parquet file via parquet.net's ReadParquetAsDataFrameAsync() function

#

the actual values in that parquet file are predetermined

#

but all the file processing for that parquet file needs to happen at runtime, since it needs to eventually be able to work with other parquet files

misty glade
#

(I didn't read back all the way to the OP, sorry - was just glancing over that code)

slate spoke
misty glade
#

I was just curious so I chased it down through the reference source.. and ultimately it ends up here:

#

(with a few more steps to ensure that it's castable to IConvertible)

slate spoke
#

that's after rewriting that bit of code to C# array[i] = new Vector3((float)df[i, xColumnIndex], 0f, (float)df[i, zColumnIndex]);

stuck plinth
# misty glade

ToSingle has overloads if the type is statically known, that one takes int as the parameter not object

echo coral
misty glade
#

I've gone so deep... help me :p

#

There's some bug in my (?) code, but it only happens on production builds. I've .. gotten maybe closer to root cause but I'm still not there yet.

#

I just don't know why/what would be different about production builds versus local builds.. All my test cases I'm crafting just don't.. fail like I expect them to locally

#

like.. check this out, this doesn't make sense to me (sec)

echo coral
#

the fact this is all "managed" code makes it very weird because you usually only get this weirdness with native code and undefined behaviour

misty glade
#

this error ("ERR: 2") happens in an .. impossible way? lemme get the code, sec

sly grove
misty glade
echo coral
#

plz describe what the difference is specifically

misty glade
#

So.. no differences in execution order. No issues with framerate (the error happens all in one tick). There might be intricacies of platform, but I'm not quite sure what/how - something nondeterministic about float priority in my priorityqueue class, perhaps

#

So .. in the code I linked, there's some checks (ERR:1, ERR:2, ERR:3, ERR:4) that look for an invalid node being added to the backtrack list (where node.location == node.parent.location). This is happening on the origin (0,0) in cartesian coordinates.

I added this check to ALL cases where I Enqueue() ... but in the error message above, that is the FIRST instance of an invalid insert.. and it's getting an item from another queue!

echo coral
#

public static HexPoint None => new(-999999, -999999); ๐Ÿคจ

misty glade
#

In short, the code SHOULD fail when inserting into the other queue (but doesn't)

#

Basically, there's two queues - _open (locations that could be the path) and _closed (locations that have already been checked). Every location added to either of these queues has a parent (where the location came from - tracing back to the "from" location).

#

A node CANNOT be inserted into either of these queues with a location=parent.location.

echo coral
#

You aren't gaining anything by using out List<HexPoint> path but setting it to a new list in the function...

misty glade
#

And yet........ somehow it is

#

I know - I am tempted to change that but for now, that's not the issue.. There's some situation where the while loop at lines 456 is failing because somehow nodes are getting inserted into open or closed with location=parent.location... and I can't figure out how.

#

(But the error could be there!)

slate spoke
# slate spoke I think it's arbitrary because the types between columns varies

I'm attempting to fix my performance issues by replacing my DataFrame stuff with a class type IList, the documentation for parquet.net mentions being able to do parallelism but I assume their example code wouldn't work without converting it to use the Job system. How would this need to be changed, if I need to?

var reader = await reader.CreateAsync(path);
var count = reader.RowGroupCount;

await Parallel.ForAsync(0, count,
    async (i, cancellationToken) => {
        // create an instance of a row group reader for each group
        using (var gr = await ParquetReader.CreateAsync(path)) {
            using (var rgr = gr.OpenRowGroupReader(i)) {
              // process the row group ...
            }
        }
    }
);```
#

I'm not sure if it's possible to make an IJobParallelFor that lets you use a FileStream

#

to clarify, FileStream is relevant because that's one of the override inputs for CreateAsync

echo coral
slate spoke
#

which is necessary for android

misty glade
echo coral
#

aha now that makes more sense to me. So would this be created by somehow adding a neighbour PathNode but somehow its parent was set to itself?

misty glade
#

In short - the check on 377 is looking at the freshly dequeue()d item for badness.. But ALL the places I enqueue are doing the same check (and none are being hit)

#

Like, in other words - I'm never enqueuing bad data but somehow I'm dequeuing bad data

#

I thought that - and so double checked the origin math, thinking there was an error in GetAdjacentHexes() (line 530)

#

I just spit out the hexes adjacent to the origin in the editor and browser, and they're both working as expected

#

(left editor, right browser)

#

Another possible guess where there's a difference in platform is the code around line 76 - it's code that I only vaguely understand to convert X/Y to Q/R/S

#

but my tests on/around the origin seem fine for that

echo coral
#

The only thing that stands out is your use of AggressiveInlining. Perhaps on prod il2cpp this will actually inline the function call and perhaps there is a bug relating to the inline?
I dont think you are going to gain much from using it on GetAdjacentHexes()

misty glade
#

I don't think it does anything, actually

#

but I left it in there as a freeroll ("couldn't hurt")

echo coral
#

in managed world i have no idea if it has an effect (don't think it was confirmed that .net actually uses it) but in cpp it certainly does

misty glade
#

i'm gonna add some checks to Dequeue() since this libraries code seems weird to me

echo coral
#

I mentioned it as we know its not happening in dev builds

misty glade
#

yeah.. honestly I'm sure there's some low level bug here and I'm kinda at the end of my patience for this one

#

like the error i showed above is .. not possible

#

I'm not changing my nodes (once created), and I'm checking them for validity when enqueuing, and when dequeueing.. and somehow I put good nodes in, and bad nodes come out. ๐Ÿคทโ€โ™‚๏ธ

#

I was literally tempted to change struct to have a _isInitialized bool and add a check in the x and y property getters against the flag

#

but that woulda definitely been some major overhead

#

(and probably not tell me much anyway)

echo coral
#

is there a page for HPPriorityQueue ?

misty glade
#

HPPriorityQueue just inherits from this queue lib

#

sorry that's wrong - HPPriorityQueue is a FastPriorityQueue<PathNode> and PathNode inherits from FastPriorityQueueNode

#
        private class PathNode : FastPriorityQueueNode
        {
            public HexPoint Parent;
            public float F;
            public int H;
            public int G;
            public HexPoint Location;
            public override string ToString()
            {
                return $"{Location}, FGH:({F},{G},{H}), Parent:{Parent}";
            }
        }

Nothing fancy here though

#

(perhaps aside from no constructor - so the Parent and Location are uninitalized/undefined if pathnode new() doesn't define them.. but I am everywhere in my code, and I am not gonna comb through the authors code in his library)

echo coral
#

well remember you are using -999 or whatever as your "none" state vs ofc the default is 0,0 for your positions

misty glade
#

yeah, but that's fine - ideally I'd like to even have x and y initialize to -999999 so I could see if they were being .. uninitialized .. but that's not allowed in clang 9

#

(ie - parameterless struct constructor and/or property initializer)

echo coral
#

why arent you using the int min but loads of 9's

misty glade
#

because if I have a bug and accidentally try to check adjacent hexes of HexPoint.None I won't get int underflow

echo coral
#

you mean c# 9 not clang ๐Ÿ˜†

misty glade
#

cslang9 ๐Ÿ˜› whatever you know what I mean ๐Ÿ™‚

echo coral
#

clang is a cpp compiler so i got very confused

#

perhaps your none state should only be if x or y is less than 0

#

but well not the main issue here i guess

misty glade
#

no, cuz those are valid locations in my map

#

0,0 is a valid location too, which is why I don't use that as "none" or "invalid"

#

(in retrospect we coulda just moved our hex to origin = 100,100 or something but .. that ship has sailed)

echo coral
#

aha i see. im kinda out of ideas atm but if you can inspect more if that queue does anything funky that may help

#

Perhaps also make sure any PathNode made is given a default value matching your none state as on 362 for example it isnt

misty glade
#

Yeah, could do that too. I'm more or less giving up because I've spent maybe ~20 hours on this single stupid issue and .. I can just deploy a dev build and it works fine.

#

I'm maybe going to make a minimal reproducible project and see if I can isolate exactly what is going on. I just keep coming back to "it's so damn confusing that it only happens in production builds".

echo coral
misty glade
#

I've found the error, actually ( ๐ŸŽ‰ ).. It is my code but it's also the author of the library not throwing an exception like I thought it would when trying to dequeue an empty queue

#

but weirdly, it only throws locally - not on production builds.. so i'm exploring that

misty glade
#

go figure

#

Don't think I have the energy to step through his code.. but his .count property works so .. I can just check if that == 0 instead of just trying to dequeue and catching the exception.. and ... hooray, I have my life back.

echo coral
#

Yay success

misty glade
#

This setting for exceptions - I still should be seeing/getting exceptions in my builds, right? Like - my code looks like it should still see exceptions?

The code for dequeue looks like this:

#

Like - that should still throw an exception to my code, even with Explicitly Thrown Exceptions Only, right?

fresh salmon
#

If built without the DEBUG symbol (which should be the case on standalone releases), code between lines 352-363 will not be compiled ie. it won't exist at all, so the exception won't be thrown

echo coral
#

DEBUG covers dev builds and editor

echo coral
misty glade
#

the DEBUG symbol is defined for my production builds (not sure how or where, but it is - this code appears to run)

#

yeah, verified - stepping through the code hits these lines (in the production build settings)

slate spoke
#

out of curiosity, do y'all think using DataFrame or SQL would be better suited for large dataset stuff in Unity?

echo coral
#

Sqlite is a popular choice

compact ingot
#

generally SQL and data frame supporting databases are not fast

slate spoke
compact ingot
#

what operations do you want to perform?

#

is it just one table?

#

any processing without the overhead of a database is likely faster

slate spoke
#

Initially, yes. Basically, each row has a set of coordinates that's being used to place an object in a massive procedurally generated environment, each of those objects will be sorted by the terrain chunk those coordinates would fall within and then rendered via compute shader

compact ingot
#

or, so zero benefit from having it in a database, also 75MB is not a lot

slate spoke
#

but, each of those objects also need to be selectable so you can view the rest of the data associated with it

slate spoke
#

I hate it

#

viscerally lmao

#

the only useful output you can get out of it is DataFrame

#

and I think that's one of the biggest hurdles with my performance issues

#

also documentation leaves a lot to be desired

#

not to mention the hurdles to jump through to get it working on android properly

compact ingot
#

well, if thats not your cup of tea, then maybe you just have to make a detour through a RDBMS

#

those aren't exactly easy to get to work properly either

slate spoke
#

fair, but I assume also infinitely more well documented

compact ingot
#

you'll have to find out if that kind of documentation is actually helpful to your problem

slate spoke
compact ingot
slate spoke
#

lol

compact ingot
#

i would think its not supposed to be a reader for a parquet file though, maybe there is an import option... i wouldn't know

slate spoke
#

true but the parquet file could be converted to SQL before runtime

compact ingot
#

kinda defeats the point, but sure.

slate spoke
#

The input database type just needs to be a standard unprocessed file of some kind

#

that way it's easily adaptable to other similar datasets

north dawn
#

How do I dynamically control the height of a small part of terrain and flatten it from code/logic?
Example: Wherever any item is placed on a terrain, that item's space required portion of terrain gets automatically flat

hearty shoal
#

Does anyone know if there's a way to hide the track binding on a custom marker track (in timeline). It seems to default to a gameobject. If I inherit from just TrackAsset, it doesnt give me the option to add my custom marker

misty pier
#

I have issues in my game where my main event bus isn't initialised when other scripts want to access it - what is the best/ safest way that proper game devs make sure the correct order of things being initialised?

Should I set just the eventbus in the Project Settings > Script Execution Order - or is that v bad to do?

Is it better to set a yield return null check for all other systems that rely on the eventbus being initialised? that also feels suboptimal and not scalable

Thanks in advance for any help

jolly token
misty pier
#

Ah ok interesting, I'll check out that attribute thanks

sly grove
misty pier
#

Ok thanks - where does 'OnEnable' fit into that priority list?

sly grove
#

OnEnable runs right after Awake when first starting up, so it's similar to Awake

glad cypress
#

im so angry rn. My only code for loading audio files durring runtime has turned out to now be able to read most WAV files and is useless. And any other solution is just not working. So how do i load an audio file as an AudioClip durring runtime?

glad cypress
#

oh ok so the only way to do it is the dumbest, most annoying and hardest oneยจto work with. Yeah, great. I wanna break something.

midnight violet
loud flame
#

Hey there, I've been pulling my hair trying to make an FPS controller for my game with ECS. But I cannot find any resource online to provides a strong start. Even the official Unity Character Controller is literally broken and doesn't work at all...

Do you guys know any sort of resources I could use? I need to also support physics (which is the main issue really)

smoky kite
#

Hi everyone,

Is anyone else experiencing significant issues with the new UVCS? Iโ€™m struggling to understand how they calculate limits, and the lack of clarity is frustrating. Recently, UVCS notified us that weโ€™ve hit our total limit, even on a day when we didnโ€™t upload anything. After opening a ticket, they couldnโ€™t provide a clear explanation and are now pushing us to upgrade.

Hereโ€™s our situation:

  • Our game project is around 12 GB in size.
  • Weโ€™re a team of two developers.
  • Daily data flow is less than 100 MB.

Iโ€™m wondering if thereโ€™s a better way to work with UVCS or if we should consider switching to another source control system. A few specific questions:

  1. Does the UVCS client update the repository automatically?
  2. Could it be counting files in the library folder toward the limit?
  3. Are there any recommended alternatives for a project of our size and scale?

Any insights, tips, or recommendations would be greatly appreciated!

Thanks in advance.

compact ingot
torn basalt
#

Hey, is it possible to export a ui toolkit hierarchy (children of an particular VisualElement) to single image? Working on an image compositor and I am having trouble with finding a way to combine all the layers and export them. USing a camera and taking a screenshot doesn't retain the aspect ratio of the page and the resoliution is a bit low. The resulting image will be printed.

smoky kite
#

got it

paper grotto
#

Is it possible to pre-load a scene, then open it later? I'm aware of AsyncOperation.allowSceneActivation, but since it blocks the loading of other scenes it isn't a good option. Setting the root GameObjects of the scene to inactive as soon as LoadSceneAsync finishes also doesn't work because this invokes Awake, OnEnable, and OnDisable on each component. Is there a workaround to this or am I out of luck?

untold moth
paper grotto
#

That might work, but it's not very intuitive. It also creates a lot of edge cases.

regal olive
exotic trout
#

Might be worth considering having your own comparable awake and start messages that whatever manager your using calls after the scene is ready rather than using the build in awake and start

livid kraken
#

Also root objects in the additive scenes are inactive by default and we enable them in batches on scene activation

glad cypress
#

to me its not simple at all, i never understood and will never understand async propably.

#

I was trying to use this, but even tho the build does recognise NAudio namespace, it does not recognise the Mp3FileReader, WaveFormatConversionStream and WaveStream classes
https://www.youtube.com/watch?v=fIW-_zxaCPM

Twitter: https://twitter.com/_acetix
Here is a simple tutorial of how you can load any music files into your project.

-------------- Downloads --------------

NAudio.dll: https://www.dllme.com/dll/files/naudio_dll.html
NaudioPlayer script: https://www.dropbox.com/s/wks0ujanr0pm6nj/NAudioPlayer.cs?dl=0
The Filebrowser I used to get my path: ht...

โ–ถ Play video
glad cypress
#

Btw, yes, i really want it synchronous. The request is part of a loading sequence, that shouldn't finnish until all data is loaded. Async is useless in that moment

#

This is the script i have now. So far i tested it once and it caused a Unity crash.

public class WavLoader : MonoBehaviour
{
    public static AudioClip LoadWav(string filePath)
    {
        GameObject loaderObject = new GameObject("WavLoader");
        WavLoader loader = loaderObject.AddComponent<WavLoader>();

        AudioClip clip = null;
        bool finished = false;

        Coroutine corutine = loader.StartCoroutine(loader.LoadMp3(filePath, (a) =>
        {
            clip = a;
            finished = true;
        }));

        while (!finished)
        {
            loaderObject.GetComponent<MonoBehaviour>().StartCoroutine(WaitForOneFrame());
        }

        Destroy(loaderObject);

        return clip;
    }

    private IEnumerator LoadMp3(string filePath, System.Action<AudioClip> onLoaded)
    {
        if (!File.Exists(filePath))
        {
            Debug.LogError($"MP3 file not found: {filePath}");
            onLoaded?.Invoke(null);
            yield break;
        }

        string url = "file:///" + filePath;
        using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG))
        {
            yield return www.SendWebRequest();

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"Error loading audio: {www.error}");
                onLoaded?.Invoke(null);
            }
            else
            {
                AudioClip clip = DownloadHandlerAudioClip.GetContent(www);
                clip.name = Path.GetFileNameWithoutExtension(filePath);
                onLoaded?.Invoke(clip);
            }
        }
    }

    private static IEnumerator WaitForOneFrame()
    {
        yield return null;
    }
}
long ivy
#

that's because you create an infinite loop that does nothing but start pointless coroutines over and over

exotic trout
midnight violet
# glad cypress Btw, yes, i really want it synchronous. The request is part of a loading sequenc...

You might just need to look into tutorials or unity learn stuff about async. Your problem is, that you only know a loading process based on blocking the mainthread here, which you cant wrap your head around the async webrequest. But in the end, you can either make your whole loading async and await all async loads or you just block your mainthread with a list that you are waiting for to empty. When loading the files, add them to a list and wait remove themselves when done, check for your lists count == 0 and continue. Just because you cant adapt to the correct situation does not mean, you have to force the wrong one. Dig into async code, learn what it is doing and how you can collect information from it while loading and use that to utilize in your loading progress system.

#

In that way you also would learn the correct way of loading things async, because blocking the mainthread means blocking your game. Imagine you want to load while have an animation running, even that could be blocked if its run by code. Or imagine you want your user to check a list of things and lazyload. You would kill the experience when loading new stuff in while its doing so.

echo coral
#

You are doing something very weird in that loop too you must be confused how coroutines work...

regal olive
#

hi, i learned one of pitfalls of using c# is Decompilation, i am making a multiplayer game so security is paramount. I looked into using c# native to compile my project to x86 directly. is there any other tools or compilers or coding practices I can use to minimize the security risks. I know about the whole don't trust the client one the server approach, but I still want basic code obfuscation. I thought about also writing large sections of my code in c/ cpp and use a c# wrapper

untold moth
echo coral
#

As long as you dont do what gta online does and trust whatever the client says then you will be good

regal olive
#

well you can ditch the cpp symbols and break it down just to just memory but from what ive seen c# keeps almost the exact same script

echo coral
#

c# retains type naming and lots of information about the type structure for reflection (and due to its managed nature) so its just how it is

novel wing
#

you don't do network security by obscurity

echo coral
#

even if you use il2cpp there are tools specifically made to decomp il2cpp cpp to semi readable code

untold moth
#

If it's a mono backend, then it's compiled to an intermediate language, which is more readable than assembly and easier to restore "original" code from. I think if you build Il2cpp it should be as as safe as a C++ game.

regal olive
#

i know that, however i also dont want people just copying my scripts

novel wing
#

if they want to they will, you can't stop it

stuck plinth
#

ultimately you have to give the user your code for them to run it haha

untold moth
tall ferry
untold moth
#

Build an il2cpp build and the decompiled code would mostly be useless to anyone but assembly experts. And even then it would take them several months to years to do anything useful with it.

tall ferry
#

the only case where you'd actually be able to hide code is if you have some client server architecture. like online games where the client isnt the one who needs to run logic

#

and even that case is very rarely ever needed

regal olive
#

thats what im doing, im compiling the project into a linux headless server and then i have the gui client

crisp temple
regal olive
#

it will be harder to fix later then now

#

if i have to rewrite entire systems

tall ferry
crisp temple
#

Trust me, if you have the problem that so many people are playing your game that there's more cheaters than you can manually ban, you have probably the best problem any multiplayer dev faces

#

I released a MP-only game that topped Steam New Releases/had 90k owners + had prized tournaments. 90% was client side. Had 2 cheaters the whole life cycle of the game, both of whom were banned fast.

tall ferry
#

Maybe only 2 that you've caught. It's not bad to just start off by implementing a better approach, especially if it doesn't take much longer to do.

#

Which is why im specifically trying to see what part they're trying to hide, so we can see if its worthy of even dealing with rather than repeating the same statement 50x

echo coral
#

If your multiplayer game has client authority then you are cooked

crisp temple
regal olive
tall ferry
#

not sure where you got the idea that they stated it was perfect. in the same message you're replying to, they specifically say "harder to read" AND "never fully mitigate"

regal olive
#

well new question, i currently have one unity project for the cilent and server, is there any macros build into unity to tell it to only include specific code is server builds?

echo coral
crisp temple
regal olive
regal olive
regal olive
#

linux server, linux and windows client

#

Just native compile a library and libraryimport it and use it with interop. Boom, a native library used in your code.

regal olive
regal olive
#

Yeah just make a classlib and native compile it and then use it in your unity code.

echo coral
#

Then hate yourself for how difficult it will be to integrate

regal olive
regal olive
echo coral
#

You still need to then use managed code with unity APIs so I doubt it will be very impactful

scenic forge
#

That only works to "protect" the class library code though, not the code in Unity project. Unless you write your entire project in those class libraries.

echo coral
#

Hahaha this convo

regal olive
regal olive
crisp temple
crisp temple
scenic forge
regal olive
scenic forge
#

Personally I consider going down this path as just a futile attempt at fake security. It weeds out the bottom barrels, all it takes is one person who cares about your game enough to cheat and it's back to square zero again.

echo coral
#

So in conclusion.. No. client side obscurity doesn't work thanks for coming to my ted talk

regal olive
#

also another thing, if im running multiple instances of the server is there anyway to used shard memory server side as a optimization, i know how to do it in cpp but idk how it would work in a unity project if at all

regal olive
#

I just don't want to load the map 50x in mem

#

Here's the thing. If the bytes of a program are on your file system, they're fair game to play with.

#

True, but if you mess with blocks of mem durring exec then that's iffy

untold moth
regal olive
#

So having other parts have checks and balances, hashes, checksums, etc. can help

regal olive
echo coral
#

You could have shared asset bundles for assets but in memory sharing won't happen

regal olive
#

You can even have code in those assets I believe. ScriptableObjects in asset bundles and addressables (I think, I may be wrong)

scenic forge
#

SOs aren't code.

regal olive
#

yeah just trying to free up some mem by not loading the same models over and over again

echo coral
#

all that will be handled by unity in native code so you would have to modify the engine so you would need engine source (i presume)

regal olive
regal olive
#

i know its a bad way of doing it, but i have the unity game project that im compiling for the client and the server the server is headless and just handles connections and physics using unity, idk how i would use my own solution without making my own networking solution and making a physics engine that would match client side physics predictions

regal olive
#

i thought this method would be best to keep coherency between the client and server

#

im just using fishnet then compiling the unity project to the linux server build

#

then i can run the unity server headless from terminal

crisp temple
#

Tbh this is another super premature concern. You may get to your final game, and find out that memory isn't the bottleneck for instances-per-server at all, and it's CPU limited.

regal olive
#

Having the backend code within the Unity code base is definitely not something I'd recommend, unless the code is strictly networking code for multi-player, in which case Mirror has a good implementation of such an architecture.

regal olive
#

well idk how else i would write the backend, but i can alsway handle large portions of the logic with a dll or only compile the logic to the server target only. eventually the client will just send input to the server and ill handle everything server side, and ofc the animations and stuff will still be in the client just not sent to the server

#

What protocol are you using to communicate with the backend?

#

i belive fishnet uses netcode

#

If you're just managing state I don't see why you need netcode. You could make your own HTTP backend and have a RESTful implementation of state.

#

true

echo coral
#

http is not well suited for "near realtime" games

regal olive
#

well most games use utp

echo coral
#

udp

regal olive
#

and you do logic to handle missed packets

#

yeah that

#

typo

echo coral
#

Id try to research what other large multiplayer games made with unity do (e.g. rust, among us)

regal olive
#

yeah, funny enough one of the among us devs responded to that question on r/gamedev

regal olive
#

Again, depends on what state we're talking about managing.

misty glade
#

Has anyone used a standalone structured logging service to the cloud from a client? I'm thinking of adding Seq to a project, but I'd like the logs to flow up to a common logging instance and not quite sure what pitfalls might await me

#

Obviously the implementation here is gonna need to have as minimal logging as possible so the logging isn't putting a lot of demands on the client (and server, but that's easier to deal with)

echo coral
# misty glade Has anyone used a standalone structured logging service to the cloud from a clie...

Do you have different goals for dev and prod? Usually for prod you only care about error logging and hopefully its infrequent enough to not be such an issue.
For games I work on we mostly use firebase crashlytics for error reporting. I've also used loggly and sentry in the past. Sentry was my favourite as it has many supported clients (inc unity) and you can self host the server side too.

#

hell i even wrote something to log tf2 sourcemod errors to a sentry instance!

misty glade
#

Goal for this project is 90% user behaviour/analytics and 10% crashes/ANRs (the client hasn't told me that crashes are an issue)

#

They have pretty low retention/monetization and are bringing on a new product manager

echo coral
#

well you should care about errors and/or crashes

misty glade
#

but when I looked at the app there's like... a lot of hand waving and guessing for why.. so I think that a good goal would be realtime logging of user interaction

#

they're already using firebase crashlytics but there aren't much in there

#

frankly the userbase is kinda too small to make any good guesses as to the lack of monetization/retention/engagement

echo coral
#

perhaps then you should be using firebase analytics too

misty glade
#

they are

#

analytics, crashlytics (and a buncha other firebase and GCP stuff)

echo coral
#

then that should already cover your needs?

misty glade
#

I just don't know that analytics is easy to ... explore use in an ad hoc way

#

it might - to be fair they're using FA in a very light way.. like maybe sending 10 different types of messages total. I was thinking structured logging would give a lot better insight into user flow

#

maybe FA can do that just fine too - provided we go and add a zillion FA logging calls in the client

echo coral
#

From my experience you log major parts of the game in a way that lets you track user progress.
e.g. levelStart (with level related params), levelSuccess, levelFail. This usually also includes monetisation related events too to track revenue.

misty glade
#

sentry doesn't work with c#..?

echo coral
#

sentry has a unity plugin

misty glade
#

gotcha, found it.. googling up

#

this looks nice too

echo coral
#

This is kinda getting of topic anyway but if you already have an analytics service you should use that to log your main game events. Ideally you query the events in a db later to get a wider picture of how the game is being played.

misty glade
#

No, definitely not OT - I'm gonna be the one implementing whatever the solution is so .. exploring other options (including just using what they've already implemented) is totally relevant

#

Sentry looks nice

#

I might just honestly need to get better versed in FA and see if we can improve the event flow to that and get better insight

echo coral
#

OT?

#

FA?

misty glade
#

off topic

#

firebase analytics

echo coral
#

aha right. firebase analytics has an 500 custom event limit and also limits how many parameters you can send max on an event.
So its usually better to send events like "gameMove" with params to give detail vs "gameMove_0_foobar"

#

guess the service you pick is up to you/cost

misty glade
#

yeah, that's probably fine.. I was thinking of defining some sort of dictionary of structured logging "types" since Seq does the same sort of thing - collapses the stringy bulk of a message into a small primitive for network transport so it's not spammy.. although it doesn't have a event limit

#

mostly I'm hoping that whatever reporting/analytics on the back end is... useful for the product manager who might not be familiar with the product

echo coral
#

seq doesnt look like the correct solution then. actual analytic tools usually have nice UI to quickly parse useful data (e.g. current active users, countries, common events ect...)

misty glade
#

What I liked about seq is if you logged something like

_logger.Info("{Player} started task {Task}", myPlayer, myTask);

You'd see this stream of events in the dashboard, and you could just click on {Player} (which would render however you want .. like, maybe the player name with a guid:)

Sharping#1234-abcd started task NewbieTask0001

If you clicked on the player - you could just filter on that player and so you'd see the event flow of everything that player was doing (or did).. in realtime

#

I think they need less of that high level stuff and more granular tracking - like "what is the user journey before they churned out" versus "what percentage of users churned out after d3"

#

they have the latter - and it's grim ๐Ÿ’€

#

But I don't think they have the answer to "what's the last or most annoying/confusing/hard thing a user did before never coming back"

#

seq has dashboards too but it's not their strength imho

echo coral
#

For a game with "levels" we can usually identify this stuff by seeing how many people start/finished levels and ofc as we go up the levels we see a drop off.
So if you can track some common game events in an easily order-able way they should be able to do the same.

misty glade
#

yeah this game's a little more "open world" (not really, but more like.. lots of small things they can do) but.. there's still probably a lot of value in tracking the engagement more finely - like "started merge board" "closed merge board" "completed task" "collected resources from world map" etc

echo coral
#

well you can log whatever you want i guess but think about what major things need to be there. regardless of platform you use its important.
logging random strings doesnt cut it.

misty glade
#

I think basically what I'm looking to provide is "here's a readable script of what a given user did" in a session.. FA might be that, but I don't think I've really used it that way in the past.. FA seems better for aggregate queries

#

yeah, definitely

echo coral
#

have a think then what major information can be used to know the "players progress" (e.g. level, play time, resource count, xp...) but hopefully this has helped you a bit. You can always have some generic "board_event" with some params and other events like "levelUp" or "resourceCollect".

glad cypress
# glad cypress This is the script i have now. So far i tested it once and it caused a Unity cra...

k one crashout and a fieldtrip later:

public class WavLoader
{
    public static AudioClip LoadWav(string filePath)
    {
        if (!File.Exists(filePath))
        {
            Debug.LogError($"MP3 file not found: {filePath}");
            return null;
        }

        string url = "file://" + filePath;
        using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(url, AudioType.MPEG))
        {
            DownloadHandlerAudioClip handler = new DownloadHandlerAudioClip(url, AudioType.MPEG);
            handler.streamAudio = false; // Ensure full loading instead of streaming
            www.downloadHandler = handler;

            www.SendWebRequest();

            while (!www.isDone) { }

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"Error loading audio: {www.error}");
                return null;
            }

            AudioClip clip = DownloadHandlerAudioClip.GetContent(www);
            clip.name = Path.GetFileNameWithoutExtension(filePath);

            // Ensure the audio data is fully loaded
            if (!clip.LoadAudioData())
            {
                Debug.LogError("Failed to load audio data!");
                return null;
            }

            return clip;
        }
    }
}

i got the solution.

#

now i just have to rename the functions and make it support multiple files

thin mesa
#

while (!www.isDone) { }
this is going to cause the entire game and editor to freeze. this should be a coroutine

glad cypress
#

Yeah, it will freeze up until the request is finnished. When im loading the audio file, it's always in moments like loading an entire level, so the app is expected to freeze up.

thin mesa
#

that would be a complete freeze though, wouldn't it make more sense to do that over several frames so you aren't completely freezing and can instead show a load/progress bar or whatever?

echo coral
#

Yea don't do this...

glad cypress
#

oh, i just realised what im expected to do

#

The Start() is part of some while that Unity initiates, but no Start is async, they go one by one, so putting this in a Start freezes up the app... and the whole content of Start is supposted to go to a Coroutine that Start starts, right?

echo coral
#

If you don't want to use coroutines use async instead via Awaitable or unitask

#

Doing a while forever will always block a thread BUT if we await or yield within it we break execution till some point later (which then means we don't block the thread for ever)

echo coral
#

I use async with UniTask a lot

glad cypress
#

oh yeah Async is MUCH better.

echo coral
#

Has some extra things you need to handle in unity specifically but do change what you are doing now

misty glade
#

you can just define start as a coroutine

#
private IEnumerator Start()
{
 // magic!
}
#

@glad cypress

glad cypress
#

oh cool

echo coral
#

you can also have a coroutine function anywhere and start it with any mono (but it them depends on that mono to be executed)

#

async does not have this limitation but you need to make it stop when playmode ends (unitys Awaitable probably does this better)

glad cypress
# echo coral you can also have a coroutine function anywhere and start it with any mono (but ...

ok cool but why do all the tasks get stuck on the Load___ functions???

protected async Task FileLoadCoroutine()
{
    var iconTask = Task.Run(() => 
    {
        Debug.Log($"Level: {Name} icon start");
        var icon = LoadIcon(); 
        _icon = Sprite.Create(icon, new Rect(0, 0, icon.width, icon.height), new Vector2(0.5f, 0.5f));
        Debug.Log($"Level: {Name} icon finnish");
    });

    var backgroundTask = Task.Run(() =>
    {
        Debug.Log($"Level: {Name} bg start");
        var background = LoadBackground();
        _background = Sprite.Create(background, new Rect(0, 0, background.width, background.height), new Vector2(0.5f, 0.5f));
        Debug.Log($"Level: {Name} bg finnish");
    });
    var musicTask = Task.Run(() =>
    {
        Debug.Log($"Level: {Name} music start");
        var music = LoadSong();
        _music = music;
        Debug.Log($"Level: {Name} music finnish");
    });

    await Task.WhenAll(iconTask, backgroundTask, musicTask);

    filesLoaded = true;
    Debug.Log($"Level: {Name} - ic:{Icon != null}, bg:{Background != null}, au:{Music != null}");
    fileLoadFinnished?.Invoke();
}
#

It just logs the start of all the functions but not than none continue.

echo coral
#

async is not just for "doing work on other thread"

#
public async UniTask DoThingAsync()
{
  Debug.Log("Hello");
  await UniTask.Yield();
  Debug.Log("Hello next frame");
}
#

ive said this on this server soo many times I really cba

glad cypress
#

than i do not know how to fix my issue. Elaborate.

#

all youve told me so far is that im doing something wrong.

glad cypress
echo coral
echo coral
# glad cypress this does not help.

my example shows via unitask that we can "await the next frame" and because its still on the main thread, we can use the unity api safely still.
Just like a coroutine!

#

@glad cypress ^ some reading for you above

glad cypress
#

oh yes i do love me some reading my project is due in a week it's 23:33 guess im not graduating, F me.

echo coral
#

stick to coroutines if you understand them

#

or if you really want you can do

while(!done)
{
  yield return null; //WAIT FOR NEXT FRAME BEFORE CHECKING WHILE CONDITION
}```
glad cypress
echo coral
glad cypress
#

what am i supposted to do than???

tall ferry
#

Though it's really not suited for the advanced channel imo

south ibex
#

Working on grass painting for my cvustom terrain system. The grass is instanced geometry drawn via DrawMeshInstancedIndirect. Whenever the user paints, I erase/dispose the current computebuffer and then recreates it with the list that contains the newly painted details. This causes a very noticable and distracting flickering.

I'm not entirely sure how to fix this. A quick google search on how to update computebuffers properly, I see stuff like "SubUpdate" buffers, with very little further explanation. Can anyone help explain how I can properly update a computebuffer to account for new data without erasing it and rebuilding it?

#
public void UpdateDetailBuffer()
{
    if (mpb == null)
        mpb = new MaterialPropertyBlock();
    if (allDetail.Count == 0)
        return;


    //Release current buffer
    detailBuffer?.Release();

    //Recreate buffer
    detailBuffer = new ComputeBuffer(allDetail.Count, Marshal.SizeOf<DetailObject>());

    //Set new data
    detailBuffer.SetData(allDetail.ToArray());
    mpb?.SetBuffer("_TerrainDetail", detailBuffer);
}

This is my current code for updating the buffers

livid kraken
#

SetData has an overload that allows you to write from a specific index onwards. You create a big enough buffer initially and keep track of the last index written to. Resize like this only if you need to.

south ibex
#

I've tried that, but I don't really understand how to use it. Documentation didn't really help and I can't find any examples of it's usage

glad cypress
#

K, redid all my code with coroutines - looks like it works. Shaders are making problems now tho...

compact vault
scenic fjord
#

I don't know where exacutly to put it but anyway guys is it possible to make binary patch by using package bsdiff and apply it for files like .resS .assets because for know i faced alot of toruble trying to do it i am working on patch system for unity game my q is should i get try using assets bundel instead of patching using binary diff for .assets and .resS or what

echo coral
scenic fjord
#

so me trying to patch ,assets file and .resS was pointless right

echo coral
scenic fjord
echo coral
#

(normally local addressable groups are embedded in the game but you can make the output/read path be whatever you want basically)

kind flare
#

I'm getting terrain height differences between the terrain chunks showing gaps between them

safe elbow
#

Ive optimized the bottom section of code into the top section of code yet its now slower.
At a glance does anything indicate why the top section would be slower than the bottom?
https://pastebin.com/THxYFd4D

safe elbow
#

good call, kind of forgot i can use that

#

ill give it a go, thanks

#

Unity wont let me run the visual studio profiler with this project

#

i can just profile this outside of unity i suppose

untold moth
safe elbow
#

Can the unity profiler profile specific functions?
I tried it and dont think it produces much detail unless im missing something

#

ill look into it more if it can

untold moth
safe elbow
#

okay ๐Ÿ‘

safe elbow
#

yeah im working on it now

#

This profiler is so unuseable

#

Okay so ive got multiple performance markers that run, and they show up under performance markers but when profiling those markers do not show up in the call stack under any frame whatsoever

#

I think i need to scroll back the profiler preview but there seems to be no way to?

untold moth
safe elbow
untold moth
untold moth
safe elbow
#

yeah alright.
What does self ms vs time ms mean in the categories?
Why doesnt each element in a dropdown's total MS add up to the parent MS?

#

if OldGenerateVertList takes .37ms shouldnt its children fucntionality take 37ms total aswell?

untold moth
safe elbow
#

yeah okay t

#

thanks @untold moth

#

thought there would be the thank bot lol

#

It seems if statements are faster than accessing a small list to deprecate those if statements in favor of a mapping?

untold moth
#

Mapping would usually be faster. If it's using hashes.
I'm not entirely sure you're comparing now and what info your conclusions are based off.

untold moth
safe elbow
#

yeah i noticed the difference that made when profiling, but now their both accessing the same amount of times

#

one just uses if statements

#

and one iterates and uses a list instead of an if statement

#

is there a way these if statements are just completely optimized out

safe elbow
#

yes

untold moth
#

if only one can be valid at any given time, then if - else if

safe elbow
#

not the case here

#

Im not trying to optimize the if statements though, im trying to find out why their faster

untold moth
#

Share the new profiler info where the number of list access is the same in both cases.

#

Also share the actual code including the method signatures

safe elbow
#

you mean definitions?

#

which method signature

untold moth
#

The definitions yes, the ones that you shared code from

#

The one's that you are profiling

safe elbow
#

This is nitpicking as these functions dont seem to be very impactful even in extreme circumstances so for now its just my curiousity

untold moth
#

What's m_NewGenerateVertList? Can you share the whole script please? or at least the methods this code is in?

safe elbow
#

m_NewGenerateVertList is the using statement in the code sample. Its the performance marker

#

same with m_OldGenerateVertList

#

both of these code sections are running one after another for profiling purposes

#

But ive also found using stopwatch the top section to be slower so theres no issues with running these concurrently in terms of benchmarking

untold moth
safe elbow
#

Yes

untold moth
#

Ok, so there are already more list access in the top method

safe elbow
#

Is there not the same amount?

#

ah, i was just looking at your code sample your rigth

untold moth
safe elbow
#

Even so, edgeIndexTable is static+readonly so it should just be fully compiled

untold moth
#

The difference mainly comes from you calculating indices(with bit shifting) dynamically, while in the bottom solution they are hardcoded.

untold moth
#

If you want to reduce list overhead, use arrays

#

Though, in a prod build there's probably not gonna be too much of a difference if at all

safe elbow
#

Im not sure if its different because C# is jit compiled but as far as im aware at compilation that static readonly list doesnt exist anymore nor the bitshifting operations; just the values of the list put in place of where their used

untold moth
#

And the bit shifting is most definitely not gonna be inlined or turned into constants.

safe elbow
#

So if static readonly values arent compiled then why are if statements?

tall ferry
#

which part of the bitshifting do u expect to be turned into a constant?

safe elbow
#

all of it

untold moth
safe elbow
#

edgeIndexTable[i] will always return the same value given the same i and henceforth that value bitshifted the same way will always be the same

untold moth
safe elbow
#

Yeah im thinking of switching some of my lists to arrays because they are completely constant, although some google searches had people saying theres almost no reason to use arrays over lists but i doubt that

untold moth
#

Anyways, that's soo many "ifs" that you shouldn't rely on it.

untold moth
#

There is some overhead to lists no matter what. So there's gonna be a difference. Unless the compiler is smart enough to replace a list with an actual array, wich I'm doubtful about.

safe elbow
#

my main point though was wondering why/how those if statements arent in the build as if they were they would be very slow

untold moth
#

Wdym? How do you know that they are not in the build?

safe elbow
#

build as in those if statements dont exist after compilation

untold moth
#

How do you know that? And if they don't exist, what does?

safe elbow
#

as if they were the OldGenerateVertList section would be horribly slow

untold moth
#

Why do you think so?

safe elbow
#

And i dont see any comparisons in the profiler

untold moth
#

These would be part of the "self time", since these are not method calls

#

You can add markers around each of the if statements and you'll see that they are executed properly

safe elbow
#

ill try it

#
            using (m_IFSTATEMENT.Auto())
            {
                if ((edgeTable[cubeindex] & 1) > 0)
                    i = 0;
            }``` would this if statement show up in the profiler?
#

with m_IFSTATEMENT being the marker

untold moth
#

It should, yes

#

*the marker would show up(with it's contents timing). Not the if statement itself

safe elbow
#

the if statement is a comparison so it should be shown taking time no?

#

with deep profiler*

untold moth
#

I don't think so. I don't think basic operations are recorded individually.

#

The profiler works on a method basis

#

Or markers

safe elbow
#

so it does show up as op_Inequality

#

for inequality operator

#

I think i had some misunderstanding

#

For whatever reason i didnt even consider that im not removing the if statements, im just putting them in a for loop lol

untold moth
#

Yep, that's pretty much what happens

safe elbow
#

It is interesting though that it is slightly slower in the for loop because of the array access

#

I wonder if i should use the for loop or just the continous if statements

#

maybe turn it into a switch

untold moth
#

Honestly, I'd look at more effective optimization methods first.

safe elbow
#

for sure

vital fossil
#

Respected, I am using google play services.. for authentication and saving and load data feature of play services.. Should i need to add scope for these features in the google cloud platform.. if yes then how..? Please guide

tardy ridge
#

hi

compact vault
#

if you have a question then just ask

tardy ridge
#

me?

compact vault
#

no, im talking to the othey guy who said hi

#

(yes, you)

tardy ridge
compact vault
#

just ask if you have a question

tardy ridge
compact vault
#

yes, most users here are

tardy ridge
#

okay so you are saying you are good at coding in unity

compact vault
#

yup

tardy ridge
#

CAN WE START A DM

compact vault
#

n o p e

#

just ask in chat

tardy ridge
#

no personal chat

#

i have questions

compact vault
#

then... ask them here

#

good chance i'll make a mistake and someone else can correct me. that wont happen in DMs

#

no asking for !collab s here. besides, i dont really have the time to be a personal tutor

thorn flintBOT
#

:loudspeaker: Collaborating and Job Posting

We do not accept job or collab posts on Discord.
Please, use Discussions to promote yourself as job-seeking, advertise commercial job offers, or look for non-commercial projects to participate in:
โ€ข Collaboration & Jobs

tardy ridge
velvet reef
#

I completed a Udemy course for RPG Core. Finished the course, but the saving system was done using the Binary Formatter class which Microsoft has flagged as having severe security vulnerabilities. Therefore, there is another course that shows how to change the code using JSON. I use Unity Services and asking the experts here. What is a better way, if there is one, to write a saving system that works with Unity Services, like their DevOps? Are there packages in the Unity Asset store that sync with Unity Dev Ops? I would rather not write code from the ground up for an entire Saving System that works if someone far more crafty than I has already added it as a Plug-In?

untold moth
velvet reef
velvet reef
manic basin
#

Hey guys I have a question for multiplayer using Mirror. So my game has 4 players max, but for any player other than the first and last player that joined, the game is always buggy such as enemies not being able to detect the other players and other features also not working for them. Some further context is that if ONLY 2 players join the game, it works perfectly, but if there are more than 2 players, it only works for the first player which is the host and the last player that joined. Thank you in advance guys!

autumn glacier
#

Hey all, I'm really stuck with this hurdle. I've got a graph system that stores nodes (ID and position) and connections (node A and B it connects). I try to calculate my 'enclosed areas', but no matter what algoritm/approach I use, I keep getting duplicates/false areas or overlaps. Anyone knows how to begin tackling this?

compact ingot
#

i would look at algorithms to find all cycles in undirected graphs

#

then analyze these cycles to find the correct ones

#

if you cannot find out which cycles are correct because you lack the data to decide, your graph is potentially underspecified and the problem is not solvable. In your picture, the graph has the appearance of being solvable, but that appearance is data that is external to the data stored in the graph. You could potentially convert the graph into a triangle mesh, where you enforce the graph edges as triangle edges, then you can probably make decisions based on triangle/face adjacency.

bleak citrus
#

I'm a little unclear

compact ingot
#

as in square meters

bleak citrus
#

so, for example, the area enclosed by this cycle?

autumn glacier
#

@compact ingot Thanks for the response! Ah alright. So this means I should consider user-assigned areas? Maybe a little less userfriendly but a quick and dirty option? The appearance of being solvable (but it not being solvable) probably explains why I broke my brain trying to solve it all day lol. The triangulation sounds interesting, I'll look into that!

#

@bleak citrus Correct, you could compare it to walls of a house (in 2D) and I need to know the rooms. Or roads and I need to know the city blocks.

bleak citrus
#

The brute-force approach here would to be find all cycles in the graph, as Anikki suggested

#

Is this graph planar?

#

i.e. there are no crossing lines

#

The main difficulties I can see are dealing with:

  • Cycles whose vertices are a superset of another cycle's vertices
  • Cycles that enclose another cycle
#

for the first case, imagine a graph in the shape of an 8

#

There are three cycles in this graph: the upper half, the lower half, and the entire thing

#

I'm pretty sure you can simply discard any cycle that completely contains another cycle's vertices

#

The second case would be something like this. You'd need to subtract the inner cycle's area from the outer cycle's area. That seems a lot more difficult to reason about.

#

You would be able to create an ordering

compact ingot
bleak citrus
#

So you'd first discard every cycle that is a superset of any other circle, then test every pair of cycles to decide if cycle A is enclosed by cycle B

autumn glacier
#

Yeah, those were the things I kept running into. Duplicates or overlaps (enclosed/superset TIL!). Couldn't find a reliable way to filter that. The not being convex also threw me off.

I guess I chose too big of a hurdle lol. I'll dive into it and give it a try. You both game me some good insights. Thanks!

autumn glacier
autumn glacier
#

Or this

#

Now the 'big' cycle is not fully containing the two smaller ones.

bleak citrus
#

Ah, yeah, you need a less strict criteria

#

Been a hot minute since I did graph theory in grad school, haha

#

I guess you could look at whether another cycle's vertices are either:

  • In your own vertex set
  • Enclosed inside your area
autumn glacier
#

This is a more advanced example. I think I can prevent inside shapes with just the placement.

So I can maybe approach it like this:

  • get a list of all nodes and connections
  • trim nodes with less than 2 connections
  • get all cycles
  • stuck, lol

Or, out-of-the-box:

  • get all nodes and connections
  • find the shortest path to itself on every node (if no path = no area)
  • remove duplicate areas
autumn glacier
bleak citrus
#

well, "simple check" is doing a lot of heavy lifting there ๐Ÿ˜›

#

this has a lot of overlap with mesh generation

#

If you can triangulate the graph, it'll be trivial to decide if a point is inside of a cycle

#

since triangles are convex shapes

autumn glacier
#

Oh that's what Anikki mentioned? I guess I'll dive into that then.

#

This brings me back to Blender tutorials lol. Triangulating Ngons and quads. But that way I could get my areas in the graph?

south ibex
#

I'm writing a custom terrain system w/ an editor for my game and currently working on the detail painting system. The detail 'objects' are instanced geometry drawn via Graphics.DrawMeshInstancedIndirect.

When the user paints on the terrain, it adds to a list containing the type 'DetailObject', which looks like this:

public struct DetailObject
{
    public Matrix4x4 trs;
    public Vector3 normal;
    public float normalOffset;
}

There is some extra processing (ensuring two details are too close, etc) and then the computebuffer that contains the data is released, and then recreated with the new data. I know this is a pretty bad way of updating a compute buffer, but I'm not really sure how to do it better. I know about basic concepts like using BeginWrite on the computebuffer, but I don't actually know how to use it and the documentation isn't any use.

Doing it this way causes the detail objects to flicker while painting due to the computebuffer being constantly released and recreated, which is distracting and ugly.

Here's what my update compute buffer code looks like:

public void UpdateDetailBuffer()
{
    //After the newly painted detail objects are added to allDetail, this function is called.

    if (mpb == null)
        mpb = new MaterialPropertyBlock();
    if (allDetail.Count == 0)
        return;

    //ToDo: Figure out how to use ComputeBuffer<T>.BeginWrite and ComputeBuffer<T>.EndWrite 
    detailBuffer?.Release();
    detailBuffer = new ComputeBuffer(allDetail.Count, Marshal.SizeOf(typeof(DetailObject)));

    detailBuffer.SetData(allDetail.ToArray());
    mpb?.SetBuffer("_TerrainDetail", detailBuffer);
}

How can I rewrite this to use BeginWrite and EndWrite?

bleak citrus
#

Although, you have to know which face is which

#

which is part of your problem

#

There's got to be some prior art here

south ibex
south ibex
#

for more clariy this is the issue I'm trying to fix

#

detail objects flicker as the user paints due to the computebuffer being deleted and recreated

sly grove
#

Instead of creating a new one

south ibex
#

If I have a ComputeBuffer that's storing 1000 detail objects and then paint 100 more and then try to add that data to the ComputeBuffer, I get an error

sly grove
#

It's not uncommon to have a limit on the number of objects the user can place

#

You could also have it delete/overwrite the oldest objects when you reach the limit, like a ring buffer

humble loom
#

got an interesting question, thought it was simple but apparently not so much

#

so I'm prepping this project for the asset store, and this asset generates code. I want it to generate it inside the folder of the asmdef of the asset just to not pollute the user's heirarchy, but at the same time i also don't know where exactly they're going to put this assembly.

So what I'm trying to do is determine (not runtime, at edit time) the root path of NisGab.asmdef, then from there just combine it with /Scripts/Generated/. anyone know how to do this?

echo coral
#

you should be able to find the NisGab asm def asset with AssetDatabase.FindAssets()

#

You could also grab its guid and do guidtoassetpath

humble loom
#

what would you filter in FindAssets to get it?

echo coral
#

perhaps "NisGab t:AssemblyDefinition" ?

humble loom
#

oh ok its literally just like the explorer filter neat

echo coral
#

yea you can filter to most asset types like Texture2D or Prefab

humble loom
#

hate that i have to put a magic string but if it work

echo coral
#

well otherwise if you know the GUID of the asm def asset you can get the path directly with that

humble loom
#

would the guid change if someone downloads and imports the asset tho

echo coral
#

i dont think so

thin mesa
humble loom
#

ok i could try that

heavy blade
#

basically using a compute shader I send a list of points from the CPU to the GPU, do the math to project it into 3D space, and I send it back to the CPU

#

then I send it to a second compute shader kernel that draws all the lines to the screen, and the result's in the video

#

I'm doing it like this because I was able to boost my performance by splitting up the task into two kernels that use threading differently, so I was basically able to double the amount of lines I could render without lagging

#

but would there be a way to handle this without having to send information back to the CPU in the middle of the calculation? that's still a big bottleneck in my system even though I was able to boost the performance a little

#

i'm technically not really gonna need to be able to render more lines than I can handle right now, I just want it to be able to lol

#

here's the relevant code

#

basically if possible I want to avoid having to juggle the information between the CPU and GPU bc that kinda defeats the purpose of using a compute shader in the first place, but I can't really think of a way to share information between kernels?

worldly pecan
#

Why donโ€™t you reuse the same buffer? That way you stop readingback?

CS.SetBuffer(1,โ€calculatedBufferโ€, buffer);

Get rid of the middle man

autumn glacier
#

@bleak citrus @compact ingot : Thanks again for the help, wanted to let you guys know I found a solution. I couldn't quite grasp the triangulation but for now I brute-forced a solution, that kinda is an abstract way to do the triangulation.

I do the following:

  • get a list of all cycles
  • cycle holds a list of the nodes, each with a normalized/sorted string
  • all duplicate strings get removed
  • now we have a filtered list
  • each cycle is now turned into a polygon
  • a 'is point in polygon' check for each cycle with every node in the scene
  • same again, but with the midpoints of each edge in the scene
  • if one of the two above is true at any point, we remove the cycle

And now we have a list with all small cycles in our planar undirected graph. Maybe it can help someone else. ๐Ÿ™‚

heavy blade
#

unless I'm wrong i thought the only way to get data back from the compute shader was to read it back into an array

untold moth
heavy blade
#

i did realize I don't actually need to be reading it back, in the first kernel i'm modifying the buffer anyway, so if I just dispatch the second kernel anyway it reads from the modified buffer on the GPU side

untold moth
heavy blade
#

oop, exactly lol

#

now the only thing limiting performance is the shader itself which shouldn't be hard to test

untold moth
#

One thing you should be careful about is race conditions though. If both shaders run anywhere close to each other, there's a chance that the second one would start reading the buffer before the first shader is done.
In this case, you should use a barrier.

heavy blade
#

mm right, how'd i do that?

#

like set a condition once the first one's done, and prevent the second one from running until the condition's met?

#

ah i see

untold moth
# heavy blade ah i see

No. That's something else(for syncing threads in one draw/dispatch call). The barrier command that I'm talking about needs to be called/queued on the CPU side.

#

Though, it's possible that unity does it itself under the hood. You'll need to test it out and see if you get any issues without a barrier.

heavy blade
#

sure, i'll check it out

#

thanks for the help!

worldly pecan
# untold moth One thing you should be careful about is race conditions though. If both shaders...

From my experience thatโ€™s not possible. The dispatch commands for compute shaders are put into the same command queue unless using a command buffer and the gpu is guaranteed to poll and complete a previous command before it attempts moving on to the next one in this queue. Either that or Unity underneath is adding a gpu fence after every dispatch

I donโ€™t have any sources on this but from testing Iโ€™ve never had to ever consider race conditions like this

#

Also you could use renderprimitivesindirect to avoid reading back entirely unless you need it on the cpu for non-rendering reasons

south ibex
#

Has anyone got any examples of Unity Jobs being used for marching squares? (and I mean specifically marching squares, not marching cubes)

#

For my custom terrain system, I'm using a modified version of the marching squares algorithm and I'm looking into moving the generation code to Unity Jobs.

It's pretty daunting and I'm struggling to figure out how to do it, but if there's any existing examples for Unity Jobs marching squares that already exist, it should help me a lot

sly grove
south ibex
#

There's a reason I specifically ask for code examples because that's the main way I learn.

#

Because I do not fully understand the jobs API, I do not know what types can and cannot be used in a job. Having code available lets me immediately know what types I should be using

#

For example, I've been trying for the last hour to figure out how to write to a native list of Vector3 (vertex positions for my mesh) and I am blocked on a single error and after around 10 different pages of documentation I'm still not sure how I'm supposed to write mesh data in a job system

#

I'm not asking anyone to spoon feed me code, I'm simply asking if anyone knows of the existance of a github repo that contains jobs code for generating a mesh with marching squares

pastel whale
manic wadi
#

when you're to the point of making meshes, look up Mesh.AllocateWritableMeshData and Mesh.ApplyAndDisposeWritableMeshData in the docs, there's some example code in there

cloud token
#

hey would anyone be able to help me out with a quick instantiation issue im having?

#

im using photon pun 2 by the way

thorn flintBOT
#

:thinking: Asking Questions

:mag: Search the internet for your question!
:book: Use the API Scripting Reference and User Manual and this troubleshooting site for commonly posted issues.
:wrench: Attempt to debug your issue.
:thought_balloon: Find an appropriate channel by reading the name and description in #๐Ÿ”Žโ”ƒfind-a-channel
:grey_question: And don't ask to ask, ask a full question illustrating with screenshots if needed.
-# For more posting guidelines, go to #854851968446365696

cloud token
#

is this not where i ask for help?

thin mesa
#

Pay particular attention to the last few points

cloud token
#

ahhhh

#

sorry about thatr

#

so im having an issue at the moment where if i were to start a game, then use another client to join said game all works fine. But if i were to leave and rejoin that same lobby i spawn and see an extra pair of arms with both my primary and secondary weapons, static, where i spawned, but this instance that did not happen and it spawned in a random location. im assuming its instantiating problems OR an issue with the clean up when i leave and rejoin, i just realized that when i rejoin the other clients dont the "player has joined the match" message.

cloud token
#

ah alright, thank you

supple nymph
#

i need a tutorial on linking phones to unity to control
like this https://www.youtube.com/watch?v=7SbNYv01bGk&ab_channel=AmalJoy

As we know, mobile phones as already equipped with a number of sensors. This is a small prototype game which I made in Unity. In this project I have used mobile phone as a motion tracking input controller. The attempt was to make kinect like controller on zero budget. The sensor data from mobile is transferred to PC (Laptop) via wifi. After that...

โ–ถ Play video
#

specifically i need the phone's accelerometers
xyz

livid kraken
#

What you need is a tutorial on how to send data over lan. Im sure you will find one.

#

Then you can build a small unity app to run in the phone and send the data over

supple nymph
#

can you help me find that tutorial

regal olive
cloud token
#

I'm going for that early 2000s feelings ๐Ÿ˜‰

#

Huge fan of the older call of dutys, especially world at war so I'm hoping to make a game similar to that, just can't get past this speed bump

regal olive
cloud token
#

Makes for gritty gameplay haha

regal olive
#

Yeah

neat harness
#

Does UnityEvent<float> let you pass the value when I invoke in code to another function connected via inspector?

#

So far it only logs the value from inspector

compact vault
plain abyss
#

Not the "Constant" one where you enter in the float you want to pass

neat harness
#

Oh it wasn't appearing at first or I'm blind

#

Honestly this is fantastic, I've been using Unity for years and never knew this was possible

#

But Godot does have a substantially better implementation with its signals.

echo coral
#

Events exist in C# anyway, unity events are needed only for doing stuff via the inspector

#

99% of events I use are traditional events and any unity events are not subbed via the inspector either

crystal oar
#

I have a top down game, im procedurally tilting the character model based on input. but when i rotate the character model to say look left, and then i start moving, it tilts based on its rotation so clicking W which moves you up it would Yaw left instead of pitching down, how do i make it tilt based on world XYZ or even based on the Character Controller rotation which doesnt rotate?

slate spoke
#

Currently writing an indirect mesh renderer that spawns a bunch of the same model across generated terrain, with each terrain chunk having its own renderer. With the way it works right now, the rotation of every plant is only randomized to every renderer, so all of the plants in the same chunk have the same rotation. How would I fix this?

    [BurstCompile]
    private struct InitializeDataFrameMatrixJob : IJobParallelFor
    {
        [WriteOnly] public NativeArray<Matrix4x4> _transformMatrixArray;
        [ReadOnly] public NativeArray<Vector3> _coordinates;

        public void Execute(int index)
        {
            //Debug.Log(_coordinates[index]);
            var random = new Unity.Mathematics.Random((uint)index + 1);
            _transformMatrixArray[index] = Matrix4x4.TRS(_coordinates[index], Quaternion.Euler(-90, random.NextInt(0,360), 0), Vector3.one /** random.NextFloat(0.9f, 1.1f)*/);
        }
    }```
untold moth
slate spoke
sly grove
#

Random is a struct in Unity.Mathematics

#

so if you're passing it around to a bunch of threads they're all going to start with the same copied state

#

they're not going to be updating the state of a shared object somewhere

#

oh I'm a dummy it's being initialized right there

#

add some kind of unique id per plant to the job

#

you could use the InstanceID of the GameObject for example

#

then you would do:

var random = new Unity.Mathematics.Random((uint)index + 1 + plantId);```