#archived-code-advanced

1 messages · Page 127 of 1

untold moth
#

Yeah, so rewriting that linq should probably make a big difference now

slate spoke
#

mhmm

#

I am not looking forward to that

untold moth
#

Helping? It was 1400ms before. It's 400 ms now

#

It definitely wasn't helping at all.

slate spoke
#

yeah

untold moth
#

You should look at the time values mainly

slate spoke
#

fair

#

I probably also need to figure out why that time thing wasn't working then

#

it's supposed to be what lets the math happen over several frames instead of one

untold moth
slate spoke
#

right

#

...I have no clue how to go about this not gonna lie

untold moth
#

Well, what is it supposed to do?

slate spoke
#

compare the xRange and yRange lists to see which ones have matching index property values

untold moth
#

So, basically get all elements in xRange that have an element in yRange with the same index?

slate spoke
#

yeah

untold moth
#

Well, the simplest way would be a nested loop

for(x in xRange)
{
  for(y in yRange)
  {
    if(x.index == y.index)
    {
      resultList.Add(x);
      break;
    }
  }
}

Something like this..? This is pseudocode obviously

slate spoke
#

I'll try that, though I feel like that also kind defeats the point of this whole algorithm

untold moth
#

wdym?

slate spoke
#

to avoid having to iterate over the entire list

untold moth
#

Well, your linq seems to do it anyway

slate spoke
#

ah

untold moth
#

So there probably was not a point in it in the first place

slate spoke
#

damn ._.

untold moth
#

You could make it work though.

#

Assuming I get what you're trying to do correctly:

for(int x = startIndex; x < endIndex; x++;)
{
  var elementX = xRange[x];
  //refactor this loop in the same fashion
  //for(y in yRange)
  //{
  //  if(x.index == y.index)
  //  {
  //    resultList.Add(x);
  //    break;
  //  }
  //}
}

Something like this?

slate spoke
#

ah, I think I see the misunderstanding here maybe

#
    public class Umap_x
    {
        public int index;
        public float value;
        public Umap_x(int index, float umap_x)
        {
            this.index = index;
            this.value = umap_x;
        }
    }
    public class Umap_y
    {
        public int index;
        public float value;
        public Umap_y(int index, float umap_y)
        {
            this.index = index;
            this.value = umap_y;
        }
    }```
#

the "index" property of these refers to their index in the original full dataset

#

which is kept so that we can instead go through the list sorted by coordinate value

#

then just call the datapoints by index once found

#

perhaps it should be renamed to originalIndex or something

untold moth
#

I don't see how that is relevant to my example. Or the conversation so far🤔

slate spoke
untold moth
#

No. It was in reference to refactoring this piece of code:

    xyRange = (from x in xRange
                  join y in yRange
                  on x.value equals y.value
                  into matches
                  where matches.Any()
                  select x).ToList();
#

Which is the main problem currently

slate spoke
#

right. Unless startIndex is 0 and endIndex is the last index in the list, I don't see the difference between using for(int x = startIndex; x < endIndex; x++;) and for(x in xRange)

#

the index property value != the element's index in the list we're going through

untold moth
#

Right. Then just keep it as the first pseudocode that I shared.

#

Or I guess, it was supposed to be value, not index.

#
for(x in xRange)
{
  for(y in yRange)
  {
    if(x.value == y.value)
    {
      resultList.Add(x);
      break;
    }
  }
}
slate spoke
#

no index was right

untold moth
#

Might want to do approximation equality to avoid floating point errors too

untold moth
slate spoke
#

..that's probably why the actual search wasn't working

#

good catch lol

#

...performance has dropped significantly

untold moth
#

Share the updated code

slate spoke
untold moth
slate spoke
#

no allocations at least

#

I'm gonna take a wild guess and say that it's the iterations causing the problem though

untold moth
#

Yeah.

slate spoke
#

at least we know the other parts of the code are doing their job

#

if there isn't a way to do this without iterating over every point, I think we're back to needing to change the actual method of search

#

this has been my life the past month or two, it feels like

untold moth
#

I think ideally you want the xRange and yRange being arrays with the index being an actual index into the array.

#

if the purpose is just to confirm indices, they can even just be bool arrays that you set to true if the element at that index exists.

#

Then the search would be as simple as if(xRange[index] && yRange[index])

slate spoke
#

true, but with index being in reference to the original 680k length dataset, there'd be gaps in both arrays

untold moth
#

That's fine. The gaps can just be set to false.

slate spoke
#

that still means we'd be iterating 680k times

#

unless we knew the lowest and highest index value of either list, I suppose

#

but that could still be 680k worst case

untold moth
#

Actually, I take it back. I was too focused on that linq(not nested loops part). But it's kinda meaningless to do it without looking at the whole picture

#

So basically, you want to get all the testimonies that have value in a range between min and max?

slate spoke
#

yeah

#

which is I think why I was being recommended to use a K-D Tree earlier

#

which I do already have an implementation of kinda, but I didn't write it, it only finds the single nearest point as far as I can tell, and it's not async

#

and the only ways to do that by searching for fixed size areas are by either assigning XY indices to each datapoint based on what fixed size area they lie in, or creating arrays for each fixed size area

#

which at that point defeats the point of doing literally any searching because the whole reason why this function exists is to figure out which datapoints lie on specific terrain chunks

#

so you'd be basically storing every single datapoint in memory anyways

#

I'm trying to work on not being a defeatist, but this sucks a lot

#

genuinely feels like the final boss of programming despite how easy it initially seems to anyone I go to this about

#

like for gods sake, my job here is to make a data science visualization tool that runs basically realtime in VR on phone hardware with unstylized realistic graphics

scenic forge
#

Storing 670k points in memory, assuming each point just needs 3 properties for range query, is not even 8 MB.

slate spoke
#

that makes me wonder why I was ever told to avoid having it all in memory, then

untold moth
#

And then you can spread it over several frames

untold moth
slate spoke
untold moth
#

We'll need to see the context of that conversation. But perhaps there was just a misunderstanding. Did they not provide an explanation?

slate spoke
#

they did, but it's hard to recall at this point

untold moth
#

Well, it's not like that's relevant ATM anyway.

#

Unless you can do it without this method at all

slate spoke
#

if it wouldn't be too computationally intense to have what I guess to be a 2D array of lists, then maybe

#

but then again, we go back to the issue of the data distribution being uneven

#

which means if you're allocating the same amount for every list, in order to get everything each list needs to fit like at least 200 points

#

and a third of those lists will probably end up being empty

untold moth
slate spoke
#

right

untold moth
#

So basically the issue we have now with a refactored code is that you have these 2 range that are sorted in an arbitrary way. Which theoretically causes most of the elments to be looped.

scenic forge
#

Random access is about the most efficient thing you can do, and is the reason why grids are so fast (faster than KD tree)

untold moth
# untold moth

We can make it better by sorting one of the lists(the internal one), so that breaks are hit more efficiently.

scenic forge
#

You can do some napkin math to see how much memory is needed, I doubt you would have issue fitting them all in memory.

untold moth
#

But honestly yeah, I'd rewrite the whole thing.
It's just a matter of using an existing solution and optimizing it as much as possible or tearing it down entirely in favor of a more efficient solution.
If you have enough time, the latter is preferred.

slate spoke
#

and also having an understanding of what approaches are gonna eventually result in a dead end several weeks into trying to get it to work the way you want

#

random access should (theoretically) be easy to implement quickly

untold moth
#

I mean, it's not like it's a dead end. It works. And there are ways to optimize it.
The understanding of what would be better for a given task comes with experience, but you can never be 100% sure.

slate spoke
#

I have 5 days and about 25 hours of paid work left to pull this off though

#

well, 4

#

needs to be ready before the 24th, so done by 23rd

#

just hoping I can afford another total rewrite

slate spoke
#

200MB

#

that still doable?

deft palm
untold moth
slate spoke
#

quest 3 has 8GB total

untold moth
#

So, as long as your whole program consumes less than 8 GB, it's fine.

exotic trout
#

Minus OS kinda stuff I assume

slate spoke
#

right

#

...I can't figure out how to prealloc a 2D array of lists ._.

#

which I'm trying to do because I need a way to know how many elements have already been added to a specific tile

untold moth
slate spoke
#

would the struct just be the list itself?

untold moth
#

I'm still not sure what you're trying to do. If you do need a list, just use a list. There's no point in putting it into a struct

slate spoke
#

I need a 2D array of lists that's 500x500, with each list allocating 200 elements

untold moth
#

Why not use a 3d array instea of a 2d array of lists?

untold moth
#

Make a 3d array of structs that contain an extra variable with whatever data you need

slate spoke
#

I can't seem to do array[0,0,].length

untold moth
#

Why would you need that anyway?

#

what does that 3d dimension represent?

slate spoke
#

the third dimension is all of the potential coordinates that lie within a specific tile

#

I have no way to know how many will be in each

#

so ideally, I would use list's .Add()

untold moth
#

Then just make it 200. And fill only those that should contain valid data

slate spoke
#

that's what I'm trying to do

slate spoke
untold moth
#
struct TileStruct
{
  int[] points;
  int count;
  public TileStruct(int[] initialData)
  {
    points = initialData;//or copy
    count = initialData.Length;
  }
}

TileStruct[,] tiles = new TileStruct[500,500];
untold moth
# slate spoke

If you want to go this path, then you can't initialize the lists. You'd need to do it later.

... = new List<int>[500,500];
slate spoke
untold moth
#

You can init it in the constructor if your want.

  public TileStruct(int num)
  {
    points = new int[num];
    count = num;
  }
slate spoke
#

is that not what we're trying to avoid?

slate spoke
#

I don't have a way to know the length of the array before it's added

untold moth
untold moth
slate spoke
#

if not when it's initialized?

untold moth
#

you do specify it when you initialize the contents of the 2d array

#

Assuming we're talking about the struct path, you're allocating the array with structs in the field initializer. But the structs in the array are empty/ default initialized. So you need to initialize them with the data that you want them to have.

slate spoke
#

if I'm going through the entire dataset element by element, how do I get the entirity of the data that goes into a specific tile first?

#

and wouldn't that mean I'm still allocating after initialization?

#

I'm trying to avoid what was happening earlier with the xRange and yRange lists

slate spoke
#

and repeat for every tile

#

that can't be the best way to do this

untold moth
#

It depends on how the data is stored in whatever you have initially.
But yes, it's likely that you'll need to iterate all the tiles once.

slate spoke
#

right, I want to make sure I'm doing that only once

untold moth
#

And that being said, it might be wiser to actually just copy the tile data into your 2d array directly. Because extra lists/arrays would cause allocations.

#

Again, I don't have the whole context so I can't say anything for sure.

slate spoke
#

that's what I'm trying to say

slate spoke
slate spoke
#

if I'm allocating as I'm going through the datapoints, that defeats the point of what we've been trying to solve all day

untold moth
#

This is not the context.
I don't know what exactly your tiles represent and why do they contain points? You'd think that a tile is the smallest unit of data. But this doesn't seem to be the case here?

slate spoke
#

tiles represent terrain chunks

untold moth
slate spoke
#

each datapoint in the game I'm making is represented as an object on the terrain

#

thus the coordinates

slate spoke
#

I'm sorry I'm just getting frustrated and exhausted

untold moth
#

Then set it to max of 200.

slate spoke
#

can I do that beforehand?

#

and not during?

#

like we were with the lists?

untold moth
#

A 3d array of [500,500,200] should work

#

If it's a 3d array, yes.

slate spoke
#

alright. with a 3d array of ints, do I have a way to check how many values have already been added to the z array of a specific xy?

#

that's why I mentioned not being able to do array[0,0,].Length earlier

#

because if I'm adding datapoints element by element, I need a way to know where in that array to put the datapoint

untold moth
#

No. You'll need to keep that data somewhere else

#

Like a 2d array of ints

slate spoke
#

so I'll need a 3D array of [500,500,200] and a 2D array of [500,500]?

untold moth
#

Yep

slate spoke
#

okay, thank you

#

it took me an hour to figure out how to define a single variable

#

I feel fucked lmao

untold moth
#

You could do it with a 2d array of structs, but you will need to initialize them manually which might be less efficient.

untold moth
untold moth
#

If you just ignore the errors and things that don't work and switch to solutions that do work, you'll never know the correct way. It would just come back to bite at you later.

slate spoke
#

that's fair. I'm just trying to focus on getting it done because of how little time I have

slate spoke
#

..alright, new problem

#

apparently with the current sample size, some terrain tiles still have 300+ points

#

... 400+ points

untold moth
#

Then just increase the size

slate spoke
#

..... 1000+ points

#

this array is gonna have to be over a gig

untold moth
#

If you can afford it, go for it. But it's really weird. What kind of tiles are these? How big are they? Why would there be 1000 objects on a tile?

slate spoke
#

there'd be over 1k apparently because the dataset has clusters that tightly knit

#

so I'm likely gonna have to make overall grid larger

#

more tiles, that is

#

1000^2 with 500 per tile is 2GB

#

I'm at least smart enough to have made the terrain generation procedural

#

so world size isn't an issue

#

even with that, it's hitting max tile capacity only 60k points into the dataset

#

fuck

untold moth
#

Might want to investigate what your dataset looks like

slate spoke
#

I know what it looks like, I mentioned this being a potential issue

#

uneven distributions

#

public int[,,] testimonyTileIndices = new int[2000, 2000, 500];

#

fuck

#

it just straight up won't let me make a variable big enough

#

if my python fuckery is correct, I might be able to get away with filtering the dataset before populating the tiles

#

I'll just have to figure out how to get the full dataset functioning another time

untold moth
untold moth
#

Maybe try a native array then

slate spoke
slate spoke
untold moth
slate spoke
#

how much of a difference would that make?

untold moth
#

It would be slightly less convenient to work with. But in terms of performance it should be superior

slate spoke
#

how superior, though?

untold moth
#

less overhead

#

Can't say anything specific though

#

At the very least it's not gonna be slower

slate spoke
#

so I should make a NativeArray of length 2000000000?

untold moth
#

Yeah. See if it throws the out of memory error.

#

That being said, it's weird that that error appeared in the first place.

#

Are you sure you were only having one of these scripts in the scene?

unkempt nova
#

From my understanding, an array needs a contiguous memory space

#

So if it can't find one, it'll throw an out of memory exception

slate spoke
unkempt nova
#

Could be

#

I wonder if you're just running low on RAM when this happens

#

I suggest restarting and running your game and seeing if this error magically goes away, an easy test

slate spoke
slate spoke
untold moth
#

I can only guess that it's due to the nature of how managed memory allocated.

#

To be safe, I'd keep an eye on the memory profiler(or at least the memory module in the regular profiler).

unkempt nova
#

Memory can be fragmented to where you can't get a contiguous segment. Just speculating

untold moth
#

Yeah, but I wouldn't think that would happen with 64GB of ram. Assuming they're not using most of it.

unkempt nova
#

Yeah it's unlikely

untold moth
#

Could be the managed allocator limitation. Like maybe there's just some internal limit to how much it can allocated in one operation and they simply don't have a specific error message for that.

slate spoke
#

unity is using a lot, outside of runtime

unkempt nova
#

30GB? Holy shit

#

I've never approached that even using GPU animations

#

I suggest profiling for memory leaks or something

slate spoke
#

surprising people with how fucked my unity project is seems to be a running theme

#

my head hurts, I need a break

untold moth
#

This is not neccesserily a leak or an issue. As long as it doesn't increase over time, it's probably just how it reserves memory in you specific sceanrio.

#

native arrays should be free of this limitation

slate spoke
#

how should I be accessing the array once it's 1D?

unkempt nova
#

I wanna say modular arithmetic

#

You're compressing a 3D space into 1D, so you need to devise a way to do that. You need to find a reasonable way to segment it to map it

slate spoke
#

right, that's what I'm asking about

unkempt nova
#

What does your data here represent?

slate spoke
#

xy are indices of terrain tiles

#

z is a list of indices from a dataset

#

it's to be able to grab all of the datapoints that fall within a specific tile and just call them by index

#

full dataset is 680k datapoints and the spread is nonuniform

unkempt nova
#

I don't have a ready made solution, but modular arithmetic is your answer here to flatten the 3D array into 1D

#

That should be your search string though, flattening a 3D array to 1D

untold moth
unkempt nova
#

But the inverse is what he needs, I think? I might be misunderstanding; but that's why I say modular arithmetic

#

Like, he'll be WORKING with a flat native array and need 3D indices into his existing array right?

slate spoke
#

right but I only ever need to access it by index I think

#

so I can just math the index

#

testimonyTileIndices[xTileIndex + yTileIndex * 2000 + tileIndiceLengths[xTileIndex + yTileIndex * 2000] * 2000 * 2000] = (int)testimony.index;

#

I think that's what I need

#

idk

untold moth
#

Probably. Might want to test a few examples on paper.

#

Then you can create a utility function to not write it out every time. I'd also avoid magic numbers and use the actual array lengths instead.

slate spoke
#

restarting unity

untold moth
#

Yeah, at this point you might be doing something wrong

#

Maybe use the memory profiler

slate spoke
#

gotta install it

#

also probably gonna use it tomorrow

#

I can't think about this right now without popping more advils

#

gotta message my employer with the "hey so uh we might not meet the deadline" email

#

and then also skip on easter tomorrow

#

I'm in hell I think

untold moth
echo coral
#

Im trying to catch up with this and why do they need a 8GB array? (basing this on new int[2000, 2000, 500])

slate spoke
#

500 is the max amount of points a specific tile can have, at least with current settings

#

without filtering and without changing the amount of terrain tiles, that goes up to like 4k or 5k

#

that number is as high as it is because the data distribution is way uneven

echo coral
# slate spoke

Hmm then may be wise to do a hybrid system where you split the data only 1 or two times (kd tree) to minimise the wasted space and need to allocate such a large single array.

untold moth
# slate spoke

With this kind of distribution at this scale, having a 3d array is gonna be inefficient indeed. At this point it's gonna be an issue just to run the program on your target device.

#

You'd need some kind of data streaming implementation.

Though, given the time constraints, using a 2d array of lists might be enough for now. Just make sure you allocate and initialize it once.

slate spoke
slate spoke
untold moth
#

You'll need to loop it and assign lists in start/awake.

#

Or maybe init it lazyliy when the tile list is first accessed

slate spoke
untold moth
#

And then you can also think about doing your processing async properly.
I think this is the best course of action given all the info that you shared.

slate spoke
#

or what that implementation would look like

untold moth
echo coral
#

My shit illustation. You would want many dimensions for the dense areas and the less dense ones can stop earlier, depending on the depth it will let you reduce the total size of the structure to hold the actual data (if using a 2d array)

#

I suggest this again because of the issues of trying to have a large collection to cover all of this range

#

This can be pre processed (if possible)

compact ingot
#

A kd inherently ends up more dense where there are many points

#

It also doesn’t need ‚buckets‘ and scales to many dimensions better than trees that split on all dimensions

untold moth
#

I'm not sure they can implemented given the time constraints.
Maybe get the current implementation working to a degree and then try to implement the kd tree path in the remaining time.

scenic forge
#

What query size are they going for anyways?

untold moth
#

Arbitrary apparently.

#

Though maybe not. Maybe they just didn't decide.

scenic forge
#

Yeah there's no way they simultaneously need to query the entire map or a tiny tiny part of the map that is so small that it contains nothing.

untold moth
#

I think the profiler data had 64 calls to the search method that they had, so perhaps 64 tiles at any given time

scenic forge
#

Giving that illustration the map size is about 50x50, if they need to query a 0.1x0.1 area, and use 0.1 as grid size, that's only 1 MB memory and skips all the complications of a KD tree.

untold moth
#

It seems like they can adjust the tile size, but if they use 2000x2000 tiles, each might have 500 or so data points(positions). That's where the 8GB come from.

scenic forge
#

The memory required to store the points themselves should not enter the calculation, no matter what data structure you use they must be stored, the only comparison to be made is the data structure itself.

untold moth
#

This was just to store indices apparently

#

To be honest, if just the indices take that much, it's just gonna be impossible without some kind of streaming system.

slate spoke
echo coral
#

it needs to be smaller so you can cut out the empty space making this unusable

slate spoke
#

though ideally there would only be about 50-100 max per tile, just so the terrain isn't completely covered

scenic forge
#

That's not how the calculation works.

#

Well, assuming you are doing List<Point>[,], if you were thinking Point[,,] then sure.

untold moth
#

It was assuming they preallocate lists of some capacity

untold moth
exotic trout
#

I don't wanna disrupt the support here, mostly just lurking for my own curiosity/learning but just a little curious about mentions of a 8gb array. With the Quest's OS in mind and the entire rest of the game + it's realistic art-style won't anything like this have to at max use far, far less in terms of memory?

echo coral
#

The issues are 3d float position to index look up time and memory usage of this mapping right?

slate spoke
#

2d float position, but yes

untold moth
slate spoke
#

z axis positions are calculated based on the terrain generation code

#

not super relevant here though

scenic forge
#

You definitely don't need 8 GB, looking at that graph only ~10% of the grids will have any point at all.

exotic trout
#

yeah 7gb then minus however much it's gonna take to do the rest of the game. Could be not as big of a deal in this project but I've seen a lot of complaints that a lot of games run into memory issues with that much still

scenic forge
#

List<Point>[,] and keep the empty grids null. I'd be surprised if the data structure even goes over 1 GB.

slate spoke
#

the problem then is the allocations done afterwards

untold moth
#

In terms of memory that's gonna be optimal. But then we're back to several seconds of loading time

#

Which is why I suggest to preallocate the lists with a median length across the data set.

slate spoke
#

I can have the load time take a few moments, I just need that to not happen in a single frame

scenic forge
#

Does load time even matter, do players actual expect your game to load instantly with this big of a data set?

slate spoke
#

ideally locked to 120

scenic forge
#

Just have a loading screen or something, people won't care if it takes a few seconds to load but smooth as butter afterwards.

slate spoke
#

realistically, 90

echo coral
#

Half life alyx has loading between levels and its fine

slate spoke
echo coral
#

Just do it all on another thread to keep your loading screen running well

slate spoke
#

that's what I've tried to do

#

My implementation was either incorrect or fundamentally flawed

scenic forge
#

I don't see how either grid or KD wouldn't work for that.

echo coral
#

Ofc it it produces a lot of garbage during the load then gc spikes return

slate spoke
echo coral
#

it doesnt need to be async and probably shouldn't if you just want to distrubute it over many main thread frames

scenic forge
#

I'm not suggesting KD tree to you, since you are having issues with the bare basics. A grid can be done in like 10 minutes.

untold moth
#

Well,get it working with a 2d array of lists first and then implement the async functionality.

slate spoke
#

I did have a class specifically made for trying to get async functionality working with a frametime budget, but that apparently wasn't functioning as it should

#

I'll try to get the 2D array of lists working once I have unity open again tonight

echo coral
hasty knoll
#

Anyone good with A Star path finding Algorithms?

echo coral
hasty knoll
#

Well, I'm in the middle of implementing mine, I have quite the specific issue with it

#

I've drawing the grid over my current tilemap, but it's showing random connected nodes which are outside the map but it's only a few, I've added a mask - lets call it avoidance layer which includes my water/obstacle/default layer. But they're still showing outside the designated area. I'm not sure if I'm allowed to send pictures but it would help you get a better visual picture

echo coral
hasty knoll
#

tyvm though big appreciate

echo coral
vagrant tartan
#

Ok this has been driving me crazy for the last hour...

I have a function that takes input Vector3 and returns one of its values as an int

{
int dirX = (int)Mathf.Sign(inputVector.x);
Debug.Log(dirX);
}```
my input vectors go -1, 0 or 1
you would think that (int)Mathf.Sign(inputVector.x) is exactly the same as (int)inputVector.x
but apperantley its not??

if I enter a value that doesnt affect x, so x should be 0:
(int)Mathf.Sign(inputVector.x) returns 1 while (int)inputVector.x retunrs 0

```csharp
        Debug.Log("input vector3 is: " + inputVector  +
            ", Mathf.Sign(inputVector.x) is: " + Mathf.Sign(inputVector.x) +
            ", (int)inputVector.x is: " + (int)inputVector.x);

Debug Log: input vector3 is: (0.00, -1.00, 0.00), Mathf.Sign(inputVector.x) is: 1, (int)inputVector.x is: 0

Full Vector3 value: (0,0000000000, -1,0000000000, 0,0000000000)

TLDR for Vector3 (0.00, -1.00, 0.00) Mathf.Sign(inputVector.x) 1
why😭 ???

devout hare
#

Returns a value of 1 when f is 0 or greater.

echo coral
#

should use Mathf.RoundToInt() instead

vagrant tartan
#

oh..

#

damn, i really should have looked at the Sign function, but copilot wasn't wrong about these things before 😱
you are so right, it says return (f >= 0f) ? 1f : (-1f); one click away

#

thanks!

echo coral
#

ai makes shit up

vagrant tartan
#

ye but usually about obscure functions or if you give it something big
i just started a new dialog and its still super convinced that Mathf.Sign is capable of returning a 0

#

guess they dont have it much in training data

vagrant tartan
#

actually i take my words back, ai gaslighting me is pretty funny

austere jewel
slate spoke
untold moth
# slate spoke

It seems to only consume 16gb at the moment. But you can inspector it further there's the inspect button next to the allocated memory distribution

slate spoke
#

not sure how to derive meaning from this ngl

long ivy
#

the meaning seems pretty clear to me. You have two ultra-massive allocations. Are you loading something into NativeArrays? Is there a package loading data? It must be huge, or incredibly wasteful

slate spoke
#

tldr, 670k datapoints of XY float coordinates, massively uneven distribution

#

the idea is to have the space for all of those datapoints preallocated so that we don't have an issue we ran into before, where 125 million allocs were happening in a single frame when loading in the dataset initially

#

to clarify, these datapoints are gonna be visualized as objects on procedurally generated terrain, and the datapoints to render are gonna be loaded in by calling the indices of the currently loaded terrain tiles

#

but random access is very much not gonna work here, at least with a 3D array

#

so we're about to try a 2D array of lists with only about 50 points preallocated per tile

long ivy
#

670,000 * 8 bytes = 5.36 megabytes. This should fit into a few tens of megabytes in the worst case scenario with some overhead. 14.9GB is enough to store billions of float pairs. You must have a ton more info for each data point? Just with some rough math, you must be storing nearly 3k floats per data point?

slate spoke
#

some tiles (a lot actually) have zero points

#

some have over 4000

#

and that's with the total dataset distributed over a grid of 2000x2000

#

so, to alloc the max amount for every tile

#

2000^2 tiles * lets say 500 points per tile * 4 bytes for each datapoint's index in the original dataset

#

you can start to see the issue probably

#

and that's just with the 3D array

#

once that's alloc'd, you have no way to know how many points are already stored in each tile

#

so you then also need another 2D int array of 2000^2 tiles to keep track of each tile's array length

#

thus part of why we're swapping to lists

slate spoke
#

(in the start function)

long ivy
#

I glanced over the context and it looks like this is a multi-day effort and probably only you really understands what needs to happen. Why does this all need to be in memory and accessible as fast as possible? It only takes a minute to look at your numbers here and know preloading all data is an instant fail if your memory target is 8GB

slate spoke
#

Indeed. That's the thing, it kinda doesn't. I have plenty of room for things to load in slowly, but the biggest thing I've been trying to focus on (when not being told to try something else) is just getting everything to not load in simultaneously

#

cuz I apparently don't know proper async/await or UniTask useage

#

and every attempt I've done at trying to make that work has made things worse lol

long ivy
#

What are you doing with this data in memory exactly? Your assumption that every grid tile requires maximum allocated memory is fishy to me and blows up your memory space budget. You used conservative lists and there was some performance problem you're trying to solve?

slate spoke
#

Originally the way I was doing it was by just searching the original dataset for all of the points that lie within a terrain tile whenever said tile is active, and then storing that list with said tile in the scene. Issue there is that when you have 49 terrain tiles loaded in, that means 49 queries

#

and because the actual file I'm working with is a .parquet, the only variable type I can convert it into initially is a DataFrame, which really doesn't seem to like anything asynchronous

#

so now it's set up to convert that dataframe to a custom datatype as soon as it's made

#

which has several arrays of the dataset's indices ordered by property for optimized searching

long ivy
#

does the actual file need to be loaded at runtime, or can it be pre-processed? and why not use spatial hashing? create a set of buckets for each tile, add all points from your dataset to a list for that bucket, do your queries in a target bucket (or set of buckets if you're searching by radius)

slate spoke
#

not that I should worry about that right now, honestly

#

I just need a POC that can be demo'd before the 24th

#

I don't think we've looked into spatial hashing yet though

#

(I also need to figure out what that is lol)

#

seems like that's for 3D, no?

long ivy
#

No, technically it works for any number of dimensions. Are each of these points associated with a tile, within that tile?

slate spoke
#

by default they're just arbitrary XY floats, so nah

#

part of my custom datatype's processing is assigning tile indices to each point, though

#

or well, it was

#

eventually swapped from that to vice versa, having the 2D array of tiles where the datapoint indices were assigned to whatever tiles they would be positioned on

long ivy
#

I assume you mean your 2d array of tiles have a list of data point indices associated with each tile, and you would use the index to find the right data point in a 670k-length list of them

slate spoke
#

yeh

long ivy
#

and why are you pre-allocating, assuming the worst case scenario?

slate spoke
#

well, for 3D arrays, because there wasn't another option other than having missing datapoints

long ivy
#

no, the 4k points per tile

slate spoke
#

that's what I mean, the tiles which would have 4k datapoints wouldn't be able to story every datapoint associated with it

long ivy
#

why not? resizable list for each

slate spoke
#

that's why we're swapping to a 2D array of lists lol

#

what I'm working on rn

long ivy
#

we're back to what are you doing with this data? there is a case to be made for performance if you know the lengths are fixed but it'll force you to stream data in from disk, and I'm confused about why you aren't taking the simple solution first

slate spoke
#

in short, this is an app where you can walk around in a giant desert with a bunch of a specific plant scattered across the terrain. Each of those plants is a datapoint, which you can go up to and select to view the information associated with it

long ivy
#

what is the relation of points associated with a tile, then? apparently they're not related spatially

slate spoke
#

the only thing that associates it with the tile is the fact that the tile is in the same position as the datapoint

#

or well, that the datapoint lies within the bounds of the terrain tile

long ivy
#

you said those points didn't necessarily lie within the bounds of their associated tile earlier

slate spoke
#

I just said they aren't assigned to specific tiles by default

#

they just get assigned to tiles after scaling

long ivy
#

your architecture is now incredibly weird to me. It sounds like you have 670k plant locations and the tiles don't really matter

slate spoke
#

another part of the reason why I have those positions associated with specific tiles is because all of the plants are being rendered with GPUI, so none of them are actual ingame objects. What that means for selecting a specific plant ingame is that you instead have to just search for whichever datapoint is closest to whatever point your selection raycast hits

#

I currently do that search by having each tile with it's own KDTree

long ivy
#

so you have 2k * 2k kdtrees? why not one? I assume it's not being rebuilt often, if at all

slate spoke
#

no, the KDTree search system was implemented before we started trying to store every single tile in memory all at once

#

the KDTrees are generated as the tile is loaded in

long ivy
#

And around we go. The tiles are loaded in one at a time now? If you already have that working, just don't load all the tiles all at once like it seems like you're doing

slate spoke
#

if it's not performance costly to query, a single kdtree could work

slate spoke
#

not loading them in all at once has been what I've been trying to do the whole time lol

echo coral
#

Time to pre process the data into a file per tile and load them as needed

#

Automate it in the editor so it's easy to do on other data in future.

slate spoke
echo coral
#

easy, write some code for use in editor (via menu option or scriptable object) to read the data and output it in a better format for use at runtime, such as being pre sorted per tile.

slate spoke
#

well, yeah, I figured that much

echo coral
#

you know your data base right now so you know what needs to be done to make it usable at runtime

slate spoke
#

Right. I'm moreso asking about what the process of doing that actual preprocessing looks like

untold moth
slate spoke
echo coral
#

But we know it uses too much memory to pre allocate all the lists as many are empty 🤔

slate spoke
#

for arrays, yes. The idea was to use Lists as a middle ground and only allocate a small amount for each tile initially

scenic forge
#

Just keep the tile empty until you need to put a point into it.

echo coral
#

new List<int>(50) still allocates an array of length 50

slate spoke
echo coral
#

the point of this is to avoid a few resizes + re allocations as the list grows

scenic forge
#

No? You allocate as you go through the points and put it in the grid.

echo coral
echo coral
slate spoke
#

I don't have any experience with making files like that

scenic forge
#

GC doesn't matter if it's something you allocate and holding onto.

echo coral
#

the list resizes will have some but i dont know enough to know

scenic forge
#

While I had some downtime yesterday, I wrote a demo using grid.

slate spoke
#

wh-

scenic forge
#

Set the point count to 1000000, map size to 2000, and building the grid takes less than a second on my computer, while querying the grid for nearby points takes less than 0.1 ms that the browser cannot even accurately measure it. And this is all in JS running in your browser, so C# should be magnitude faster.

slate spoke
scenic forge
#

It's not even, I have the randomizing biased towards 0,0

#

But the more uneven it is, the less memory it takes up.

#

The memory usage is only ~45 MB without accounting for the points themselves, if you count 24 bytes per point that's still well within 100 MB.

slate spoke
#

do each of these points have indices associated with them?

scenic forge
#

The grid just stores pointers to the points, it would take even less memory if you store points via their indexes instead.

slate spoke
#

wait so how does this work? I'm kinda having trouble parsing it

scenic forge
#

It's just a 2D array of lists, exactly what you are doing.

#

I was just curious and wondering what the memory and performance characteristics look like so I wrote a small demo with configurable point count and map size to play around.

slate spoke
scenic forge
slate spoke
#

it's almost demoralizing how well this does what I'm trying to do lmao

untold moth
slate spoke
#

right but even the loading takes less than a second

scenic forge
#

The code is not exactly written in high standard it's just a quick demo I whipped up, but L28 is the code of building the grid, L58 is the code of querying nearby points.

slate spoke
#

wait so where are the lists? all I see is Array and Set, the latter I haven't seen before

echo coral
slate spoke
#

ah

echo coral
#

A C# list wraps an array and handles reallocation of the array when it needs to get larger or smaller for you.

#

This is important to know, pre allocating a list with 50 as it's capacity means it already made an array of size 50

#

This is good if you know you have 50 things to add as we avoid a few resizes to get to 50 at the end

#

If you have 2 things to add... Bad

slate spoke
echo coral
#

A 2d array in c# using [,] is actually 1 array with maths to calculate the index, usually x + y * width

#

[][] is different, that is an array of arrays.

slate spoke
#

right, but isn't this supposed to be a 3D array?

#

or well, equivalent to a 2D array of lists?

#

I'm still kinda flabbergasted by this, like I've spent literal months trying to figure this out

#

this has been the #1 obstacle for this entire project, we'd be out of business in like 4 days from now if we didn't get something even a 10th as effective as this

#

I just feel incompetent now

scenic forge
slate spoke
#

I don't know JS so I might need some help figuring out what all's happening still

#

what's going on with the ??= [] on L32?

scenic forge
#

JS ??= is the same thing as C# ??=, [] just creates a new empty array.

bold frigate
#

Hey guys, How do I capture collision and trigger data of child game objects on a script attached to the parent?

#

2D physics

slate spoke
#

I'm just still totally confused by how this is running as fast as it is

#

there's not even anything async or multithreaded from what I can tell

#

I'm just trying to figure out what's making that much of a difference

slate spoke
scenic forge
#

Yeah, it's a fancier way to get or initialize, then add into it.

#

I think the demo code can pretty much be translated line by line to C#.

slate spoke
scenic forge
#

List is a reference type, the tile at that index in the array points to the same one as the variable.

slate spoke
#

Ah. For some reason, this line is giving me Object reference not set to an instance of an object

for (int i = 0; i < tileIndices[(int)tileIndex.x, (int)tileIndex.y].Count; i++)```
scenic forge
#

The idea is that only the tiles that have any point at all will be initialized, and the empty tiles are just null to save memory. You need to null check the tile before using it.

untold moth
novel plinth
#

Array.Copy is the general-purpose version of Buffer.BlockCopy, so the perf should be almost the same for most use cases AND much safer

#

inb4 some folks doubting the perf, Array.Copy/Buffer.BlockCopy is hella fast and it's what being used in the backing array of your beloved List<T>

echo coral
#

What I said was in context of their issue

echo coral
#

The problem originally was lots of garbage during creation and now it's too much memory usage.

hybrid belfry
#

Hi, is there any way I can specify multiple types here. For example, I have MonoBehaviour. I would like to add NetworkBehaviour as another option

public class Singleton<T> : MonoBehaviour where T : Singleton<T>
thin mesa
#

no, that "specifying" a type here is inheriting from MonoBehaviour and C# does not support multiple inheritance. just create another singleton class that inherits from NetworkBehaviour if you need that

sly grove
sage lichen
#

how do I do this webRTC stuff?

slate spoke
#

either way, trying to access any of the lists results in a zero length list

#
    private async UniTask PopulateTilesWithTestimonies(List<Testimony> testimonies)
    {
        foreach (Testimony testimony in testimonies)
        {
            // + 18 to make every value positive (lowest value is -17.75)
            int xTileIndex = (int)Math.Round(((float)testimony.umap_x + 18) / plantMapSampleScale, MidpointRounding.AwayFromZero);
            // + 17 to make every value positive (lowest value is -16.61)
            int yTileIndex = (int)Math.Round(((float)testimony.umap_y + 17) / plantMapSampleScale, MidpointRounding.AwayFromZero);

            List<int> tile = tileIndices[xTileIndex, yTileIndex] ??= new List<int>();
            tile.Add((int)testimony.index);

            //Debug.Log($"x = {xTileIndex}, y = {yTileIndex}, length = {tile.Count}");
        }
    }```
this is what I'm using to populate the lists
#
    public List<Testimony> GetTestimoniesInTile(Vector2 tileIndex)
    {
        //Debug.Log($"x = {tileIndex.x + testimonyTileCenterOffset.x}, y = {tileIndex.y + testimonyTileCenterOffset.y}");

        List<int> tile = tileIndices[(int)(tileIndex.x + testimonyTileCenterOffset.x), (int)(tileIndex.y + testimonyTileCenterOffset.y)];
        List<Testimony> testimonies = new List<Testimony>();


        if (tile != null)
        {
            for (int i = 0; i < tile.Count; i++)
            {
                testimonies.Add(this.testimonies.testimonyArray[tile[i]]);
            }
        }
        //Debug.Log($"testimony length: {testimonies.Count}");
        return testimonies;
    }```
and this is what I'm using to access those lists
cedar cradle
#

How do I actually use BFS algorythm, Ive looked it up an dI now know how do the algorythm and get an ordered list of all the connected noeds but how do I actually get the shortest path from a to b now ?

slate spoke
#

op wait, it's def being stored. I'm just either sampling from a bad point in the dataset, filtering too much, or setting the data rescale too high

slate spoke
#

yeah that's fixed. Next is just figuring out why I'm still getting a big frametime spike

echo coral
echo coral
stuck plinth
slate spoke
#

the length of those lists varies way too much for that

#

like a third of them don't even get populated

stuck plinth
#

i think rob also means passing an initial capacity into those lists so they don't need to allocate new memory when you call Add? if you have some idea of how many individual entries will be in most tiles, setting the initial capacity might help a little

stuck plinth
slate spoke
#

the spread is extremely uneven

#

and there's 670k of them

stuck plinth
#

that's why you want a separate pool, i'm not saying preallocate one for every single location

slate spoke
#

I'm not sure wym

#

the amount in any given tile can also range anywhere from 0 to like 4000

stuck plinth
#

is this a one time thing?

slate spoke
#

tile data is read from every time a terrain tile gameobject is loaded in

echo coral
#
if (tile != null)
{
    List<Testimony> testimonies = new List<Testimony>(tile.Count);
    for (int i = 0; i < tile.Count; i++)
    {
        testimonies.Add(this.testimonies.testimonyArray[tile[i]]);
    }
    return testimonies;
}
else return null;
#

an example of what i mean

#

We know already the amount we will add to the list so its best to set the start capcity of the list.

stuck plinth
#

in PopulateTilesWithTestimonies you don't know the size of each tile list ahead of time, but you could maybe try doing a separate pass to count the items at each location first without adding them to the list! if the amount of memory allocations is your main problem that would let you pass in the capacity there too

scenic forge
stuck plinth
scenic forge
#

They have a dataset of 670k points in a tile map of 2000x2000, if you store the counts in first pass in an int[,], that's already ~15 MB of garbage.
Without knowing the distribution of the data we cannot really calculate how much resizing will occur, but if we assume uniform distribution, 670k points across 2000x2000 tiles means each tile only has 0.16 points, no resizing at all.

echo coral
#

this is why I still think this data should be pre sorted and stored for each tile but hey ho 🙏

stuck plinth
scenic forge
#

I don't think the math of this optimization still checks out.

#

I could be remembering wrong, but list starts off with a capacity of 4, and doubles every time it runs out (8, 16, 32, etc).
For a tile that contains exactly 4097 points (worst case scenario), it would have to resize and cause 4 + 8 + 16 + ... + 4096 = 8188 x bytes taken for each item amount of garbage. Assuming 8 bytes per pointer, that would be ~64 KB of garbage, and you would need 240 of these tiles to generate 15 MB of garbage, for the optimization to make sense. However 240 of these tiles already contain 983k points.

stuck plinth
#

the counts could be in a dictionary or something if it's mostly empty squares, but i guess the point is that whatever it is you could reuse that between calls so it's not being allocated every time like the individual lists

scenic forge
#

I doubt that even with a dictionary the optimization would still check out. But either way, this is during the loading screen, as long as the amount of garbage allocated is within constraint then it doesn't really matter, and 15 MB of garbage is hardly something the target device cannot handle.

dapper cave
#

Entities people! does hybrid rendering handle view frustrum and umbra occlusion culling?
also how do you send an instance material property block?

#

in doing everything with jobs and at this point i might as well switch to URP and use ECS

sage lichen
#

right, here's the rub; i have a website, or at least a URL created by the UE5 Remote Control API, and I want to get a unity script to manipulate the events through the URL

#

did anyone try this thing out before?

sage lichen
#

danke

slender widget
sage lichen
#

htf does any of this make sense

wintry sequoia
#

guys is it possible to do something like this in unity? so basically that a circle has a radius of a certain color, and when that radius comes into contact with another radius of a different color they form a border between eachother, like how it is in the image

dusty wigeon
regal lava
#

Stencils sounds like the idea but if you want the edge outline you'd look into intersection shaders

wintry sequoia
regal lava
#

You can do both in the same shader yeah

#

If you want to use shader graph though you'll do the intersection in the graph and probably use pipeline render objects

solar beacon
#

hey guys! i wonder is it possible with the water surface to displace the water by a ship? i know there are decals and such but I wonder is it possible to actually change the geometry?

I seem to not be able to make physics that feel good without this because the ship does not influence the water around it

wintry sequoia
echo coral
dusty wigeon
edgy shard
#

Having some issues w raycast commands, its absolutely insistent that my results buffer is too small when using 2 jobs in the same fixed update


            boundsCheckHits = new(boundsCheckCommands.Length + 1, Allocator.TempJob);

            JobHandle jh2 = RaycastCommand.ScheduleBatch(boundsCheckCommands, boundsCheckHits, 1, boundsCheckCommands.Length + 1);
            jh2.Complete();
#

every time I run this code, it says
The supplied results buffer is too small, there should be at least maxHits space per each command in the batch.

#

OH wait hold on i've just realised, its maxHits PER command

#

okay, fixed that issue
only problem now is that it just won't hit anything

#

all of the results come back null

ebon crag
#

Because SerializedObjectView is a view on top of PackedBinaryStream this means I can't just store views for later deserialization?

lament salmon
edgy shard
#

i figured it all out, turns out I was being dim and I was just plain missing the raycasts. I've amended the casts themselves and everything works as expected :)

wet magnet
#
    "name": "Game.Server",
    "references": [
        "Game.Shared"
    ],
    "includePlatforms": [],
    "excludePlatforms": [],
    "allowUnsafeCode": false,
    "overrideReferences": false,
    "precompiledReferences": [],
    "autoReferenced": true
}

Ive got an asmdef for my server build but all my packages arent being automatically referenced? how would i fix this

sly grove
wet magnet
#

im just wondering how id automatically reference all packages im using

sly grove
#

Autoreferencing only works for code that isn't itself in a specific assembly definition.

wet magnet
#

i have 3 folders inside my script folder client shared and server which contain all the scripts for each build so server folder contains server asmdef

sly grove
#

for code that's in another assembly, you need to add your assembly as a dependency to that assembly

sly grove
wet magnet
sly grove
#

Not that I know of. I can't imagine automating it would ever lead to anything good TBH

#

you don't want all your assemblies to reference all your other assemblies

#

for one - you'd have circular dependencies that way

wet magnet
#

👍 alright thanks for the help 😄

wet magnet
coarse quarry
#

Code design question.

I have a player with inventory in my game. Different items can have different associated actions and info specific to them.
For this example:
I want to be able to place selected item only if it supports it.
How do i keep my code structure CLEAN?

I have this:

class Inventory{
    UsableItemSO[] items
}

abstract class UsableItemSO : ScriptableObject{
    List<ItemActionSO> itemActions

    PerformAction(owner, actionIndex){
        itemActions[actionIndex].Perform(owner)
    }
}

class PlaceableItem : UsableItemSO{
    size
    sceneObject
}

abstract class ItemActionSO : ScriptableObject{
    actionInputKey
    actionName

    Perform(owner)
}

class PlaceAction : ItemActionSO {
    Perform(owner){
        //needs some specific values from PlaceableItem
    }
}

When a player provides corresponding input I call currentItem.Perform(gameobject, actionIndex).
Question is: how do i get the info needed for PlacePreviewAction from PlaceableItem that it was called from?

unwanted solutions:
I can't just find player gameobject and get it's currentItem: it hold a reference to a UsableItemSO. I don't want to downcast.
I can't add UsableItemSO to Perform() arguments: same reason.
I can't have PlaceableItem as UsableItem field: some items are not placeable and i don't want to have unrelated fields.
I can't have needed fields defined in concrete itemAction class (for example i can't have size defined in PlaceAction): it is wrong due to SRP.

echo coral
#

why not have ItemActionSO be generic so you can have PlaceAction correctly get PlaceableItem without casts?

#

e.g. ItemActionSO<T> where T : UsableItemSO

#

otherwise perhaps an interface for actions is better so place action can be made with ItemActionSO in mind

tall ferry
#

Even if its generic, you eventually come down to the exact same thing: placeable item and place action rely on each other.
The only way I'd see here to not rely on each other would be some god class containing every variable, which you can pass to any ItemAction. The derived classes would read the values it wants (and still relies on the item setting values properly!). This would be bad for obvious reasons

echo coral
#

List<ItemActionSO> itemActions is the problem because if you want all actions in 1 list that is inherited then you cant really get around needing to cast later

coarse quarry
echo coral
#

its an up cast from ItemActionSO -> PlaceAction

#

your design has forced this requirement

#

bleh i mean to UsableItemSO

#
abstract class UsableItemSO : ScriptableObject{
    List<ItemActionSO<UsableItemSO>> itemActions

This may work if we then have class PlaceAction : ItemActionSO<UsableItemSO> { right?

tall ferry
echo coral
#

Ah, is the issue with trying to create functionality with serialized SOs...

tall ferry
#

id just downcast here unless you really want to redesign this. you can spend days trying to go into best practices to convince yourself your code is decoupled. At the end of the day, it really wont be

sly grove
coarse quarry
# tall ferry having everything as SO here doesnt seem like good practice either

These are the classes i have at the moment, i don't mind changing them. I was thinking to create PlaceAction class and have a reference to a PlaceableItemSO there, passing it at instantiation. I'd have to explore this. Anyway id like to hear if it can be solved with some, any design that doesn't involve workarounds.
or id be satisfied with a reason why this downcast is not considered a workaround. I just don't have enough expertise to reason this

echo coral
#

we gave you options

tall ferry
# coarse quarry These are the classes i have at the moment, i don't mind changing them. I was th...

I don't like to downcast here either. I usually think it feels wrong because deriving classes exist to handle differences like this. In your current setup, thats really just the easiest way to go about it.

PlaceAction class and have a reference to a PlaceableItemSO there, passing it at instantiation
Assuming we arent talking about using SOs here anymore. "passing it" was the problem from the start. How do you plan to do this?
If PlaceableItem passes itself to PlaceAction: It currently doesn't store anything of type PlaceAction. You'd need to cast again.

coarse quarry
#

Replied to wrong message, sorry

echo coral
coarse quarry
tall ferry
#

Trying to think also how id use generics here but I don't really see how this would avoid the initial problem either honestly

echo coral
#

I presume you want all items to be "usable" via a shared function/interface

coarse quarry
#

Any item can have multiple actions, can be any number of them. I would have to pass a string as a parameter and have a switch statement or something which is ugly already

#

I switched to action as a class to prevent this in the first place

echo coral
#

you cant magically share these actions between many item types AND get the item as the type without casting 😐

tall ferry
echo coral
#

generics make it work as its essentially code gen so a version is made for each generic type used

tall ferry
#

If you don't want to cast at all, then PlaceableItem has to be the one doing the logic with size and sceneObject

echo coral
#

the solution is to cast and just deal with it 😆
(UsableItemSO)item

#

then up to you to ensure the action is not given to the wrong item types

coarse quarry
echo coral
coarse quarry
#

Say when i hold a placeable item f to Place(), R to Rotate().
When i hold throwableitem f to ThrowOverhand(), Z to ThrowUnderhand()
🤣

tall ferry
#

specifically System.Action, not to confuse with your ActionSO thing

plain abyss
#

Having an issue with GLTFast and UniTask. Currently doing this to load a bunch of GLB files asynchronously:

foreach (FileInfo fileInfo in filePaths)
{
    GltfImport gltfImporter = new GltfImport(null, deferAgent);
    var task = gltfImporter.Load($"file://{fileInfo.FullName}", settings).AsUniTask().ContinueWith(
        async t => {
            if (t)
            {
                //Do various onSuccessful things here
            }
            else
            {
                Debug.LogError($"Unable to load asset file://{fileInfo.FullName}");
            }
        }
        );
    tasks.Add(task);
}
await UniTask.WhenAll(tasks);

But I'm getting a null reference exception inside of .Load due to some malformed data in a GLB file. This means the entire task ceases to be, and it never gets to the ContinueWith condition, it just dies. I want to display information to the user about a broken file, but I don't know how I could. How would I gracefully handle essentially Try-Catching a task?

scenic forge
#

In general you don't want to mix async/await with .ContinueWith.

plain abyss
#

I'll admit I don't know a lot about how to properly deal with Tasks and whatnot, but that was the suggested code from the GLTFast documentation, with an extra AsUniTask in there so I can us that instead of a normal system task

scenic forge
#

Inside a UniTask like LoadAsset, you can await regular tasks just fine so you don't need to .AsUniTask() to convert it. .AsUniTask() is most of the time used when you already have a task, you don't need to change that task in any way (eg continuation and error handling), and you want to pass that task to somewhere that only accepts a UniTask.

#

If you do need to do more logic like continuation and error handling, it's much easier to just write async/await rather than .ContinueWith.

#

In your case what's failing isn't the task but the synchronous call of .Load, then you would need to do something like:

foreach (FileInfo fileInfo in filePaths)
{
    try
    {
        var gltfImporter = ...;
        var task = gltfImporter.Load(...).AsUniTask().ContinueWith(
            // ...
        );
        tasks.Add(task);
    }
    catch
    {
        // ...
    }
}
wintry sequoia
#

ok so i currently am in stencil buffer hell and i wanna do some things but am failing, how could i make it so that i instantiate the triangle at the very end of the black circle, and not the middle of it, like in the second image?

#

also, do intersection shaders properly work with stencil buffers?

echo coral
# plain abyss Having an issue with GLTFast and UniTask. Currently doing this to load a bunch o...

Tasks when awaited re throw exceptions so they can be caught. If you adjust your code you can catch the load exception and still await all of the loads:

async UniTask LoadGLB(string name)
{
    GltfImport gltfImporter = new GltfImport(null, deferAgent);
    try
    {
        var glb = await gltfImporter.Load($"file://{name}", settings).AsUniTask();
        //Do thing with successful load
    }
    catch (Exception e)
    {
        Debug.LogException(e);
    }
}

foreach (FileInfo fileInfo in filePaths)
{
    var task = LoadGLB(fileInfo.Fullname);
    tasks.Add(task);
}
await UniTask.WhenAll(tasks);
#

making a local async function can be useful in situations like this!

scenic forge
#

Also consider how you want to handle exceptions in relation to the other tasks. If one task fails, should the entire process be aborted, or should the other tasks still continue? If you want the entire process to be aborted, you also need to cancel the already started tasks.

echo coral
#

I caught the individual load fails as it sounded like they want to try to load them all but not break the entire process

plain abyss
#

Tried to wrap the .Load section in a try-catch, and it didn't trip. The error came up on await UniTask.WhenAll(tasks) line

#

So it's not the call to Load that's causing it

scenic forge
echo coral
#

Its almost the same but i omitted the continuewith

#

anyway we both explained the same concept 👍

scenic forge
#

(I gave two snippets in case you missed it, the first one is the exact same code as yours)

plain abyss
echo coral
#

sorry to repeat the same stuff but hopefully its enough to get thing working

scenic forge
#

Yeah the second snippet is more so showing how the same logic can be written both ways (assuming the exception is in .Load which turned out to not be true), the first one is really the one you should be doing.

plain abyss
#

Okay, this one works and gives me an error message and lets me skip the failing file and let the user know which one broke

#

Thanks! One of these days I will actually understand what tasks do under the hood so I can figure out what to do when they go wrong

austere jewel
#

All you gotta know about this bit is that an exception thrown inside an async method is collected by the task and thrown again when it's awaited

scenic forge
#

A quick and dirty way to think is that async/await is a syntax sugar on top of .ContinueWith, so unless you have very good reasons not to, you should just use async/await everywhere and pretend .ContinueWith doesn't exist.

austere jewel
#

So you either catch it so it never hits the task, or you catch it up where you await any task above

echo coral
#

magic state machine code gen and stuff all handled by the compiler 🙏

novel plinth
hybrid belfry
#

Hi. how can I get the angle of the bullet in relation to its forward direction in comparison to Up and Down vectors? Preferably a value between 0 and 1

soft marlin
hybrid belfry
hybrid belfry
#

I got the value I wanted with ```cs
Vector3.Cross(Vector3.forward, this.transform.forward).x

runic tendon
#

How performance intensive is raymarching in 3D? I have like a single cube renderer as bounds area for like 6-8 spheres that need sdf blending. It'll always be running.

wet magnet
#

anyone know networkmanager callback for on network manager spawn object?

somber swift
crude root
#

Hello! I'm looking to offload some performance intensive tasks from my main calling stack, to reduce the load on my main thread. im looking into async programming and coroutines. i found this https://github.com/Cysharp/UniTask?tab=readme-ov-file#asyncenumerable-and-async-linq that says its a better form of tasks that can go into unity functions. My problem is, if i run everything async but still on the main thread, doesnt that still cause performance issues? the whole goal of async is to let multiple threads be able to handle the data no?

cursive horizon
scenic forge
#

But yes depending on the type of task you are doing and the requirements, might be better to use job system + Burst if the goal is to speed things up (it would require some rewriting though).

#

If the goal isn't necessarily speeding things up but simply to not block main thread, then running the code on a background thread is the easiest and might not even need any code changes.

crude root
untold moth
# crude root Hello! I'm looking to offload some performance intensive tasks from my main call...

Async means that you don't execute the whole logic immediately, thus avoiding blocking the thread for that duration. It allows you to break up the logic into smaller pieces that don't take much time and executes these pieces one by one making breaks to let other logic/code run. Thus it takes more time to complete the async logic, but it doesn't bother(at least not as much as sync) other logic that could be more time sensitive.
This, even if it's not running on a separate thread, it doesn't mean that it's meaningless.

compact ingot
crude root
# compact ingot what causes your long frame times anyway?

Heightmap terrain editing, i delayed my lod, but still if i use like 1k-2k detail heightmap area for some precise editing, it can cause some problems in main thread. im only setting the heightmap for the area that actually get editted but still.

compact ingot
crude root
# compact ingot you can't speed that up by threading

Ahh, when you try to set the heightmaps of the terrain, its done / has to be done immediately / synchronously? i thought the lag may be caused by the large for loop that was running to setup the array, so was just going to make async to future proof.

compact ingot
crude root
untold moth
#

You need to profile

#

Making random solutions not based on actual profiling data might make it worse

compact ingot
#

personally i look at unity terrain as a read-optimized data-structure that is capable of quickly creating LOD meshes from huge datasets. Based on that i would not expect that writing to that structure is fast or can be made fast, as its a common trade off in optimization go for either read or write speed (not both)

crude root
#

I will profile, but if the terrain system is highly inefficient for what im trying to use it for, then its worth it to change no matter what the profiler says.

untold moth
#

Whether the terrain is efficient or not is highly questionably and depends on your specific use case.

#

All of this would be clear if you profile

crude root
#

yes, i know it would be. my question was more so about how async works, not really about profiling.

untold moth
#

Well, then you got your answers.
But perhaps it's worth stepping back a bit and looking at the whole picture.

crude root
#

I'm sorry for creating the Xy problem, thats on me. Let me reformat the question then. I want to be able to till ground by changing the height of the terrain underneath me. I'm currently trying to figure out how to make it in a way that both offers accurate changes, and doesnt impact the users fps at all while editting. The Async question was related, but i was more so confused about the goal of async, eg. why use async if you dont use a seperate thread, which was answered.

compact ingot
# crude root I'm sorry for creating the Xy problem, thats on me. Let me reformat the question...

A smallish update on a few pixels only to the heightmap should not be an issue (personal experience in a tiny project with a normal size terrain of 1km size, 2k resolution and a first person camera, changing no more than 9 pixels at a time ), but that might not be true if the terrain is relatively small (10m) and has high resolution (2k) which would mean large parts of the terrain have to be regenerated for spatially small changes. its also likely that you have many chunks in LOD0 state depending on pixel error settings. You could try changing the pixel error and see if you get different results that still look acceptable.

shut wing
#

i've been working on open world car game, and taking huge inspiration on one city. i extracted that city heightmap and applied it to terrain. currently im trying to also import roads but to no avail. i have GeoJSON file with all roads in that city but im stuck on how to do that, any help would be good thanks.

lament salmon
#

If it's just the center lines, might wanna plug the data into some spline mesh generator

shut wing
#

thanks

echo coral
shut wing
#

thanks

hazy bear
#

Anyone here knows thing or two about roslyn analyzer and source generation? I literally had my first contact with it yesterday so I barely even know how it works.
I want to create analyzer that simply finds all unique generic usages of a specific class and then emit a static class with read only collection of qualified names off all unique generic arguments used for that class into a specific assembly (you could say I try to c++'ify my project). To make life easier I decided to limit searching to only FieldDeclarationSyntaxes for now, and I managed to write something that I think kinda works, but it creates this static class in every assembly and in that read only array it includes only types found in that exact assembly, so Im kinda stuck as I have no clue how to make it so it finds all generic usages in all assemblies first, and only when it finishes source generation for my specific assembly kicks in with all the information gathered.

sage radish
hazy bear
#

with that parallel nature I had in mind an idea that each assembly gets somehow flagged with information about what generic usages it contains, but then I would need to use reflections to union them all into a single collection in my editor code, which isnt ideal, thus I was searching for alternative

#

but maybe someone has a better idea with their experience

#

to put it simply I have generic ScriptableObject type and I want to automate defining concrete types when such are in use, so if user defines a field somewhere public GenericSO<int> system ensures that there is a generated file that defines it in non-generic way to work with unitys serialization (Simply an empty class in its ow file like internal class GenericSOInt : GenericSO<int>{}).

echo coral
#

I woulder if unity specifically makes this not be required for lists (and now unity events)
Is it not usable for other generic classes too? I forget.

#

I mention this as I remember unity events used to need this workaround but then it was changed

hazy bear
#

it works to some extend, but in case of ScritpableObjects you cant have a generic one, thats for sure

echo coral
#

Ah right I failed to notice this, mb

hazy bear
#

even when you work around it and define manualy concrete definition as I mentioned, asset filtering works wierd in this case which bugs me XD When you have serialzied field of type lets say [SerializeField] private GenericSO<int> IntField and want to assign it in inspector, it cant diffirentiate closed types from each other so it will list you all variants, like ones derived from GenericSO<float> and so on

sage radish
hazy bear
#

no, the idea is to pretend like they dont exist, so I plan to create a separate assembly for generated closed types and keep these classes internal so user is allowed to use only generic definition

sage radish
#

Then that opens up the possibility of using an IL post processor instead of a source generator. Instead of generating source code that gets included in the compilation, it runs after compilation and modifies or generates IL directly in the compiled assemblies.

#

And that workflow allows for scanning other assemblies as part of it.

#

The only problem is that it's an entirely undocumented part of Unity and only really intended for internal use. But it's used by many packages like Burst, Entities, and even some third party assets like Mirror networking.

#

Because it happens after compilation, none of its changes are visible to IDEs, hence my question before.

hazy bear
#

wait wait wait... I got kinda lost. Are you atalking about emiting these class definitions into IL or somehow just an information about generic usages? Because im interested in a latter one, as at the end of a day its not only about having a class definition, but to have it specificaly in a physical file so Unity can create meta file for it and for this thype to be associated with a guid for serialzation purpouses

sage radish
hazy bear
#

yeah thats why I try to use Roslyn mainly for finding generic usages, and then normaly in editor script create files and write to them

sage radish
#

Are you using Roslyn mainly over performance concerns then, over using Reflection to find the types?

hazy bear
#

oh yeah definitely, I once did this kind of analysis with reflections and it was terrible XD

#

but I was young and stupid so I didnt even know about existance of such things like Rosylyn

#

(which was maybe half year ago)

sage radish
#

How about letting the source generator generate an internal class containing all the generic definitions used in that given assembly, and then using Reflection in an editor script to find all those types in all the assemblies and generate the concrete classes in another assembly?

hazy bear
#

so I guess the only solution for me is to create some kind of manifest-like classes in every assembly that contains generic usages and then using reflections to union them in my editor script.

hazy bear
#

I have one other idea as well to try make it more optimized, as this reflections approach will still create some overhead

sage radish
#

You could also use a IL post processor to find these instances, but Roslyn analyzers are well optimized for this task already.

hazy bear
#

If these internal classes could have something in common, like base type or class attribute, I could laverage the power of TypeCache in Unity which is absurdly fast for such things, but then the problem is that I would have to make sure that all these assemblies sees that base class or attribute

#

...which is a problem

#

it would need to be something that already exists and is provided by the engine, or is part of CoreLibrary but not used so often to avoid collecting other than these generated classes as much as possible

sage radish
#

Since you only need to find one type in each assembly, and you can know its exact name, you can use Assembly.GetType. I don't know what it's performance is like, but it feels like it should be relatively fast, since it's an exact search.

hazy bear
#

yeah that will be fast but iterating over assemblies wont :/

#

hmmm you know what? You are right! Im overcomplicating things XD

#

that is actuyally the approach, I believe somewhere in CompilationPipeline unity gives easier access to cached assemblies with specific filters to avoid going through everything that is in domain and only iterate over user defined ones ond/or plugins

dusty wigeon
# hazy bear Anyone here knows thing or two about roslyn analyzer and source generation? I li...

You can use the compilation reference to get all referenced assembly. https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.compilation.references?view=roslyn-dotnet-4.13.0

You can also use the compilation AssemblyName to only generated in the assembly you wants. https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.compilation.assemblyname?view=roslyn-dotnet-4.13.0

I suggest that you do not put your analyzer inside an Assembly Definition. From what I tested, I could not reference correctly the generated code same if it was supposed to be generated...

slim sentinel
#

damn im struggling so much with the new urp
i dont get why the shader Lord.mat_effects doesnt really have a depth texture

void OnEnable() => RenderPipelineManager.endCameraRendering += ApplyEffects;
void OnDisable() => RenderPipelineManager.endCameraRendering -= ApplyEffects;

CommandBuffer cmd;
void ApplyEffects(ScriptableRenderContext context, Camera camera){
    if (!camera.name.Contains("Soul(Clone)")) return;
    if (camera.targetTexture == null) return;
    if (Lord.mat_effects == null) return;

    if(cmd == null){
        cmd = new CommandBuffer { name = "ScenePostProcessing" };
    }

    cmd.SetGlobalTexture("_CameraDepthTexture", BuiltinRenderTextureType.Depth);
    cmd.Blit(camera.targetTexture, Lord.soul.result, Lord.mat_effects, 0);
    context.ExecuteCommandBuffer(cmd);
    cmd.Clear();

    raw_image.texture = Lord.soul.result;
}
thorn flintBOT
languid isle
#

What is the appropriate chat for asking questions about accessibility options with unity??

nova bolt
#

So how can i get Unitys Terrain Tools Brush Size

#

As i kinda need it for my Auto Terrain Painter

nova bolt
#

nvm i got it

languid isle
#

I'm starting to suspect that Unity has no accessibility function any more. The plugin for TTS and STT doesn't seem to have been updated in the last year, and appears to have only marginal functionality.

zealous summit
#

does anyone use Newtonsoft.Json here? I wrote custom serialization for SO's and getting an error Item must be instantiated using the ScriptableObject.CreateInstance method instead of new Item.. Here's the code:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    string path = null;

    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.EndObject)
            break;

        if ((string)reader.Value == "resourcePath")
        {
            reader.Read();
            path = (string)reader.Value;
        }
    }

    return Resources.Load(path, objectType);
}
#

I tried like ten different approaches including making a subclass of DefaultContractResolver and it still tried to use new()

echo coral
#

why do they need to be scriptable objects if they come from json?

#

is this editor or runtime?

untold moth
zealous summit
zealous summit
#

it's not anywhere in my code

untold moth
zealous summit
#

yeah, I see it, but when I try to open it the script with related issue is empty

untold moth
#

Even if it's not in your code, by seeing where and why it invokes it you can troubleshoot it.

zealous summit
#

also I dont need to serialialize a whole SO, just some sort of reference for now, maybe a GUID in the future

echo coral
#

should be that now

untold moth
zealous summit
#

yeah, it could also work

#

it's not a problem to serialize it:

"allInventoryItems": {
  "resourcePath": "Items/FashionMagazine"
},
#

the problem is with loading it

#

I think no matter if it's an ID, reference path or GUID it will lead to the same issue

untold moth
#

When deserializing the id, assign the correct SO reference to wherever you need it.

#

Not sure what issue you're talking about

zealous summit
#

because even if I return an already existing SO (for testing purposes of course) it still doesn't "fully" use the ReadJson properly and gives the error:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    return UnityEngine.Object.FindObjectOfType<SOLibrary>().Item;
}

throws:
Item must be instantiated using the ScriptableObject.CreateInstance method instead of new Item. UnityEngine.ScriptableObject:.ctor () Item:.ctor () (wrapper dynamic-method) object:lambda_method (System.Runtime.CompilerServices.Closure) Newtonsoft.Json.Serialization.JsonSerializerInternalReader:CreateNewObject (Newtonsoft.Json.JsonReader,Newtonsoft.Json.Serialization.JsonObjectContract,Newtonsoft.Json.Serialization.JsonProperty,Newtonsoft.Json.Serialization.JsonProperty,string,bool&) (at /root/repo/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:2247) Newtonsoft.Json.Serialization.JsonSerializerInternalReader:CreateObject (Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.Serialization.JsonContract,Newtonsoft.Json.Serialization.JsonProperty,Newtonsoft.Json.Serialization.JsonContainerContract,Newtonsoft.Json.Serialization.JsonProperty,object) (at /root/repo/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:479)

#

this throws the same error (even simpler version):

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    return ScriptableObject.CreateInstance(nameof(Item)) as Item;
}
#

unfortunately that's the script the error leads to:

untold moth
zealous summit
#

here's more:
Newtonsoft.Json.Linq.JToken:ToObject (System.Type,Newtonsoft.Json.JsonSerializer) (at /root/repo/Src/Newtonsoft.Json/Linq/JToken.cs:2084) Newtonsoft.Json.Linq.JToken:ToObject (System.Type) (at /root/repo/Src/Newtonsoft.Json/Linq/JToken.cs:2058) Newtonsoft.Json.Linq.JToken:ToObject<System.Collections.Generic.List1<Item>> () (at /root/repo/Src/Newtonsoft.Json/Linq/JToken.cs:1935)
SaveSystem.SaveData:Get<System.Collections.Generic.List1<Item>> (string,System.Collections.Generic.List1<Item>) (at Assets/Scripts/SaveSystem/SaveData.cs:21)
SaveSystem.SaveSlotFileHandler:Load<System.Collections.Generic.List1<Item>> (SaveSystem.SaveSlot,string,System.Collections.Generic.List1<Item>) (at Assets/Scripts/SaveSystem/SaveSlotFileHandler.cs:137)
SaveSystem.SaveSlotFileHandler:Load<System.Collections.Generic.List1<Item>> (SaveSystem.SaveSlot,SaveSystem.Savable1<System.Collections.Generic.List1<Item>>) (at Assets/Scripts/SaveSystem/SaveSlotFileHandler.cs:143) SaveSystem.SaveSlotExtensions:LoadFromFile<System.Collections.Generic.List1<Item>> (SaveSystem.SaveSlot,SaveSystem.Savable1<System.Collections.Generic.List1<Item>>) (at Assets/Scripts/SaveSystem/SaveSlotExtensions.cs:9)
SaveSystem.SaveSlotDataHandler:BootstrapLoadedForDataLoad (SaveSystem.SaveSlot) (at Assets/Scripts/SaveSystem/SaveSlotDataHandler.cs:99)
SaveSystem.SaveSlotDataHandler/<>c__DisplayClass12_0:<SceneLoadedForDataLoad>g__callback|0 (UnityEngine.SceneManagement.Scene,UnityEngine.SceneManagement.LoadSceneMode) (at Assets/Scripts/SaveSystem/SaveSlotDataHandler.cs:85)
UnityEngine.SceneManagement.SceneManager:Internal_SceneLoaded (UnityEngine.SceneManagement.Scene,UnityEngine.SceneManagement.LoadSceneMode)`

#

I can try to send it all as a file the discord won't let me otherwise

zealous summit
#

but I will look into it

untold moth
#

It seems like you're serializing Item that has an SO field.

#

You should make sure that the field is not being serialized/deserialized

untold moth
thorn flintBOT
zealous summit
zealous summit
#

will know for the future

untold moth
zealous summit
#

just for a single Item

zealous summit
#

From my understanding I want to serialize the Item, but with a custom serializer that will only save ID/reference path etc

untold moth
zealous summit
#

it's this field:

private static readonly Savable<Item> _allInventoryItemsSavable = new(key: "allInventoryItems");
untold moth
#

Is Item inheriting from an SO?

zealous summit
#

that goes to this:

public class Savable<T>
{
    public string Key { get; set; }
    public T Value { get; set; }
    public T DefaultValue { get; set; }

    public Savable(string key, T defaultValue = default)
    {
        Key = key;
        DefaultValue = defaultValue;
    }

    public Savable<T> WithValue(T value)
    {
        Value = value;
        return this;
    }

    public Savable<T> WithDefaultValue(T defaultValue)
    {
        DefaultValue = defaultValue;
        return this;
    }
}
#

yes

untold moth
#

Well, then your custom serializer doesn't work

zealous summit
#

yeah, it doesn't fully

#

it serializes properly

#

but Newtonsoft somewhere still tries to use new() on the result even tho it has specific instructions not to do so

untold moth
#

I think it just uses the default serializer.

zealous summit
#

it it did it wouldn't serialize as inteded I think. Just deserialization doesnt work

#

because this works:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    var so = value as ScriptableObject;
    writer.WriteStartObject();
    writer.WritePropertyName("resourcePath");
    writer.WriteValue(GetResourcePath(so));
    writer.WriteEndObject();
}
untold moth
#

Well, you'll need to share all the code relevant to the custom serializer

zealous summit
#

properly serialized SO here:

"allInventoryItems": {
  "resourcePath": "Items/FashionMagazine"
},
zealous summit
# untold moth Well, you'll need to share all the code relevant to the custom serializer
using System;
using Newtonsoft.Json;
using UnityEngine;
using SaveSystem;
using UnityEditor;

public class ScriptableObjectConverter : JsonConverter, IAutoJsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(ScriptableObject).IsAssignableFrom(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var so = value as ScriptableObject;
        writer.WriteStartObject();
        writer.WritePropertyName("resourcePath");
        writer.WriteValue(GetResourcePath(so));
        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return ScriptableObject.CreateInstance(nameof(Item));
    }

    private string GetResourcePath(ScriptableObject so)
    {
        if (so == null)
            return null;

        string assetPath = AssetDatabase.GetAssetPath(so);

        int resourcesIndex = assetPath.IndexOf("/Resources/", StringComparison.OrdinalIgnoreCase);
        if (resourcesIndex >= 0)
        {
            string relativePath = assetPath[(resourcesIndex + "/Resources/".Length)..];
            if (relativePath.EndsWith(".asset"))
                relativePath = relativePath[..^".asset".Length];

            return relativePath;
        }

        return null;
    }
}
#
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;

namespace SaveSystem
{
    public static class ConvertersLibrary
    {

        private static List<JsonConverter> _allConverters;

        public static List<JsonConverter> AllConverters
        {
            get
            {
                _allConverters ??= GetAllConverters();

                return _allConverters;
            }
        }

        private static List<JsonConverter> GetAllConverters()
        {
            return AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(assembly => assembly.GetTypes())
                .Where(t => typeof(JsonConverter).IsAssignableFrom(t) &&
                            !t.IsAbstract &&
                            typeof(IAutoJsonConverter).IsAssignableFrom(t))
                .Select(t => (JsonConverter)Activator.CreateInstance(t))
                .ToList();
        }
    }
}
#

and used in other script:

private static readonly JsonSerializerSettings JsonSettings = new()
{
    Formatting = Formatting.Indented,
    Converters = ConvertersLibrary.AllConverters,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
untold moth
#

Where do you call the deserialization?

zealous summit
#

in SaveDataHandler.cs:

public static T Load<T>(SaveSlot saveSlot, string key, T defaultValue = default)
{
    return saveSlot.Get(key, defaultValue) ?? defaultValue;
}
#

SaveData.cs:

using System;
using System.Collections.Generic;

namespace SaveSystem
{
    public abstract class SaveData
    {
        public Dictionary<string, object> Data { get; private set; } = new();

        public virtual void Set<T>(string key, T value)
        {
            Data[key] = value;
        }

        public virtual T Get<T>(string key, T defaultValue = default)
        {
            if (!Data.TryGetValue(key, out object rawValue)) return defaultValue;

            try
            {
                return rawValue is Newtonsoft.Json.Linq.JToken token
                    ? token.ToObject<T>()
                    : (T)Convert.ChangeType(rawValue, typeof(T));
            }
            catch
            {
                return defaultValue;
            }
        }
    }
}
untold moth
zealous summit
#

which part do you mean? I have a lot of custom code here

untold moth
#

The deserialization part

#

What's Conver.ChangeType?

#

Or is that not the deserialization?

#

I can't see where you actually deserialized the json.

zealous summit
#

the token.ToObject<T> handles deserialization here

zealous summit
#

but .ToObject<T> might now that I think about it

untold moth
zealous summit
#

also here's deserializing the SaveSlot itself:

public static SaveSlot GetSaveSlotFromFile(int index)
{
    string path = GetSaveSlotPath(index);
    if (!File.Exists(path)) return null;

    try
    {
        string json = File.ReadAllText(path);
        return (JsonConvert.DeserializeObject<SaveSlot>(json, JsonSettings) ?? new SaveSlot()).WithIndex(index);
    }
    catch (Exception ex)
    {
        Debug.LogError($"Failed to load save slot {index}: {ex.Message}");
        return new SaveSlot();
    }
}
zealous summit
#

damn it works!

#

thanks a ton for your help with troubleshooting

#

it never used the settings for deserialization before like you said

#

just provided them like this:

public virtual T Get<T>(string key, JsonSerializer jsonSerializer, T defaultValue = default)
{
    if (!Data.TryGetValue(key, out object rawValue)) return defaultValue;

    try
    {
        return rawValue is Newtonsoft.Json.Linq.JToken token
            ? token.ToObject<T>(jsonSerializer)
            : (T)Convert.ChangeType(rawValue, typeof(T));
    }
    catch
    {
        return defaultValue;
    }
}
#

so .ToObject<T> just needed a jsonSerializer

marble otter
#

Guys, does the backend service with C# modules support data persistence in memory? If so, how long does it stay active and what would make it clear this cache? Is there any documentation?

#

founded!

languid isle
#

Does anyone here know anything about Unity capability with TTS or STT?

untold moth
glass cradle
#

Is there an easy way to modify a single script in a package without having to copy the entire package

sly grove
glass cradle
valid crane
#

[Netcode] Cannot start Host while an instance is already running
UnityEngine.Debug:LogWarning (object)

TitleScreenManager:StartNetworkAsHost () (at Assets/All/Skrypty/Title Screen/TitleScreenManager.cs:54)

bruh i dont know what to do

the line at titlescreen:54 is

public void StartNetworkAsHost() //blad
{
NetworkManager.Singleton.StartHost();
}

and there there isn't any error

also

i didn't noticed this error at first and now im struggling to fix it
please help😖🙏🏻

#

any1?

gritty ore
#

Are you calling NetworkManager.Singleton.StartHost() or StartNetworkAsHost() from more than one place? Seems like the singleton checker is just warning you the latest call is an extra.

compact ingot
#

If you don’t have the installer for those you are likely in breach of some non-disclosure or non-distribution agreement. Generally you only get those if you also have access to a Xbox dev kit.

wraith raptor
#

working on a vr game rn, and im trying to recreate the movement in orion drift so i have something to build off of. how would i implement the carving? carving is a way of making sharp turns while keeping momentum, by kinda rotating around your hand. this is my script atm, no carving yet

flint sage
#

Perhaps you should attempt it first

thorn flintBOT
wraith raptor
#

wow thanks for your helpful advice

fading fulcrum
#

Hi I'm having some problem with my entity bot object not showing up visually.

public class NavAgentAuthoring : MonoBehaviour
{
    [SerializeField] private Transform targetTransform;
    [SerializeField] private float moveSpeed;
    [Header("Rendering")]
    [SerializeField] private Mesh mesh;
    [SerializeField] private Material material;

    private class AuthoringBaker : Baker<NavAgentAuthoring>
    {
        public override void Bake(NavAgentAuthoring authoring)
        {
            Entity authoringEntity = GetEntity(TransformUsageFlags.Dynamic | TransformUsageFlags.Renderable);

            AddComponent(authoringEntity, new NavAgentComponent
            {
                targetEntity = GetEntity(authoring.targetTransform, TransformUsageFlags.Dynamic | TransformUsageFlags.Renderable),
                moveSpeed = authoring.moveSpeed
            });
            AddBuffer<WaypointBuffer>(authoringEntity);
        }
    }
}

Here's my baking code, placed on the bot gameobject itself which is a child in a subscene gameobject in the scene.

Am I doing anything wrong?

fading fulcrum
sand grail
#

I want an opinion, for a PF algorithm you guys think that it is better to run ASYNC with everything in the code or have it's own loop for each path that should be created?

untold moth
sly grove
#

pathfinding presumably. But I think the question is too vague. Different games have different requirements for pathfinding.

#

Some games can precompute all the pathfinding up front. Some need to do it dynamically.

hybrid tundra
#

have anybody seen this error during building?

#

it just stuck in here each time I try to make a build

#

already tried to delete Libraries folder

#

ventilation is up like if it would be doing something...

untold moth
hybrid tundra
#

"Version Control: Cannot check out files in offline mode"

#

this is in the errorlog

#

can this be really a reason for making the build to stuck?

untold moth
hybrid tundra
untold moth
#

Where did you save the build?

hybrid tundra
untold moth
#

Theoretically, there's nothing that should be checked out during the build.

#

Does it not point to any files?

#

Are there any other messages around that one?

hybrid tundra
#

there were other errors I already fixed

untold moth
#

Are you using unity vcs?

hybrid tundra
untold moth
hybrid tundra
untold moth
#

Make sure none of the temp/build related files are added to the depot

untold moth
#

Unrelated to version control

hybrid tundra
#

so I'm making the build into outside of the workspace

untold moth
#

You should only version assets, source code, meta files and a few config files. Everything else needs to be excluded.

untold moth
#

Like temp files or library.

#

Make sure these are ignored.

hybrid tundra
#

well, I guess some stuff is setted up into something like gitignore

#

which was already in the project

#

by others

untold moth
#

Then it's not configured correctly.

#

At least in your environment.

hybrid tundra
#

well, isn't it working like Git? in there you have a .gitignore you can add to the repo

#

and its pulled for everyone

#

and thats all

untold moth
#

Gitignore is not used by p4

hybrid tundra
#

I guess p4 has something similar as well

hybrid tundra
untold moth
hybrid tundra
#

then its probably already setted

untold moth
#

Others could possibly have local ignore file that is not in the depot

hybrid tundra
untold moth
#

Or they have the workspace configured to not set files to read only

#

Anyways, something is wrong with your environment and you should figure it out.

hybrid tundra
#

not even connecting to the version control

ebon abyss
#

That might be the issue

untold moth
untold moth
hybrid tundra
#

and I didn't want to connect to the VC now

ebon abyss
#

You could temporarily remove the P4 plugin

#

Just to open it

hybrid tundra
#

for Git, this was never an issue

ebon abyss
#

It shouldn't try to check out files though

untold moth
#

Then configure the workspace such that it doesn't need to checkout stuff

hybrid tundra
#

you could be offline whenever you wanted and you could use the project as it is

#

with Git

ebon abyss
#

Yes, git is distributed. P4 is centralized

untold moth
#

I mean, what's the point complaining to us?

ebon abyss
#

Perforce requires checking out files before modifying

hybrid tundra
#

I just wanted to figure out if I could make a build without connecting to P4 or not

#

that's all

untold moth
#

Then configure it that way

hybrid tundra
#

at least not the ones inside Assets folder

ebon abyss
#

It shouldn't

#

Hence the suggestion that Library somehow made it into P4

untold moth
hybrid tundra
#

but its never there

untold moth
ebon abyss
#

What about the build folder?

hybrid tundra
#

those folders/files are never in the changelists

untold moth
#

Files only appear in the pending changes when you check them out

#

Or reconcile offline work

hybrid tundra
untold moth
#

You should really start from looking at the depot. See what files are added to version control. Perhaps some temp files are added. If so, then whoever created and manages the depot are just dummies

hybrid tundra
#

found the .p4ignore file

hybrid tundra
#

anyway, I have found the p4ignore file

untold moth
#

Ok, make sure that it's in the correct place and contains the expected paths

hybrid tundra
#

can I use this the same way as .gitignore? so adding the path where the file was P4 couldn't check out offline, making the build, and when I go back where I can connect to P4, I can remove that line from p4ignore?

#

would this work?

hybrid tundra
#

thanks

untold moth
#

Though, thinking about it, if the ignore file was not in there originally, it might not help.

untold moth
#

Then what happened to it?🤔

hybrid tundra
#

Version Control: Cannot check out files in offline mode
Assets/StreamingAssets/addressable_keys.json

#

and the Assets/StreamingAssets is in the p4ignore or whatever it is called

#

yes, p4ignore

#

but the thing is that

#

only specific file types were mentioned in the p4ignore inside that folder

untold moth
#

Ok, so there was more info that you didn't reveal... You could have saved us a lot of time...

hybrid tundra
#

/Assets/StreamingAssets/.bank
/Assets/StreamingAssets/
.bank.meta

#

these were in the p4ignore

#

and the addressable_keys.json is a json