#archived-dots

1 messages Β· Page 118 of 1

zenith wyvern
#

When you read that page on IJobParallelFor, in what ways do you think your requirements differ from what you're seeing in the example?

odd cipher
#

well first of all, my tile array is a 2 dimensional array so that gets complicated with the index

zenith wyvern
#

You can easily represent a 2D array with a 1D array, and convert a 1D index to 2D and vice versa. So inside Execute you can derive your x/y position from the index it's passing

odd cipher
#

not sure if it'll be worth it though

zenith wyvern
#

Dunno, based on your description this is exactly what a bursted job is good at, transforming data in a linear array. Up to you if you actually want the performance or not

odd cipher
#

I suppose I'll keep trying but I dont really understand the syntax or how to use it in a way that works with my code so

zenith wyvern
#

Just study that page I linked carefully. A big part of switching to using burst is rethinking how you structure your data. If you want that performance, you need to represent your data in a cpu-friendly way, no abstractions. When you get it into a nice linear array and rewrite your logic to work inside jobs, you will be amazed at how fast it moves compared to the kind of OOP most people write.

#

Also make sure you actually enable burst on your jobs with the [BurstCompile] attribute

odd cipher
#

@zenith wyvern Thank you, so just to be clear, what you are saying is that I call the job once instead of creating one for every 40,000 tiles?

zenith wyvern
#

Yes, just like the example in the link I posted

odd cipher
#

@zenith wyvern Alright, hopefully I'm not annoying you but how did you say I could convert the array to 1D?

zenith wyvern
#

Should be plenty of material on google on how to represent a 2d array in a 1d array

odd cipher
#

@zenith wyvern One problem is that I can't SetPixels in a separate thread

zenith wyvern
#

Yes, you would complete the job then write the array all at once with one of the batch versions of SetPixels

#

SetPixelData even takes a NativeArray directly

fathom trout
#

There's the added complexity that the data needs to be formatted correctly for the texture format (not colors) it may have to be represented as bytes

#

Tho u could convert in a final job

#

As far as perf being 800ms, the editor has safety checks that slow things down

#

(safety can be disabled in burst drop down menu, but is good idea to keep on when developing)

low tangle
#

if your writing a texture in jobs/ecs land I'd be using a dynamic buffer <yourrgbstruct>

#

and only binding / doing the texture upload though a final call

#

that way only that last step has to be on main thread

odd cipher
#

@zenith wyvern well back to this error, I'm pretty sure it appears because the NativeArray is being edited in multiple threads at once Index 0 is out of restricted IJobParallelFor range [36663...36663] in ReadWriteBuffer.

zenith wyvern
#

Inside execute you're trying to access index 0. You can only access the index passed by the execute method

odd cipher
#

dont get what you mean

zenith wyvern
#

From the page I linked you: Execute(int index) will be executed once for each index from 0 to the provided length. Each iteration must be independent from other iterations (The safety system enforces this rule for you). The indices have no guaranteed order and are executed on multiple cores in parallel.

odd cipher
#

It's just really confusing

zenith wyvern
#

Not sure how it could be any more clear than the example on that page. You can always try taking a step back and working on a simpler test project

#

Just to get a better feel for how to properly write jobs and structure your data

lusty otter
#

It's like a for loop and each Execute is just the body of the loop, so you are only supposed to operate on the index given by the argument.

low tangle
#

think of it as a for loop where based on your batch sizes and number of cores in your machine it will give one job thread all the job data and say run(0-100) a random other one (400-500) and then another one (300-400) and so on

#

the safety system is just enforcing you work on the right indices

pine fiber
#

Hello, I'm making a game with procedural terrain. Instantiating tons of terrain objects is pretty slow. Is dots something that could speed up the instantiation of lots of prefabs? (Sorry if this is a dumb question)

low tangle
#

prefabs of gameobjects, no, best to pool that kind of thing

#

what kind of procedural terrain is important

#

are you sure that its the spawning thats slow and not generating the data?

zenith wyvern
#

Is there a simple way to change a value type in a job without putting it in a nativearray?

opaque ledge
#

if its 'global' i use shared static for that, thats what i do with Random for example, but no if that value belongs to an entity or system probably

#

but perhaps you could take the unsafe pointer of that value and send it to your job ? never tried it before but perhaps there is something like that

low tangle
#

.Reinterpret<T>() @zenith wyvern

#

most native things support it, and its free, but make sure the type your converting to is the same size (or you know the difference)

zenith wyvern
#

It's more like what Curly said I just want to store a single value associated with my struct, putting it in a nativearray is annoying but I have no idea how to work with pointers in C# so I'll just use a NativeArray with a size of 1

low tangle
#

you mean, so that your job accesses the same as another job?

odd cipher
#

One of the problems I'm having is that the index cant be used in addition for some reason; this works cs for (int i = 0; i < c.Length; i++) { colors[index] = c[i]; } but this doesnt cs for (int i = 0; i < c.Length; i++) { colors[index + i] = c[i]; }

opaque ledge
#

what kind of error does it give ?

#

if you are doing this in parallel job safety system wont let you

low tangle
#

you shouldn't be traversing the array manually with a for loop

odd cipher
#

Index 23328 is out of restricted IJobParallelFor range [23324...23327] in ReadWriteBuffer. etc etc

low tangle
#

but if you need to do something like i+0 i+1 i+2 as a stride then thats something different

#

yeah because your trying to walk outside of your allowed index

odd cipher
#

soo you cant do for loops in a IJobParallelFor?

low tangle
#

you can

#

but not on the base data when writing

#

you can only write to your data at index as a race condition safety

#

you can turn this off but I don't think you are doing something that needs that yet

#

if you explain a bit more of what you are doing I'll show you

zenith wyvern
#

@low tangle Yeah, basically I'm making a NativeContainer and I have an associated length. I write to the internal NativeArray so the changes are reflected outside the job, but if I change the "length" int inside the job, it's not reflected outside the job

low tangle
#

length isn't assignable iirc

#

on an array

zenith wyvern
#

Yeah it's my own variable

low tangle
#

yeah, thats because the values there are thread local memory

#

everything inside the job struct is thread local copy of the inital data when constructing the struct on the main thread

zenith wyvern
#

Just an int inside my container struct. And yeah that's what I figured, I was wondering if there's a way to make that data shared outside of putting it inside a nativearray

odd cipher
#

Well, before I was doing all these Job things I had a function that got called 40,000 times (for each tile) at startup or when you regenerate a world, and that function did everything like neighbour checking and setting 8x8 colors at tile position in a Texture2D. Now with Jobs I pretty much want to do the same thing but in a more optimized manner, but I cant get anything to really work as I want it to. Mainly because I pretty much cant edit a Texture2D in a different thread

low tangle
#

well, when I ran into that kind of problem before, I just stuffed it onto a singleton entity with a known type. in the job struct I grab the entity, paste it in, grab a ComponentDataFromEntity<singletonT> and shove that in with safetys off

opaque ledge
#

you dont need to use ECS for that, you can just use a bursted job if its computation heavy @odd cipher

low tangle
#

into the job struct creation on the system

#

yeah you wont edit a texture2d directly

odd cipher
#

Yeah I know I dont need ECS for that, I am talking about just Jobs

low tangle
#

thats just to paste in the data at the end in bulk

#

instead your job will be operating on a NativeArray<Color> of [Width*Height]

#

your for loop operates on the 1d values, so you would then index % width to get your x and index / width to get your y

#

then your inside your for loop with X, Y and the rest is your algo

#

any procedural data will be brought in as NativeArrays, or generated there

odd cipher
#

so, that NativeArray has the whole Texture2D or one NativeArray for every tile?

low tangle
#

one native array is the colors that will be set onto the texture2d when done

#

its your placeholder for the texture2d, you do all work on it, then later on you would paste it onto the texture2d in one memcpy and call it a day

odd cipher
#

then I'm pretty sure the problem I'm having is just that final loop. because thats supposed to set a 8x8 area of colors in a tile but currently it doesnt

bright sentinel
#

Did you post the whole code somewhere?

#

That would help me help you

odd cipher
#

I havn't since its rather large and most of it doesnt have anything to do with the Job part

bright sentinel
#

That's fine, you can just point us to where the problem arises

#

We're big boys, we can manage it

odd cipher
#

well pretty much this part in the Job cs for (int i = 0; i < c.Length; i++) { colors[index] = c[i]; } because currently that will just set one pixel. not a 8x8 area of pixels which is what I had before I tried using this Job system

bright sentinel
#

Can't help you much without the full code though

odd cipher
bright sentinel
#

@odd cipher I'm not sure why you would loop over it like that. the index variable isn't going to change within the for loop. So that would be the same as removing the for loop and setting colors[index] = c.Length - 1

odd cipher
#

I just said why It's like that and why I need to change it somehow but I dont know how

bright sentinel
#

Well, if you post the whole code it would be easier

odd cipher
#

that is pretty much all the code

#

that use the Jobs atleast

bright sentinel
#

But it's not all the code

#

If you refuse to let me help you, then I won't try, sorry man

low tangle
#

instance.tiles1D

odd cipher
#

yeah that might a lil problem aswell

low tangle
#

this isn't passed into the job

#

avoid strings

#

instance.GetSprite(

#

this likely wont work

#

I dont see this function nearby as a static function

#

also sprites are objects in unity mono land

odd cipher
#

no instance is the script that this is in

low tangle
#

for (int i = 0; i < c.Length; i++) {
this doesn't work because your already in the body of a for loop doing this for you

#

IJobParallelFor

zenith wyvern
#

You can't use any reference types or any mutable static data inside a job. Basically you should think as your job as being entirely self contained.

#

And I mean entirely. No exceptions.

#

Anything the job needs, you pass in.

#

And again, no reference types.

#

That means no "normal" arrays, only NativeArrays

#

And no strings, and etc etc

odd cipher
#

seems really annoying to work with then

low tangle
#

only at first

zenith wyvern
#

Like I explained earlier. You need to entirely rethink how you are structuring your data. You are making it CPU friendly.

low tangle
#

if you get over the small hump its easier for some people to build this way

#

and a lot faster for the cpu

zenith wyvern
#

And the performance gains are truly massive compared to how most people write OOP.

odd cipher
#

Alright well, the first thing I still dont understand is the index

opaque ledge
#

i still dont know what/how burst do but it works 🀷

odd cipher
#

in IJobParallelFor yes

low tangle
#

its a bunch of for loops

#

each running on batch size index's

#

one will run on 0->batchsize another on batchsize->batchsize*2
if batchsize is 8
that would be two different for loops running on
for(int i = 0; i < 8; i++)
and a totally different one running on
for(int i=8; i<16; i++)

#

yeah but hes not getting the simple fact of the slicing

#

needs to connect the index to that for loop thats done for him

opaque ledge
#

IJobPrallelFor is to process an array in a parallel manner.
Lets say i have int NativeArray that has 10 elements, then what will this IJobParallelFor will do is process each element in a parallel manner, that "index" variable in the execute function is the index of the array that is currenty being executed basically

low tangle
#

I'll let you take over though, I'll get back to work

opaque ledge
#

you can think of IJobParallelFor is the loop itself, and execute function determines what it does with it's elements

odd cipher
#

I just need to figure out how to set a 8x8 pixel area per loop and that is what is confusing me at this point, for that loop that I showed a couple of times

#

no, they are pretty much tiles

zenith wyvern
#

Oh I see, each of your tiles are represented by 8x8 pixels in the texture, right?

odd cipher
#

yeah

zenith wyvern
#

Hmm I'm trying to think of the best way to do it

low tangle
#

longer size / 8

zenith wyvern
#

@digital scarab Is it possible to make it safe to access a certain sub-section of the array within a ParallelForJob without disabling the safety system?

low tangle
#

actually wait width / 8 + height / 8 for the number of tiles to loop though

#

that gives you the tile index you are working on

#

the only problem is the saftey system will have to be disabled on the nativearray

opaque ledge
#

or cut your array into pieces and process each with their own jobs and and combine those jobs and wait for them ?

low tangle
#

more complex for no gain

zenith wyvern
#

Cut my array into pieces....this is my last resort.

opaque ledge
#

but yeah, why would disabling safety be a problem πŸ€”

low tangle
#

suffocation no indexing

#

because we made a big deal about it and it will be confusing why the 180 flip and disabling it

zenith wyvern
#

If you have the tile index though you may not even need to access adjacent indices

#

Whatever logic you were going to do could be figured out from which pixel within which tile you're in

opaque ledge
#

thats... thats pretty deep

zenith wyvern
#
void Execute(int index)
{
    int tileSize = 8 * 8;
    var tileColors = new NativeSlice(texColors, index * tileSize, tileSize);
    for(int i = 0; i < tileColors.Length; ++i )
        tileColors[i] = whatever
}

Something like that I guess? And you would have to disable the safety restrictions on your container

#

@odd cipher So basically instead of doing the foreach over every pixel, you want to do it over every set of pixels representing your tiles. You get the subset of pixels representing your tiles using a NativeSlice like the code snippet and you can change the slice to affect the pixel of that tile

#

It's a bit complicated but that is probably how I would do it

low tangle
#

don't think you can create the slice in the job but I haven't actually tried

dull copper
#

I now can't get over a mental image of baby yoga trying to ride a tiny bicycle

#
## [Havok Physics 0.2.0-preview] - 2020-03-12

### Changed
- `HavokSimulation.ScheduleStepJobs()` now takes `SimulationCallbacks` and `threadCountHint` separately as input arguments.
- `Simulation.CollisionEvents` and `Simulation.TriggerEvents` can now be used to iterate through the events directly using a `foreach` loop, rather than only via `ICollisionEventsJob` and `ITriggerEventsJob`.

### Fixed
- Android ARM64 platform is now supported. Please see [Supported platforms](Documentation~/platforms.md) for details.
- Jobs implementing ICollisionEventsJob, ITriggerEventsJob, IContactsJob, IBodyPairsJob or IJacobiansJob can now be Burst-compiled in both editor and standalone player.
- Duplicate jobs for debug display (like FinishDisplayCollisionEventsJob) are no longer being scheduled, since only HavokPhysics variant of their systems (DisplayCollisionEventsSystem) is now running and covers both HavokPhysics and UnityPhysics simulation.
#

@warped trail ^

#

just tested the new havok package, at least the joints don't explode on it anymore like in the earlier version πŸ˜„

#

that being said, I don't have 100% same setup here but it should be close to identical for the joints themselves

#

the previous exploding suggested some forced rigidbody overlap tho and that could indeed be different now on my test scene as I use different mesh

warped trail
#

how can i use this Simulation.CollisionEvents ?πŸ€”

opaque ledge
#

Yeah, i asked the same question yesterday but couldnt figure out

#

Simulation property from StepPhysics returns the interface not Simulation class which holds the trigger events and collision events

warped trail
#

and Burst does not support foreach πŸ€”

mint iron
#

generally yeah, it does with a ref struct though.

dull copper
#

new hybrid renderer v2 test projects on srp branch now

#

so I guess 0.4.0 is v2?

#

we are now at 0.3.5-preview.15

#

that 0.4.0-preview.7 isn't yet available on public registry (had to check)

#

(meaning, we can't test this ourselves yet)

mint iron
#

is there a list anywhere yet of whats changing? the two things i care about are 1) manipulating shader properties without hacks or replacing the material and 2) being able to build for IOS without it showing psychedelic textures. been working on other things while i wait for these.

dull copper
#

there isn't any list yet but once the hybrid renderer v2 releases, we get at least the changelog

#

this is what Joachim wrote at the start of Feb: ```Changes are part of 20.1.

It is both massive perf improvements, keeping all instance state persistent on the GPU.
As well as supporting the full feature set of HDRP during conversion. ```

#

(about the upcoming hybrid renderer upgrade)

#

I'm bit reserved on "full feature set" part there, but it's probably going to be more compatible at least

#

also from what I can tell, the changes are for both HDRP and URP on the SRP repo, no idea if they still keep focusing on HDRP more (like they said earlier)

#

@mint iron I did dig the psychedelic visuals tho πŸ˜„

#

but yeah, better URP support would probably help you there

mint iron
#

sounds promising, so very glad they're working on it.

opaque ledge
#

uuuh, burst new package ? πŸ‘€

bright sentinel
#

Should hopefully fix some of the crashes

opaque ledge
#

yeah probably, since previous release was yesterday

pliant pike
#

I'm confused how comes I can convert a LocaltoWorld straight into a Matrix4x4 componentdata but I cant convert Localtoworld into a Matrix4x4 in a local variable?

zenith wyvern
#

Should be able to. Again, make sure you're using localToWorld.value so you're actually using the float4x4 and not the localToWorld

opaque ledge
#
## [1.3.0-preview.6] - 2020-03-12


### Added
- Experimental support for `Prefetch`, allowing users to request from the memory subsystem pointer addresses they intend to hit next. This functionality is guarded by the `UNITY_BURST_EXPERIMENTAL_PREFETCH_INTRINSIC` preprocessor define.

### Fixed
- Fix SSE `maxps` intrinsic would emit `maxss`
pliant pike
#

yep am doing that I think

pliant pike
#
Matrix4x4 bezzymatrix = new Matrix4x4();
        bezzymatrix = BezzyTransform.Value;```
#

that's what I'm doing the Bezzytransform is the localtoworld and it does not work

coarse turtle
#

BezzyTransform.Value is a float4x4?

pliant pike
#

no its a LocaltoWorld

coarse turtle
#

you need it to be a float4x4

#

since float4x4 can be implicitly converted back to Matrix4x4

#

otherwise you can do a Matrix4x4.TRS(position, rotation, scale)

pliant pike
#

do I have to manually do that with each specific variable? I thought I could auto assign it

coarse turtle
#

uh what does auto assign mean?

pliant pike
#

i just mean assign all the variables at once like an array to an array

#

it works when I assign a transform to a localtoworld in the conversion for instance

zenith wyvern
#
        float4x4 f = default;
        Matrix4x4 m = default;

        m = f;
#

That works

pliant pike
#

I can even assign a transform straight to a matrix4x4 by using transform.localtoworldmatrix

zenith wyvern
#

LocalToWorld.value is a float4x4 isn't it?

mint iron
#

it is

warped trail
#

localtoworldmatrix is matrix4x4πŸ˜…

pliant pike
#

goddamit BezzyTransform.Value.Value;

#

how would i know to put that leahYTHO

coarse turtle
#

Oh you stored a LocalToWorld component

zenith wyvern
#

Oh, you wrapped a LTW in your own type

#

Why did you do that

pliant pike
#

I wanted one that I knew and was easily accesible

bright sentinel
#

yeah that's something I'm a bit confused about. Is there a reason the Matrix4x4 stores a Float4x4? The same with quaternion

#

Why not store the individual variables inside the structs?

pliant pike
#

I couldn't just get it off the entity because I'd have to create a tag for entity and couldn't be bothered

coarse turtle
#

individual variables in the struct?

warped trail
#

what do you mean by individual variables?πŸ€”

bright sentinel
#

Like we can do Quaternion.x, but we have to do quaternion.Value.x in ECS

zenith wyvern
#

Well I'm not sure what you're trying to do, but the point you need to understand is that you're not converting a LocalToWorld to a Matrix4x4, you're converting a float4x4 to a matrix4x4

warped trail
#

4x4 matrix is default thing for transformation, isn't it?

pliant pike
#

no wonder I was confused

warped trail
#

quaternion.Value.x what? πŸ˜…

#

maybe Rotation.Value.x ?

worldly pulsar
#

@bright sentinel I think you are confusing Rotation (a component) and Rotation.Value (quaternion)

warped trail
#

oh

bright sentinel
#

... I might

warped trail
#

never used direct values

warped trail
#

it is quaternion.Value.xπŸ€”

#

sorry

bright sentinel
#

I was right

amber flicker
#

yup - float3.x but quaternion.value.x is a bit annoying

mint iron
#

the could build getters into the default components make it look nicer i guess.

zenith wyvern
#

All components are just wrappers around the underlying data. You shouldn't think of a component itself as your data, it's just the wrapper

worldly pulsar
#

oh, sorry, the quaternion has a float4 in it

amber flicker
#

it just happens to be a constant exception with my codegen as it's different from other types but it's not a big deal

#

I guess it might help remind some people it's not euler?

pliant pike
#

i think I remember i had a blob that was value.value.value once

coarse turtle
#

haha - yes that was me once πŸ€”

bright sentinel
#

Yeah I also don't like the naming of the built-in components Value

#

Too nondescript imo

worldly pulsar
#

considering the UnityEngine.Quaternion docs have a "please don't touch this" next to each of x,y,z,w storing an opaque "value" may be a good idea tho πŸ˜›

warped trail
#

yeah, why do you need this valuesπŸ˜…

pliant pike
#

that's it I'm not using value anymore 😠

bright sentinel
#

@warped trail For netcode syncing

#

I mean, it's not like a big thing to write .Value, but it caught me off guard for a while

mint iron
#

what about an extension with aggressive in-lining, you'd have to check but it might collapse it.

worldly pulsar
#

can't have extension properties, so it'd be quat.x(), which is even more confusing

mint iron
#

mmmm 😦

#

write your own version of the components and cast it would work

coarse turtle
#

I've written an extension for localToWorld to get the scale as an xyz float3 and my friend looked at me funny asking 'What's ltw.Scale()?"

dull copper
#
## [Burst 1.3.0-preview.6] - 2020-03-12

### Added
- Experimental support for `Prefetch`, allowing users to request from the memory subsystem pointer addresses they intend to hit next. This functionality is guarded by the `UNITY_BURST_EXPERIMENTAL_PREFETCH_INTRINSIC` preprocessor define.

### Fixed
- Fix SSE `maxps` intrinsic would emit `maxss`
#

I thought prefetching didn't give any gains on modern cpu's

vagrant surge
#

it does bring gains

#

i measured gains from it on an ECS implementation i did

#

but it was very convoluted to actually work well, so it was annoying to use

#

i saw a gain of 10%

dull copper
#

ah, I just remember some older discussion on this topic where that was the stance for not supporting it

vagrant surge
#

but it was having to look-ahead 5 steps

bright sentinel
#

Isn't that the whole issue of performance optimizations? πŸ˜‚

vagrant surge
#

in the algorithm

bright sentinel
#

Hard to achieve

vagrant surge
#

and btw

#

those 5 steps

dull copper
#

btw, unity updated physics samples now: https://github.com/Unity-Technologies/EntityComponentSystemSamples

## [Samples Project for 0.3.0-preview] - 2020-03-12

### Changes

* Joint samples now correctly add new joint entity to prefab's linked entity group so they will be instantiated along with the rest of a prefab.
* Renamed `StiffSpringJoint` to `LimitedDistanceJoint` to reflect changes in API.
* Updated the following packages
    * Input System from `0.9.6-preview` to `1.0.0-preview.5`
    * Lightweight RP from `7.1.6` to `7.1.7`
    * DOTS Editor from `0.2.0-preview` to `0.3.0-preview`
    * Hybrid Renderer from `0.3.3-preview.11` to `0.3.4-preview.24`
* Character controller improvements
    * `CharacterControllerUtilities.CheckSupport()` now uses a collider cast
    * Character now doesn't collide with triggers, but raises trigger events instead
    * Fixed the support check issue with slopes equal to MaxSlope
    * Fixed the returned support state when there are no supporting planes```
vagrant surge
#

if i had less or more, the 10% would quickly evaporate

#

sub 3 steps it was actually slightly slower

#

basically forming a bell curve

#

so yeah it was definitely not a good idea to try using it in that algo, at all. Too volatile and only works at specific step size that depends on cpu

coarse turtle
#

interesting - that's good to know

vagrant surge
#

there are some fun cases where you can get gains. THere is a cppcon talk about it

#

a very fun one

#

where they abuse coroutines to execute a bunch of binary-searches at once, interlieaving the search state with prefetching

coarse turtle
#

o - do you have the link to the video?

vagrant surge
#

i did some tinkerin with the coroutines on cpp20

#

they already work on visual studio

#

they are pretty fun. Better and more flexible than the C# ones

#

main detail of the cpp coroutines is that their overhead is very low. They are stackless, and its basically an abstraction over a state machine

safe lintel
#

anyone know how you use ConvertAndInject with child gameobjects ? I want the builtin conversion system to run on the child gameobjects though, not just manually adding components

vagrant surge
#

the compiler creates a "context" struct with a state machine inside, and thats what the coroutines converts to. It does 1 allocation

#

in that talk above, they do the whole state machine business by creating a custom coroutine type, and then also create a custom allocator, because coroutines in C++ will forcibly allocate once

coarse turtle
#

@safe lintel havent found a public API yet - but I did manage to do it with reflections to match ConvertAndDestroy but left out the destroy part

worldly pulsar
#

Cpp coroutines are closer to the auto-generated IEnumerators (with yield etc) from C# than the Go variant, right?

vagrant surge
#

somewhat, yes

#

but a lot more controllable

#

kinda... too much

#

its absolute madness

#

in fact, the compiler doesnt implement coroutines

#

its up to the library writers to use the syntax sugar state machine thingy

#

and create their own coroutine types

#

in the cppcoro lib, there are a few you can use, thats what ive been tinkering with

#

there is a generator<T> coroutine that is sync (cant await), and its handle can be used as iterator

#
generator<int> numbers(int max){
for(int i = 0; i < max; i++){
co_yield i;
}
}

for(int n : numbers(3)){
cout << n;
}

#

this will print 0,1,2

#

also a recursive_generator where you can yield a generator inside another generator, but from the outside, everything will still be a 1d linear iterator

worldly pulsar
#

yeah, really wish the C# enumerators had less overhead. They are really convenient (vs. an explicit state machine), and writing this kind of generators as structs that can be supported by foreach is so much pain

vagrant surge
#

the library also has more "typical" coroutine stuff. THere is a Task<> type that is a over-time task (can be co_awaited), and in fact it doesnt get executed until you co_await it

#

but yeah, the point of the cpp coroutines is that they are spectacularly overengineered, so that library authors implement whatever they want with the "base" mechanism

worldly pulsar
#

I was trying to replicate the Rust-style iterators a few years ago, would be trivial to do with yields (or even LINQ) if you don't care about allocations, ended up with like 2k LoC of generic structs just for some basic iteration over lists/arrays/slices

vagrant surge
#

rust final async-await thing is not iterators

#

its just the "state machine" base

#

its also truly zero overhead. rust awaits dont allocate

#

unlike cpp ones

#

honestly my first impression of generators is great

#

this is crazy good for ecs stuff

#

simplifies the code

#

i will try to make those sort of prefetched generators (like in the talk above) on my ECS lib

worldly pulsar
#

I meant the Iter trait (and friends) and how the Rust for works. Like expressing your int 0 -> max generator as a C# IEnumerable struct is a stupid amount of code

junior fjord
#

do you guys have tag components or do you have boolean components do do if(booleanComponent.true) in the systems?

#

say for example if a mesh needs to be recalculated, should I do it as a tag or boolean component?

worldly pulsar
#

mostly depends on if I want to query by that component

junior fjord
#

yeah I mean either you query or you do a if statement

slim nebula
#

sorry for the newb question: what's a tag component?

worldly pulsar
#

if the mesh recalculation is rare I'd probably use a tag

fallow mason
#

Generally better to mark (ie change boolean value) if it changes every frame

#

Tagging changes chunk archetype

worldly pulsar
#

@slim nebula tag components are components with no data in them (only used so that you can use them in queries)

junior fjord
#

yeah because of the copying when changing archetype I was asking

#

there won't be new meshes created every frame

#

only when the player changes something in the environment

fallow mason
#

I'd just tag in that case then. Fewer entities to iterate through

worldly pulsar
#

In that specific case (assuming that it matters for performance, which it probably doesn't), I'd actually spawn an entity with an UpdateMesh(Entity meshEntity) component or tell the mesh rebuilding system directly to update that mesh when it next updates

junior fjord
#

also what is the best practice for this: I want to create the meshes and store them somewhere and handout an id to some entities, so that I can control the deletion of the meshes from the entity.

Should I do this as a normal C# dictionary in a class that I pass around? what should I use as index? I could use the entities that "own" the mesh as index or just an increasing id.

If I would use an increasing id I could also just use an array of meshes instead of a dict and try to implement some "id reuse" mechanism

fallow mason
#

WithChangeFilter could be of use too

junior fjord
#

@worldly pulsar you are a genius thanks

#

that is the perfect solution

#

I'll check that out @fallow mason

worldly pulsar
#

"best practices" for Unity ECS are not exactly well established. I'd say do the simplest thing that works and see if there are any problems with it

junior fjord
#

ok I mean dict with entity index is obviously the simplest thing

#

and there won't be so many meshes to draw that the iteration over the dict will completly kill me I guess

#

ok and if they somehow make the whole mesh thing fully ECS at some point then I will probably have to change that either way

#

ok trying to find anything that explains what WithChangeFilter does πŸ˜„

loud matrix
#

I know we just said there is no "best practices" for ECS, but if there a good way to make a global entity archtype? I've only been able to find examples of them being setup and used immediately. Where as I would rather set them up all in one location then create them on need, but i can;t think of a good way to go about it.

warped trail
#

you can store it in componentπŸ€”

fallow mason
#

static class?

loud matrix
#

Static class was what I was thinking, Which usually means there's a much better way to go about it.

fallow mason
#

MyGameArchetypes.PlayerArchetype tempting though, huh? πŸ™‚

loud matrix
#

I know I'm gonna end up with like 20 singletons at this rate XD

fallow mason
#

doesn't need to be a singleton, just a static class (in case that's what you were thinking)

loud matrix
#

Well it seems like I need to go do some reading as I apparently have been handling static classes wrong in unity

fallow mason
#

yeah static classes can be abused (singletons even more so), but it might be the right tool for this particular job

worldly pulsar
#

Be careful with static classes if you are using the fast scene/assembly reload options

loud matrix
#

It causes issues i take it?

worldly pulsar
#

static fields are not reset to null when you enter/exit play mode (that's like 90% of the speed boost you get from the fast assembly reload afaik). So be sure you explicitly initialize them in system OnCreate or w/e

glossy summit
#

Anybody know what's happening with the Hybrid dots renderer V2 that was added to the roadmap?

#

what's new with v2, why is it better etc.

bright sentinel
#

@glossy summit There's some discussion further up about it, although not sure how much πŸ˜… Generally, it has full feature set for SRP, URP and HDRP, and a lot better optimization than V1

glossy summit
#

Ah yeah, found it thanks!

junior fjord
#

@warped trail thanks

fallow kraken
#

guys, i can't get the dots physics debug display to work. all you need to do is create an empty game object and add PhysicsDebugDisplayAuthoring (and ConvertToEntity of course) to it, right? i'm just seeing no debug display at all when running, and there are objects colliding...

odd cipher
#

@zenith wyvern Late response because I had to sleep but that gives me ArgumentException: Slice may not be used on a restricted range array

loud matrix
#

the one downside of ECS I seem to be finding is loading assets at runtime. Which is a shame as I really liked the "old" way of doing it.

bright sentinel
#

@loud matrix I think this is mostly a hybrid/transition issue. I'm sure there will be some better ways once there is some ECS integration with the editor

#

But you're right, it's an issue currently

loud matrix
#

I keep wanting to make a quick prefab out of cubes but its quicker to just make it in blender and export a propper mesh

sour ravine
#

Is this a good channel for DOTS networking? Thoughts on using ghosts for NPCs/synced AI?

junior fjord
#

just a quick question, if I use z as height instead of y, will I regret that later?

#

I mean will I often have to work against the system in some sense?

bright sentinel
#

@sour ravine As with any network question... It depends on your needs. Generally, if your NPCs change their path a lot/is not on a predictable path, then you probably want to use ghosts. If they are predictable though, you might want to just sync whenever a change in their path happens.

junior fjord
#

it makes life especially easier for me since I often have 2d coordinates on my map and then at some points add the height,
newpos = int3(pos, height)
is much nicer than
newpos = int3(pox., height, pos.y)

bright sentinel
#

@sour ravine I recommend starting with the ghosts (as you are probably already familiar with it), and if you need to cut down on bandwidth, then you can start looking into how to optimize the data like I described above

#

You may even be able to completely simulate the NPCs on clients with deterministic behavior, depending on your needs

#

But generally NetCode is made with server authority in mind at the moment

sour ravine
#

system is pretty innately event-driven FWIW but we would like to support direct player nav control and player possession of NPCs

#

(RPG)

#

not a bad case for the transport layer but it seems like I might be fighting the fundamental assumptions of ghosts and data architecture

bright sentinel
#

Hmm, I'm not too familiar with NetCode yet to say what your best option for that is then. I'm fairly certain it should be possible to change the entities to be Client Predicted.

#

But yes, right now NetCode is built for FPS games, with generally 1 character tied to 1 player

#

But if you can figure out if you can change an entity from interpolated to predicted, then it's definitely possible to do what you want

#

You can of course also forego any prediction, and sync the player commands to the server, which are then executed, and then synced back to the player

sour ravine
#

the actual codegen stuff is actually a neat idea

#

low-level net replication is usually a brain melter

bright sentinel
#

I'm not a fan of it

#

Surely it should be possible to have that code somewhere without devs having to press buttons to generate it

#

Also forces recompile

#

Maybe there are some pros to it, but I'm not smart enough to know those atm

fallow mason
#

alright, the Tiny Spaceship demo has the Camera converted in a subscene, yet doesn't render the scene unless unconverted. Is this how it's supposed to be?

odd cipher
#

currently having this problem ArgumentException: Unity.Collections.NativeArray`1[UnityEngine.Color32] used in native collection is not blittable, not primitive, or contains a type tagged as NativeContainer

fallow mason
#

I can confirm it converts to an entity with a Camera component on it, but no rendering

dull copper
#

@fallow mason it's listed in the known issues

#

on the 2D tiny forum thread

fallow mason
#

oh hah ok

dull copper
#

basically you have to open the subscene for editing for it to work or something?

fallow mason
#

right

dull copper
#

what's weird is that it still shows up in the scene view

#

just not in game view

fallow mason
#

but then its MB camera which will not work in tiny build if I'm not mistaken

#

yeah, that is weird

dull copper
#

I'd give it more time

#

it's first 2D version on this iteration πŸ˜„

#

like 3rd version so far but still

fallow mason
#

yeah cant expect much yet. just didnt see the forum post. though you'd think camera rendering would be one of the first things you'd address πŸ€·β€β™‚οΈ

odd cipher
#

anyone?

sour ravine
#

you cannot use native containers in other native containers ^

dull copper
#

they might have had it running internally but then disabled it before release if there were remaining issues

fallow mason
#

@odd cipher is Color32 blittable? might need to be float4?

dull copper
#

I mean, I could totally see something like that happening

sour ravine
#

color32 should be. Unity.Collections.NativeArray`1[UnityEngine.Color32] used in native collection is referencing a native collection

odd cipher
#

I'm not sure.. I'm very new to the Job system and its very confusing to me :p

sour ravine
#

Are you doing something like NativeArray<NativeArray<Color32>>?

#

that's no good 😦

opaque ledge
#

You also cant put native collections into struct component datas

odd cipher
#

Well I tried doing this so NativeHashMap<int, NativeArray<Color32>>

#

pretty much

sour ravine
#

ah

#

same deal

#

you want NativeMultiHashMap

opaque ledge
#

You might want to check NativeMultiHashMap

odd cipher
#

Yeah I tried that aswell, but gives the same problem with Color32

sour ravine
#

might be an actual issue with the way Color32 is declared then

opaque ledge
#

NativeMultiHashMap<int, Color32>

odd cipher
#

well I need an array of Color32

#

in each

bright sentinel
#

I mean, isn't Color32 a reference type?

sour ravine
#

it's a struct

opaque ledge
#

probably not

bright sentinel
#

Still might want to use float4 though

#

Not sure if it's blittable

sour ravine
#

did you use NativeMultiHashMap?

odd cipher
#

Tried both

sour ravine
#

I'm not sure if you tried NativeMultiHashMap with an array (which you should not do) or just with the Color32

#

OK, so it might be a problem with Color32 then

opaque ledge
#

One penguin to another, imo try to take it easy if you are new to ecs/jobs, there are some tutorials on the internet that you can check out

odd cipher
#

this is the full line NativeMultiHashMap<int, NativeArray<Color32>> colors = new NativeMultiHashMap<int, NativeArray<Color32>>(tiles1D.Length, Allocator.Persistent);

sour ravine
#

you can use something like a uint4 from the mathematics package

odd cipher
#

yeah I might

#

Its very complicated to me

sour ravine
#

aha, no

#

try NativeMultiHashMap<int, Color32>

fallow mason
#

still native container inside another. cant do

odd cipher
#

but that means it can only have one color no?

sour ravine
#

it's NativeMultiHashMap, not NativeHashMap

#

you can put the values in a temp array if you really really need them in that form

#

in your job, etc.

bright sentinel
#

A NativeMultiHashMap is sort of like a 2D array, which you seem to want

#

You ujst need to handle it a bit differently

odd cipher
#

alright, well, next error :P UpdateTerrainJob.colors is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.

sour ravine
#

the error message is, uh, pretty much correct there 😦

#

what are you trying to do here

opaque ledge
#

are you only reading the colors array ? if so put [ReadOnly] attribute

sour ravine
#

it might actually make more sense to Dare to be Stupidβ„’ and brute force with parallelism

odd cipher
#

I'm trying to make a IJobParallelFor that generates the colors for every "tile" in my 40,000 tile array

#

to make the process faster but im not really getting anywhere on that front

sour ravine
#

yeah, just make a big NativeArray<Color32> and Be Stupidβ„’

#

IJobParallelFor uses an index into that array and does its thing

#

what is the key for

odd cipher
#

the Tile index

sour ravine
#

what's the meaning of/utility of that

#

sparse sets?

#

that's a parallelism antipattern

odd cipher
#

whatever that means

opaque ledge
#

πŸ˜„

sour ravine
#

OK, fair πŸ™‚

#

so for lots of normal CS education, you're taught about skipping work and tricks for that

#

so that looks like you have a hash map set up where you only keep colors for certain tiles (probably hashing the X and Y?)

odd cipher
#

yes

#

but like, so instead of doing that I just have a large Color32 and set that?

sour ravine
#

so parallel work (and jobs) have a different set of assumptions-- you want to do lots of the same work, even though the CS academics will scream at you about big-O efficiency and other brain rot

bright sentinel
#

As I understood it, weren't you trying to create a large array where each 8x8 in that array was the same color?

odd cipher
#

no, each pixel in that 8x8 area is supposed to be different colors

bright sentinel
#

Ah, right

odd cipher
#

because its terrain so

bright sentinel
#

Yeah makes sense

sour ravine
#

yeah it makes more sense to think in terms of individual pixels in your terrain

#

a lot like shader invocations, in fact

bright sentinel
#

I'm just wondering why isn't this just on a texture actually?

odd cipher
#

it is on a texture

opaque ledge
#

You can do [NativeDisableParallelStuff] attribute on the array, and calculate 'local' index from the index you get from execute function, but not sure if that can help your situation

bright sentinel
#

Hmm, it kind of sounds like you're trying to do work on a CPU that should really be done through a shader, no?

sour ravine
#

not necessarily

#

if you need it on the CPU it can save some copies

bright sentinel
#

Hm, that's true.

#

I guess I just really am missing some context on what the end goal is here

sour ravine
#

it might make sense, but that ties into the 'what are you actually doing` question

bright sentinel
#

Hehe πŸ˜„

odd cipher
#

I did not but I 'm quite literally trying everything

#

sort of- but it didn't work very well

#

Alright well, the problem was this Slice may not be used on a restricted range array

#

That was the recommended solution no?

sour ravine
#

Dare to be Stupidβ„’

odd cipher
#

Yeah my system does work without a Job but I wanted to try and optimize it

sour ravine
#

πŸ™‚

bright sentinel
#

I think I'm also a bit confused, but this is maybe just a general confusion about DOTS here and how to architect the jobs. How would you split up the jobs? Would you create a job for each single pixel, or each single tile here?

sour ravine
#

that's actually an interesting question in of itself

bright sentinel
#

Right, but these can be split into either tiles or individual pixels.

#

That's what I'm wondering

odd cipher
#

the reason it works without a Job is because it knows what tile it is on; in this case it doesnt

sour ravine
#

I would actually say tile makes sense on account of cache line sharing

odd cipher
#

non-overlapping 8x8 pixels represent tiles yes

bright sentinel
#

So in this case you would split the jobs into each tile?

odd cipher
#

each loop in the Job is a tile yes

#

I think

#

lol

mint iron
#

lol

bright sentinel
#

No each job should be a tile, right?

odd cipher
#

theres only one Job, which is a IJobParallel

bright sentinel
#

Yeha okay, but each parallel version of the job should loop over a tlie

sour ravine
#

@bright sentinel scan lines are another popular choice in image processing

zenith wyvern
#

You just need to use a bit of math to derive your pixel position for the Execute index

sour ravine
#

anything approx. one cache line in size

#

otherwise lol invalidation

odd cipher
#

@zenith wyvern I have to note, not really that good at math :)

sour ravine
#

you can actually tune the break threshold too

odd cipher
#

yeah, the number of iterations is the number of tiles

zenith wyvern
#

Googling will help you, there are plenty of resources on collapsing 2d arrays. It's a bit more complicated in your case since it's essentially a 2d array in a 2d array

bright sentinel
#

I'm talking about how to structure the execute function of the parallel job. Should I do

setPixel[index] = someColorValue

Or should I

for (i = 0; i < 8*8; i++)
{
  setPixel[index + i] = someColorValueDependantOni
}
zenith wyvern
#

You need to get which tile you're in from the index then derive which pixel of that tile you're in

bright sentinel
#

Because I feel like the parallel could be run as both here

sour ravine
#

@bright sentinel option B very possibly

odd cipher
#

index + i doesnt work

sour ravine
#

it sure do

bright sentinel
#

It was just some very crude pseudo code

#

Don't count on it working

sour ravine
#

well

north bay
#

Why would it not work?

sour ravine
#

assuming index is an int and all that

bright sentinel
#

It was more to get thoughts on how to architect jobs

odd cipher
#

I dont know why it wouldnt work

#

it just

#

this is what happens when I do that IndexOutOfRangeException: Index 13308 is out of restricted IJobParallelFor range [13296...13307] in ReadWriteBuffer.

#

Definitely

sour ravine
#

[NativeDisableParallelForRestriction] is necessary for that in any case, I think

#

otherwise the bounds checker will think (not without merit) you're stomping over other values

#

might be misunderstanding the attribute tho

bright sentinel
#

If we go with option B of my pseudo code, then it is needed, as the index will only be as many as you have tiles, while the size of the NativeArray will need to be 256 times the amount of tiles

odd cipher
#

yeah, done that

zenith wyvern
#

In at work so I cant write an example for you right now. You need to do more research on collapsing 2d arrays so you really understand what that means and how it works

bright sentinel
#

@digital scarab What are your thoughts on my different options? The first option will generally need to have the data more accessible beforehand, as each job would need some way to access the individual pixels value, while the second will to know which tile it is currently operating on.

#

It feels like the first option is more the DOTS way, but the second option improves "developability" a lot

#

At least it's easier to conceptualize

#

You would probably even need another job to lay out the data properly

#

Right sure, but that seems like it would require a lot of work done before entering the job, and sort of breaking the whole purpose for a job

#

Since it would need to know which pixels to operate on, and then you've already done the heavy work outside the job

sour ravine
#

not necessarily

#

you can do sparse writes

bright sentinel
#

Sorry if I'm not understanding exactly what you're saying or making myself clear, but the whole DOTS way of thinking is quite new to me

#

Sparse writes?

sour ravine
#

read start offset from a NativeArray<> and use the same 8x8 block logic

#

jobIndex turns into Offsets[jobIndex] where Offsets is your array of tiles in need of updating

#

could also be scan lines or any other non-pixel level of granularity

bright sentinel
#

I kind of thought that the whole point of jobs was to split each execution into atoms, i.e. the smallest part available

#

But this kind of breaks that way of thinking, no?

sour ravine
#

the point of jobs is to be parallel, just on its own terms

#

sometimes being parallel beats being smart

#

sometimes being smart and then parallel beats being parallel

mint iron
#

is he just trying to iterate all the blocks in a 2d grid?

sour ravine
#

p much

#

that's an embarassingly parallel problem anyway, but you're assuming every pixel needs touching

#

which may (but is not necessarily) be true

odd cipher
#

I'm just considering to go back to before all this Jobs stuff

bright sentinel
#

I'm just confused as to when you should stop granularity within jobs. Because before all this it made sense to split jobs into its smallest part as possible, kind of like a fragment shader. But now I'm just confused

mint iron
#

i dunno unless you're careful and really need to go parallel it can easily be slower.

#

smallest part possible is not a good idea either because you've got the scheduling overheads

sour ravine
#

SIMD parallelism likes small dumb scalar jobs but I don't know what Burst is capable of there

#

which I will class as extremely advanced topic

#

speaking of GPUs

bright sentinel
#

Hm, DoD is confusing. That's all I've learned from all of this πŸ˜‚

sour ravine
#

all software is terrible

bright sentinel
#

Well, objects are easy to conceptualize

sour ravine
#

especially Javascript

bright sentinel
#

Now THAT we can agree on

#

[] + {} != {} + []
shivers

mint iron
#

yeah, nightmare material

bright sentinel
#

Ghost stories told around a campfire: [] + {} != {} + []

#

Anyways, it's still been educational

#

Although I still can't quite wrap my mind around DoD

#

Feels like I'm missing a few puzzle pieces

#

(Sorry for hijacking the chat)

odd cipher
#

but my math def isnt helping this situation

sour ravine
#

@bright sentinel DoD throws plenty of professional engineers for a loop-- case in point Mike Acton's GDC presentations on the topic.

#

Always liked John Carmack code, he's another really smart dude that figured this out before it had much of a name

bright sentinel
#

So what's your argument for using a double for loop within the "execution" loop? Couldn't that also be in their own jobs?

#

@sour ravine That's good to know πŸ˜…

sour ravine
#

that's not quite what he's asking I think

#

it's a 'why this granularity' question

#

not indexing logic

#

I'll take a stab at it, then

#

there's a minimum amount of work involved with setting up a job

bright sentinel
#

Even then you could put that into a job, by supplying it with which pixel coordinates to draw on and the color

sour ravine
#

like, at a very mechanical level you need to spend some cycles putting things in the worker thread queue

#

I think that's what the question is really about-- nested parallelism and what makes sense as a unit of work

#

jobs creating other jobs/mesh dependencies are actually kind of a parallelism holy grail

#

Amdahl's, etc.

bright sentinel
#

Of course that's possible. I can set up a job that takes the pixel coordinates which will be unique, and input the color it should be set to as well

#

No I'm not :d

#

πŸ˜„

#

But what's stopping me from saying that each execution should read data about which pixel coordinates it should set and what color that should be?

#

But wouldn't that mean something like a blur algorithm isn't thread safe?

sour ravine
#

write hazards are always a thing

#

I'm not understanding what you're asking, then

#

topher is correct

bright sentinel
#

That was a bit of a tangent though to the original problem. Let's park that for now.
What I'm not seeing in the problem though is how each pixel is dependent on each other

#

But in the example code you posted, the pixels didn't seem to be dependent on each other

#

Right, and I understand that part

sour ravine
#

yeah, so maybe I was kind of right. That's the embarassingly parallel bit. There's no actual interdependence between pixels, so scheduling it in the smallest, most parallel terms (i.e. most number of elements) makes sense

#

if you use a different algorithm that can impose ordering limits

bright sentinel
#

What I'm trying to understand is why I wouldn't execute for each of those inner loops if I need to do some calculation on each pixel, compared to executing for each block. (And I mean

sour ravine
#

and that's what topher lumps into scheduling overhead

bright sentinel
#

Yeah I think you get what I mean @sour ravine πŸ˜…

sour ravine
#

which is a broad and rather technical topic

bright sentinel
#

Which was exactly what I wanted to know about πŸ˜…

#

Exactly my point

sour ravine
#

yep, p sure they get it

bright sentinel
#

Why would you do a block over individual pixels?

sour ravine
#

so I was right, this is a question about parallelism and scheduling overhead

#

why would you choose to use blocks over pixels when it can actually be done in more parallel fashion

#

that's the question being asked, I think

bright sentinel
#

πŸ˜‚ This is getting comical haha

#

I'm sorry if I have been unclear here, but it's really cleared up a lot about parallelism at least. I get that overhead can be a problem if what you're doing in a job is very little work. This at least seems like a problem for the profiler. But it makes sense that you would try to atomize the job if you can

#

Just trying to explain my thinking helped me make it more clear

amber flicker
#

🀞 crossing my fingers so hard right now that smelly is actually Acton trolling everyone πŸ˜‚

sour ravine
#

if that's correct, just consider that there are some cycles involved with configuring the job scheduler. If you spend a certain number of them setting up a job, and processing an individual element takes about the same amount of cycles, there will come a point where you will have spent more cycles on job creation over actual element processing

#

this is disguised Amdahl's Law

#

Mike I love you if you're actually reading this

#

Big Mike

odd cipher
#

I have no idea what is going on in here anymore

bright sentinel
#

I'm sorry for hijacking your problem πŸ˜‚

odd cipher
#

I feel like I started something here

bright sentinel
#

@sour ravine Yeah, I guess that helps explain it. I guess this helps to learn a bit more about DoD, but adds a lot of complexity when actually writing your jobs haha

sour ravine
#

just remember that any scheduling is going to happen on the main thread by design

#

it's not a wrong decision, but it is going to contribute to that parallel vs. serial factor

#

you can spend more time scheduling jobs then you get back running them on different processor cores at the same time

odd cipher
#

in other news; I did manage to render the world but some weird things are happening with the colors

#

not getting the correct color that is

plush portal
#

I'm making a tool to make it easy to communicate between game objects and systems. I was wondering if the syntax is awkward or not.
Here are examples of what's in there yet:

_entityProxy = new EntityProxy("Name of entity used for communication");

_monologue = _entityProxy.CreateMessage<IMessageComponentData>()
    .WithoutResponse<IMessageComponentData>();
_monologueState = _monologue.HasBeenRead();
_monologue.Send(_messageComponentData);

_dialogue = _entityProxy.CreateMessage<IMessageComponentData>()
    .ExpectingResponse<IMessageComponentData>();
_dialogueState = _dialogue.HasBeenResponded();
_response = _dialogue.GetResponse();
_dialogue.Send(_messageComponentData);
#

@opaque ledge I know you've used an Hybrid method. What do you think?

And I was thinking to make a game object with Unity events, but I'm not really sure it's a good idea.

odd cipher
#

@digital scarab Thanks for that link, it helped make this; though a problem is with getting the correct color to be set at the end cs for (int _x = 0; _x < instance.terrainSpriteSize; _x++) { for (int _y = 0; _y < instance.terrainSpriteSize; _y++) { int pixelX = (x * instance.terrainSpriteSize) + _x; int pixelY = (y * instance.terrainSpriteSize) + _y; int j = pixelX * instance.terrainTextureHeight + pixelY; colors[j] = c[_x * _y]; } }

#

"c" is the locally created color array, that I show the process of since its pretty big

#

also ill probably have to fix that instance thing because it doesnt work with Burst. instance is a reference to a script that has a couple variables and functions so

#

x and y is the location of the tile

sour ravine
#

your global array indexing looks off no, hold on. There are some index issues

lusty otter
#

If I'm understanding correctly, colors is supposed to be the output?

odd cipher
#

yes

lusty otter
#

Then you should not write it in as knowing x and y, output something to colors[j], rather you should write it as knowing j, calculate x and y in reverse, output something to colors[j]

#

In that case j would be the index your job execute passes in.

#

The job walks through your colors array once and that's it, there's no x and y loops.

odd cipher
#

no.. index is the tile

sour ravine
#

yeah this is basically a blit routine

#

your strides are off, just thinking through the loops here

odd cipher
#

blit?

sour ravine
#

old-school image copy stuff

odd cipher
#

well, I cant really think of any way to do it better, because I want the index to be the current tile its rendering

sour ravine
#

yup, that makes sense

#

is c supposed to be the size of the tile?

odd cipher
#

no, c is the color array that it picked above that code

#

which isnt really related to this

#

I just need to change the end bit to get the correct pixel from the c array, because it currently doesnt

#

its not supposed to look like that

lusty otter
#

That's the disconnect between your way of thinking vs job's way of thinking.

sour ravine
#

probably going to need some more info then. Like I mentioned, this looks like a tile copy like what you'd actually see in an actual old-school 2D console game

lusty otter
#

Job walks through your output array once, with the index of that array, you operate on it.

#

The index is the index of the array not the index of the tile.

odd cipher
#

yeah and the array is the array of tiles

#

so

#

could calling functions that arent in the struct be the cause?

sour ravine
#

that would generally cause a compiler error, so it would not be my first guess

odd cipher
#

alright

#

then the problem is def from the last part of the code, which I sent

sour ravine
#

right, like it should be along the lines of c[_x * instance.terrainSpriteSize + _y] though you mentioned c might not be the same size as the tile is

#

assuming it is, in fact, a blit

#

c is filled with some colors that you copy to the final location

odd cipher
#

c's size is 8x8

#

yeah

sour ravine
#

that is probably your issue then

lusty otter
#

Say if you have 10 tiles, are you trying to output an array of 10x8x8?

zenith wyvern
#

You're accessing x*y index from your source. What is that index supposed to be

sour ravine
#

^

zenith wyvern
#

Again, you need to actually understand how to convert a 2d index to a 1d index

#

Copy pasting is not going to help you

odd cipher
#

x and y is the position of the tile and the tile is from the 1D tile array with the index index

lusty otter
#

Because from my brief reading, it seems that you are trying to do
Let job go from 1 to 10, then I operate on each tile to generate the 8x8 for that tile

#

The right way should be
Let job go from 1 to 10x8x8, then I operate on each pixel

zenith wyvern
#

"X*Y" is a meaningless index.

sour ravine
#

that's why I've been asking for more information about the length of c and what it actually contains

#

might not be, but I'm assuming it's a sort of 'source sprite'

lusty otter
#

Yeah that's what I was saying, you are still thinking of tile index, when you should be thinking of the output array index.

sour ravine
#

you can even simplify that loop further if you're generating the tile in a local array first, just go one scan line at a time

#

hoist some terms up

odd cipher
#

so.. pretty much just make the loop for each pixel instead of tile? thats gonna mean a lot of changes to my existing code

bright sentinel
#

Optimization will often lead to code rewriting

odd cipher
#

I mean, yeah true

sour ravine
#

not exactly, just moving int pixelX = (x * instance.terrainSpriteSize) + _x; out of the loop on y, that kind of thing.

zenith wyvern
#

You can do two nested loops, one over the tiles the inner one over the pixels. Which is exactly what topher posted

sour ravine
#

compiler is probably already doing it

zenith wyvern
#

It's the most sensible way, you just need to understand how to convert the 2d to 1d tile index then the 2d to 1d pixel index.

#

If your source tiles are the same size you may not even need to "2d loop" on the pixels. Just copy then 1-1 in a normal loop.

odd cipher
sour ravine
#

was it colors[j] = c[_x * instance.terrainSpriteSize + _y];

odd cipher
#

no but close colors[j] = c[_x + instance.terrainSpriteSize * _y];

#

plus the change on this int j = pixelX + instance.terrainTextureHeight * pixelY;

sour ravine
#

excuse, that's right. I was striding on the wrong loop counter. So you actually did write a blit

odd cipher
#

well.. I mean it is faster than the version without Jobs

sour ravine
#

time for SIMD

odd cipher
#

SIMD?

sour ravine
#

reinterpret as uint4 and... probably run at the same speed since lol out of order execution

#

Same Instruction, Multiple Data

#

if you've heard of NEON or SSE, that kind of thing

odd cipher
#

no still not sure what you mean

mint iron
#

now you're just playing πŸ˜„

#

learning SIMD and Assemlby is probably a bit far

sour ravine
#

Burst will insert appropriate stuff if you use vector types. Whether or not it's clever enough to manipulate the loop and autovectorize is a good question, but LLVM is damn clever

#

you do need to worry about memory bandwidth vs. instruction dispatch

odd cipher
#

currently my Job isnt really working with burst because of this main issue Burst error BC1042: The managed class type `WorldController` is not supported. Loading from a non-readonly static field `WorldController.instance` is not supported

#

so, id have to pass those variables I use through the Job correct?

sour ravine
#

pretty much. Just copying the ints you need is a good start

bright sentinel
#

Yes, and that is very much preferred actually, instead of getting them from a static class

sour ravine
#

the Mike Acton way is to drop the class πŸ™‚

bright sentinel
#

Just doing that to enable burst will give you massive performance increases

odd cipher
#

alright, what about functions I call? do I just.. copy paste them into the struct or what

sour ravine
#

how often/when do they change

#

rather, what do they compute

odd cipher
#

actually nevermind, the one it calls is so small its fine

#

I can just move it

sour ravine
#

consider caching the result if it's the same over the entire run of the Job

#

just whack it in a field

odd cipher
#

alright, one additional problem.. one of the variables I use is a Dictionary, is it possible to pass those?

sour ravine
#

Are you sure you're not actually Mike?

#

πŸ˜„

odd cipher
#

Whos mike πŸ˜…

north bay
#

Invalids personal jesus

mint iron
#

just dont use a dictionary, use a NativeHashMap instead

sour ravine
#

the Supreme Datamaster

#

you can also do blob asset stuff, but that's a lot of work.

odd cipher
#

blob

#

ill just use a NativeHasMap

sour ravine
#

might also be able to use that in your class too

#

rather than copy it

bright sentinel
#

@sour ravine Why are you so obsessed with MActon? πŸ€”

#

Any specific video or response he gave that got you hooked?

sour ravine
#

internet comedy purposes, but real talk I do think the DOD stuff is a good way to approach compsci

odd cipher
sour ravine
#

Blobs can still work

odd cipher
#

I dont know what those are so

sour ravine
#

BlobString for equality, that kind of thing

hollow sorrel
#

invalid has a big boner for mike

sour ravine
#

ask me about Chris Avellone πŸ™‚

odd cipher
#

blobs is for ECS right?

bright sentinel
#

I'm going to regret this, but who is Chris Avellone?

sour ravine
#

Yep, for things that don't change a lot but have varying sizes and shapes

#

@bright sentinel a Very Important Writer

#

@odd cipher there are also NativeStringXX types which should be easier to work with

#

you can make them pretty easily from regular strings

odd cipher
#

alright thatll work then, but what about the Color32[] array thats in there

sour ravine
#

multimap per earlier discussion

odd cipher
#

oh I totally forgot

sour ravine
#

you can actually turn that into a NativeArray in the tile job if you want, but that's obviously going to take CPU time

#

iterate through values

#

park in the array

odd cipher
#

alright, so which NativeString do I use and how do you convert a string to it

sour ravine
#

how big are your string(s)

#

the number at the end is how many characters you can store in it

#

big strings are usually not a good idea for performance, though, so if you can use another way to identify tile groups consider cheating your way out of the problem that way

#

enums, the like

#

(I think they're value types in C# but I'm second-guessing myself)

odd cipher
#

maybe like max 16 letters

#

which isnt an option so ill just pick the lowest one 32?

sour ravine
#

yeah

#

enough to test things out and see what happens. Again, if you want to go DOTS then go DOTS. Figure out how to avoid the strings altogether

hollow sorrel
#

i think fixedstring is the replacement for nativestring now but ya it sounds like ideally you don't want to use strings here

sour ravine
#

yes, there are even format methods in there so you can generate them directly

odd cipher
#

how would I get the color32 array from a key from the multimap?

#

@sour ravine

sour ravine
#

TryGetFirstValue() -> TryGetNextValue()

#

you can probably even make an extension method if you're feeling fancy

#

put those in an array at the beginning of the job

#

you're doing repeat work at that point, but at least it's amortized per tile

#

I'm not sure if array slices would pose a problem but another strategy is to make a big list of all the Color32s for all the tile groups and then put region markers in the hash map

#

start index and length, that kind of thing

odd cipher
#

Trying to figure out how to set value array now

sour ravine
#

keep adding the elements to the map using the same key

#

you need to clear the key out first if you reset-- this is sounding like a good use case for BlobAssets but you know more about what you need the game to do

odd cipher
#

Alright, also noticed I need to pass the array of tiles as well.. and a tile is a non monobehaviour script so its gonna throw an error

sour ravine
#

as always, consider whether or not you need to actually touch that data

#

if there's just a property you need, gather it all up in reference-friendly C# land then kick off to the job system

#

pretty much what BlobAssetReference was built to do

bright sentinel
#

"Next release will also have blob assets which is made for sharable immutable resource data. In that case, you could convert a ScriptableObject into a BlobAsset and then share it from multiple instances in the same scene.

BlobAssets are made for zero cost deserialization for large amounts of data. AnimationClip, CollisionMesh, CurveData is a good example of what we think belongs into a BlobAsset." Old forum post

#

So essentially a ScriptableObject in ECS land

sour ravine
#

bingo

bright sentinel
#

I'm guessing we would also use this to store textures then?

sour ravine
#

you can recreate it as appropriate, but that construction can be expensive

odd cipher
#

Burst error BC1042: The managed class type `Tile[]` is not supported. Loading from a non-readonly static field `WorldController.tiles1D` is not supported

sour ravine
#

NativeArray would also work if you just need a big flat run of constant size stuff

#

@bright sentinel see BlobAssetBuilder

bright sentinel
#

The problem is the docs are very sparse on BlobAssets unfortunately

sour ravine
#

yes, they're mostly just a way to bundle up some structs in a way that doesn't run afoul of Burst

hollow sorrel
#

ya and they are a pain to create

odd cipher
#

dont really know what to do to fix this since Burst doesnt like my Tiles

sour ravine
#

I've built a simple database out of them, it's actually not as bad as you'd expect

#

@odd cipher it's complaining about the managed array

#

if possible, move the data you need from each Tile into a struct and return a NativeArray<> holding that

#

alternately use a NativeList<> with the Tiles directly if that can be done

#

but again, this is really, really sounding like all the hard work of using a BlobAssetBuilder and going that route

odd cipher
#

I dont think any of that is possible

sour ravine
#

what do you actually read from the Tile

#

in that job

odd cipher
#

I check the tiles neighbor etc

#

such as if (t.NeighbourCheck(x, y + 1)) neighbourName += "N";

sour ravine
#

that's a tremendously inefficient design if you're working on strings

odd cipher
#

..maybe.. buttt I want to get this working first

zenith wyvern
#

You cant create strings in burst. What are you using the strings for? And why do you need a dictionary?

odd cipher
#

well the dictionary contains all the sprites for the terrain

#

with the string name of the sprite as the key

zenith wyvern
#

Change the key from a string to an enum

#

You should never use strings for anything except debug and ui

odd cipher
#

cant use an enum because that sprite list "changes"

sour ravine
#

in the sense you have variants?

#

not a problem for enums, FWIW. You can create values with the modifiers

#

adding new modifiers is a pain, but doesn't happen too often

odd cipher
#

the game is moddable

zenith wyvern
#

What do you mean it changes? The source data for your sprites changes?

odd cipher
#

therefore the sprite list changes

#

and an enum cant change correct?

sour ravine
#

the value can't sure, but depending on gameplay mechanics it might not actually change

#

consider minecraft-- while there are mods, there are very few that fundamentally change the kinds of blocks or ways they interact

#

hence it might still be possible to make the block type an enum

#

or just an int

coarse turtle
#

or even bit flags

zenith wyvern
#

Well regardless of how you represent it outside the job, if you're passing it in to a bursted job so you need to restructure it to fit that requirement.

#

I would probably use ints as keys, use a static class of constants named appropriately to represent the keys

odd cipher
#

so theres no way to do this in the meantime without changing pretty much everything?

zenith wyvern
#

No shortcuts to performance

hollow sorrel
#

You should never use strings for anything except debug and ui
@zenith wyvern
i 100% agree but this reminded me of this other issue i was having
before DOTS i'd just do spriteAnimator.SetAnimation("fart");
i don't like using strings here but they are a lot friendlier to use than to check the animation id from the scriptableobject and do SetAnimation(5)

so was thinking of either
a) codegen an enum whenever the anim scriptableobjects change
b) do something like SetAnimation(animDict["fart"]) that returns an int
what would you do? am open to other ideas as well

sour ravine
#

zoidberg why not enums

odd cipher
#

i could start changing the strings to int but the problem itself will still exist; that I cant use Tiles in the loop

odd ridge
#

I have some old style unity cubes in my scene mixed with ECS converted cubes, both have the same material, yet they are lit differently. why? I changed the lighting settings but only the old cubes are taking my new light settings, the ECS cubes render as if they use the default unity lighting settings

odd cipher
#

@sour ravine @zenith wyvern ^^

sour ravine
#

you can, you just need a way to turn it into a flat NativeArray of structs

odd cipher
#

so, whats the point of changing the strings to ints currently? I mean sure I can do it later but I don't NEED to do it right now

sour ravine
#

strings don't work in Burst

#

and potentially generate lots of garbage

odd cipher
#

Ah crap

fallow mason
#

Kids and their fart animations grumble grumble

odd cipher
#

aandd I just accidentally erased all the stuff I did for it to semi work with Burst.. I dont think I'll be able to make it work either way because of the Tiles :<

covert raven
#

Quick question on timing when dealing with component systems. In monobehaviour when dealing with animations, we could simply have actions get triggered when a certain frame hits, in terms of ECS (specially in multiplayer NetCode server authoritative), is there a best practice for that? Should the server have a ability system that tracks time? Or should the server inject the GameObjects and trigger the same animations and wait for feedback from the monobehaviour script?

odd cipher
#

@sour ravine So, I took your advice and changed it from using the name of the terrain type to id of the terrain type and using enums instead of strings. all this made the world generation take 100MS instead of 200MS :DD

sour ravine
#

good start

#

might even be able to cut it down more with parallelism, etc.

odd cipher
#

yeah I dont remember what that is

sour ravine
#

jobs

odd cipher
#

oh right

#

yeah I am still using the semi working Job code :P

#

I do really want to use Burst though

#

since it can give huge performance boosts

zenith wyvern
#

What is it about your tiles that prevents you from using it in Burst?

odd cipher
#

due to this Burst error BC1042: The managed class type `Tile[]` is not supported. Loading from a non-readonly static field `WorldController.tiles1D` is not supported

zenith wyvern
#

So change your tile array to a NativeArray<Tile>

odd cipher
#

thats it? oh.. well then, ill try

zenith wyvern
#

Your tile also needs to be blittable, so it has to be a struct with only blittable types

odd cipher
#

well that wont really be possible with my current system

zenith wyvern
#

Then you need to decide what you're using your tiles for in your job and extract that out into a NativeArray that you pass into the job

#

With burst it's all about how to get your data into that nice linear nativearray

#

@zenith wyvern
i 100% agree but this reminded me of this other issue i was having
before DOTS i'd just do spriteAnimator.SetAnimation("fart");
i don't like using strings here but they are a lot friendlier to use than to check the animation id from the scriptableobject and do SetAnimation(5)

so was thinking of either
a) codegen an enum whenever the anim scriptableobjects change
b) do something like SetAnimation(animDict["fart"]) that returns an int
what would you do? am open to other ideas as well
@hollow sorrel

It's been a while since I've used Unity's animation system. If I remember right Unity uses strings too, but they hash them to ids anywhere they don't need to be human readable

hollow sorrel
#

oh no i'm not using unity's anim system

#

oh i didn't read the second part

#

yea i like the hashing, is simpler than codegen

zenith wyvern
#

I would avoid codegen like the plague unless you're having some kind of serious performance issue

hollow sorrel
#

would be nice to have enums tho since you can just autocomplete and see what anims there are without leaving ide

#

why would you avoid it

zenith wyvern
#

The results are fine, it's the work to get it there and what it does to your code readability that's the problem

odd cipher
#

how would you generate a random number between 0 and 2 in a Job? nothing really seems to work for me

hollow sorrel
#

ah, fair
i agree and i'll go for hashing then, ty

zenith wyvern
#

how would you generate a random number between 0 and 2 in a Job? nothing really seems to work for me
@odd cipher

Google "Unity rng in jobs" there are plenty of resources to learn from

#

The short answer is use the "Random" struct from Unity.Mathematics

#

But it's a complicated subject that requires research to get right

odd cipher
#

Yeah I tried that but it seems off.. ```cs
var random = new Unity.Mathematics.Random((uint)index + 1);
if (random.NextInt(0, 2) == 1) { }

#

it doesnt look "random"

plush portal
#

@covert raven I would've liked to help, but I don't know and am curious myself. You might want to ask on the Unity forums

zenith wyvern
#

RNGs are not meant to be dropped in place like that. They're persistent objects. You get random from repeatedly calling NextInt on the same Random

#

But since Random is value type you can't just pass it into the job and get it back out, you need to put it in a native array, or pre-generate your random numbers

#

Like I said, a complicated subject

#

The quick and dirty solution is to create your Random on the main thread, seed it with UnityEngine.Random.Range() then pass it into the job and use it throughout.

odd cipher
#

Yeah, that's pretty much all I need anyway

#

that fixed the problem, thanks!

plush portal
#

You could probably put a random in a scriptable object, make it addressable and retrieve the addressable in your job.

Just kidding, but if you are working in Hybrid ECS, you can use a MonoBehaviour to randomize your numbers and send it to the ECS world as an entity component.
When the component is read, a tag component is added to the entity that holds the component, which is found by the MonoBehaviour, who then sends a new value and removes the "used" tag.

Or you could just use my messaging tool when it's ready πŸ˜‰ πŸ˜‰

#

Talking about messaging tool, I posted that earlier, but didn't get any response yet:

I'm making a tool to make it easy to communicate between game objects and systems. I was wondering if the syntax is awkward or not.
Here are examples of what's in there yet:

// Creates a proxy using an entity.
_entityProxy = new EntityProxy("Name of entity used for communication");

// Creates a message that doesn't expect a response from any system.
_monologue = _entityProxy.CreateMessage<IMessageComponentData>()
    .WithoutResponse<IMessageComponentData>();
// Checks if the message has been read.
_monologueState = _monologue.HasBeenRead();
// Sends the message.
_monologue.Send(_messageComponentData);

// Creates a message that expects a response from a system.
_dialogue = _entityProxy.CreateMessage<IMessageComponentData>()
    .ExpectingResponse<IMessageComponentData>();
// Checks if the message has been responded.
_dialogueState = _dialogue.HasBeenResponded();
// Gets the response from a system.
_response = _dialogue.GetResponse();
// Sends the message.
_dialogue.Send(_messageComponentData);
#

That's only the code MonoBehaviours can use. I'm not finished with the part where a system can retrieve the message.
Is the syntax easily understandable, or is it awkward?

hollow sorrel
#

how are you making dialogue get a response before its sent?

#

also maybe you could omit the withoutresponse part if its only with or without
if expectingresponse is not included then without is implied right

plush portal
#

It's just a list of all the things you can do right now, not necessarly in order.

hollow sorrel
#

ah i see

plush portal
#

And usually in an update I would check if a response was received at the beginning of the update. And if I also send a message in the same update function, I would put it after, so it doesn't override the last message before it is received.

#

I don't know if I should've made it so it would work fine if there was two of the same message, but that would mean I would have to either create and delete entities, or make a pool or something. Which I thought would get messy for no reason.
But if you think it would be better that way, I might change my mind on that.

plush portal
#

@hollow sorrel And for the WithoutResponse thing, if I omitted it, that would mean I could do .ExpectingResponse on the monologue whenever I want, and I thought that would be awkward.
But maybe it wouldn't be that awkward.
I mean we can basically do Entities.WithBurst().ForEach().WithBurst().WithoutBurst().Run() and it still works, but I find that weird myself.
Or I could do _proxy.Message().ExpectingResponse().Create() and _proxy.Message().Create(), but I don't know if that's also weird or not.

odd cipher
#

@zenith wyvern Hey, hope I'm not annoying you but I'd like to thank you for helping me a lot with this even though I had no idea what I was doing. I would ping InvalidPointer aswell but they are offline so I don't really wanna ping them.

zenith wyvern
#

No worries, happy to help

opaque ledge
#

@plush portal i never tried to implement hybrid event system πŸ˜„ i know Tertle did some ECS events using native containers you might want to check them out

#

as for your syntax, it seems cool

low tangle
#

you missed initing the random is why its not random

#
var r = new Unity.Mathematics.Random();
r.InitState();```
bright sentinel
#

So are there any cases where you don't want it initialized?

surreal grail
#

hello! I have a question, somebody told me a while ago that allocating and writing to a NativeArray more than 12mb in size in a burstjob would crash the stack or something, but it appears it doesn't (in fact my array I'm testing it with is 500mb+), why is this the case?

#

ahh so is it because I use Allocator.Persistent which allocates to the heap?

opaque ledge
#

i think in their documentation it says its basically malloc function if you use persistent

surreal grail
#

yes it appears so, thank you!

#

oh so I know what the misunderstanding was, I said that I was going to use the array as a temporary one, but it actually gets re-used millions of times

opaque ledge
#

i am getting this weird error:

Burst error BC0101: Unexpected error while processing function `TradeFleetAvoidEnemeyAITagRequest.<>c__DisplayClass_TradeFleetAvoidEnemyRequest.OriginalLambdaBody(TradeFleetAvoidEnemeyAITagRequest.<>c__DisplayClass_TradeFleetAvoidEnemyRequest* this, Unity.Entities.Entity entity, ref Unity.Entities.DynamicBuffer`1<AITagRequestBuffer> requests, ref TradeFleetAvoidEnemeyStateData state, ref Unity.Entities.DynamicBuffer`1<RaycastResult> results)`: System.ArgumentNullException: Value cannot be null.
Parameter name: key
  at System.Collections.Generic.Dictionary`2[TKey,TValue].FindEntry (TKey key) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 
  at System.Collections.Generic.Dictionary`2[TKey,TValue].TryGetValue (TKey key, TValue& value) [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 
  at Burst.Compiler.IL.Syntax.ILBuilder.CreateBasicBlockForInstruction (Mono.Cecil.Cil.Instruction inst, System.Boolean isEntry) [0x00000] in <d44e69c6e62c40a48187c633e22e4133>:0 
  at Burst.Compiler.IL.Syntax.ILBuilder.PrepareFunction () [0x001fc] in <d44e69c6e62c40a48187c633e22e4133>:0 
  at Burst.Compiler.IL.Syntax.ILBuilder.ProcessFunctionBody () [0x00084] in <d44e69c6e62c40a48187c633e22e4133>:0 
  at Burst.Compiler.IL.Syntax.ILBuilder.CreateFunctionFromRef (Burst.Compiler.IL.Syntax.ILFunctionReference funcRef) [0x000fa] in <d44e69c6e62c40a48187c633e22e4133>:0 
  at Burst.Compiler.IL.Syntax.ILBuilder.VisitPendingFunctionReferences () [0x000b2] in <d44e69c6e62c40a48187c633e22e4133>:0 

And this error repeating:

nvalidProgramException: Invalid IL code in TradeFleetAvoidEnemeyAITagRequest/<>c__DisplayClass_TradeFleetAvoidEnemyRequest:OriginalLambdaBody (Unity.Entities.Entity,Unity.Entities.DynamicBuffer`1<AITagRequestBuffer>&,TradeFleetAvoidEnemeyStateData&,Unity.Entities.DynamicBuffer`1<RaycastResult>&): IL_004b: br.s      IL_ffffffdf
#

This error happens at this

var relation = Shared_Cooperations.GetRelation(ownerData, targetOwnerData);

function is:

    public static CooperationRelationValue GetRelation(Guid host, Guid target)
    {
        if (host == target) return CooperationRelationValue.Ally;
        var relation = relations.Data;
        var enumarator = relation.GetValuesForKey(host);
        
        while (enumarator.MoveNext())
        {
            var data = enumarator.Current;
            if (data.Equals(target)) return data.relation;
        }

        return CooperationRelationValue.None;
    }
#

relations.Data is shared static

#

The thing is i am using this function at 2 seperate places, one for pirate AI one for trade fleet AI, pirate one doesnt give me any errors and works properly, trade fleet one doesnt

#

it works if i do WithoutBurst

#

oh this only started to happen after i upgraded to 2020.1b

opaque ledge
#

it works now 🀷

fallow mason
#

@loud matrix This is what I was referring to when I recommended statics: ```using Unity.Entities;
using Unity.Transforms;

public static class MyGameArchetypes
{

public static EntityArchetype PlayerArchetype => World.DefaultGameObjectInjectionWorld.EntityManager.CreateArchetype(new ComponentType[] {
    typeof(Translation),
    typeof(Rotation),
    typeof(Player)
});

public static EntityArchetype EnemyArchetype => World.DefaultGameObjectInjectionWorld.EntityManager.CreateArchetype(new ComponentType[] {
    typeof(Translation),
    typeof(Rotation),
    typeof(Enemy)
});

}```

#

public class EntitySpawnerSystem : SystemBase
{
    protected override void OnCreate()
    {
        World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntity(MyGameArchetypes.PlayerArchetype);
        for(int i = 0; i < 50; i++)
        {
            World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntity(MyGameArchetypes.EnemyArchetype);
        }
    }

    protected override void OnUpdate() { }

}```
#

I don't think you'd run into the issues with fast reloading/assembly that Rett described because the statics are stateless and don't need to be initialized. Wouldn't be the same case if you needed to create the archetype definition at runtime however.

#

@worldly pulsar correct me if I'm wrong

opaque ledge
#

Entities 0.8 is up πŸ‘€

#
## [0.8.0] - 2020-03-13

### Added

* Added missing dynamic component version API: `ArchetypeChunk.GetComponentVersion(ArchetypeChunkComponentTypeDynamic)`
* Added missing dynamic component has API: `ArchetypeChunk.Has(ArchetypeChunkComponentTypeDynamic)`
* `EntityArchetype` didn't expose whether it was Prefab or not. Added bool `EntityArchetype.Prefab`. This is needed for meta entity queries, because meta entity queries don't avoid Prefabs.
* Added Build Configurations and Build Pipelines for Linux
* LiveLink now gives an error if a LiveLink player attempts to connect to the wrong Editor, and advises the user on how to correct this.

### Changed

* Optimized `ArchetypeChunkComponentTypeDynamic` memory layout. 48->40 bytes.
* LiveLink: Editor no longer freezes when sending LiveLink assets to a LiveLinked player.
* LiveLink: No longer includes every Asset from builtin_extra to depend on a single Asset, and sends only what is used. This massively speeds up the first-time LiveLink to a Player.
* Upgraded Burst to fix multiple issues and introduced native debugging feature.

### Deprecated

* Types that implement `IJobForEach` interfaces have been deprecated.  Use `IJobChunk` and `Entities.ForEach` for these jobs.

### Fixed

* Fixed LiveLinking with SubScene Sections indices that were not contiguous (0, 1, 2..). Now works with whatever index you use.
* Fixed warning when live converting disabled GameObjects.
* Allow usage of `Entities.WithReadOnly`, `Entities.WithDeallocateOnJobCompletion`, `Entities.WithNativeDisableContainerSafetyRestriction`, and `Entities.WithNativeDisableParallelForRestriction` on types that contain valid NativeContainers.
coarse turtle
#

o wow that was fast

#

hmm what's a dynamic chunk component?

opaque ledge
#

no idea πŸ˜„

#

probably something related to IJobChunk

#

also F for IJobForEach, he will be remembered πŸ‡«

safe lintel
#

Wait hold up ijobforeach deprecated? 😩

autumn sleet
#

@safe lintel welcome to the club buddy

coarse turtle
#

hmm I guess it's not too difficult to switch IJobForEach to the fluent API - well I should go change that sometime soon in my stuff

autumn sleet
#

The lambda stuff is confusing + adds extra time to compile because of codegen

#

Imo

north bay
#

I love it, it hides so much boilerplate

safe lintel
#

I quite liked the format of ijobforeach, switching is a hassle but not my main source of contention

coarse turtle
#

im lazy - so I didnt wanna change it when I had the chance lool

autumn sleet
#

Well with IJobForeach you can follow solid, now your Update method is a bunch of logic

#

With anonymous methods in it

#

Even lets say if you do not inline it - you pay method call cost because Mono never inlines aggressively

opaque ledge
#

For collections 0.7

# [0.7.0] - 2020-03-13

### Added

 * Added ability to dispose NativeKeyValueArrays from job (DisposeJob).
 * Added `NativeQueue<T>.ToArray` to copy a native queue to an array efficiently

### Changed

 * Upgraded Burst to fix multiple issues and introduced a native debugging feature.

### Deprecated

 * Deprecated `Length` property from `NativeHashMap`, `UnsafeHashMap`, `NativeMultiHashMap`,
   `UnsafeMultiHashMap`, `NativeQueue`, and replaced it with `Count()` to reflect that there
   is computation being done.

### Removed

* Removed expired API `CollectionHelper.CeilPow2()`
* Removed expired API `CollectionHelper.lzcnt()`
* Removed expired API `struct ResizableArray64Byte<T>`

### Fixed

* Removed code that made `NativeStream` incompatible with Burst.
#

Hybrid Renderer 0.4

### Added (All Versions)

* HeapAllocator: Offset allocator for sub-allocating resources such as NativeArrays or ComputeBuffers.

### Added (Hybrid V2)

Hybrid Renderer V2 is a new experimental renderer. It has a significantly higher performance and better feature set compared to the existing hybrid renderer. However, it is not yet confirmed to work on all platforms. To enable Hybrid Renderer V2, use the `ENABLE_HYBRID_RENDERER_V2` define in the Project Settings.

* HybridHDRPSamples Project for sample Scenes, unit tests and graphics tests.
* HybridURPSamples Project for sample Scenes, unit tests and graphics tests.
* MaterialOverride component: User friendly way to configure material overrides for shader properties.
* MaterialOverrideAsset: MaterialOverride asset for configuring general material overrides tied to a shader.
* SparseUploader: Delta update ECS data on GPU ComputeBuffer.
* Support for Unity built-in material properties: See BuiltinMaterialProperties directory for all IComponentData structs.
* Support for HDRP material properties: See HDRPMaterialProperties directory for all IComponentData structs.
* Support for URP material properties: See URPMaterialProperties directory for all IComponentData structs.
* New API (2020.1) to directly write to ComputeBuffer from parallel Burst jobs.
* New API (2020.1) to render Hybrid V2 batches though optimized SRP Batcher backend.
#
### Changes (Hybrid V2)

* Full rewrite of RenderMeshSystemV2 and InstancedRenderMeshBatchGroup. New code is located at `HybridV2RenderSystem.cs`.
* Partial rewrite of culling. Now all culling code is located at `HybridV2Culling.cs`.
* Hybrid Renderer and culling no longer use hash maps or IJobNativeMultiHashMapVisitKeyMutableValue jobs. Chunk components and chunk/forEach jobs are used instead.
* Batch setup and update now runs in parallel Burst jobs. Huge performance benefit.
* GPU persistent data model. ComputeBuffer to store persistent data on GPU side. Use `chunk.DidChange<T>` to delta update only changed data. Huge performance benefit.
* Per-instance shader constants are no longer setup to constant buffers for each viewport. This makes HDRP script main thread cost significantly smaller and saves significant amount of CPU time in render thread.

### Fixed

* Fixed culling issues (disappearing entities) 8000+ meters away from origin.
* Fixes to solve chunk fragmentation issues with ChunkWorldRenderBounds and other chunk components. Some changes were already included in 0.3.4 package, but not documented.
* Removed unnecessary reference to Unity.RenderPipelines.HighDefinition.Runtime from asmdef.
* Fixed uninitialized data issues causing flickering on some graphics backends (2020.1). 

### Misc

* Highlighting `RenderBounds` component change introduced in `0.3.4-preview.24` which was not part of the previous changelogs, see below.
safe lintel
#

🀩 hybrid v2 soothes the pain of losing ijobforeach

bright sentinel
#

Is there a reason IJobForEach is removed?

#

Is it just a case of always wanting to do IJobChunk instead?

opaque ledge
#

Well basically ForEach lambda and IJobForEach is doing the same, they decided to support the lambda way

bright sentinel
#

But isn't the lambda generating a job?

sour ravine
#

wait, ComputeBuffer write from job

#

as a graphics programmer YEEEEES

#

the dark ascent begins

#

that's yuuuge

opaque ledge
#

Techincally yeah Bmandk

#

enjoy InvalidPointer πŸ˜„ i simply dont know whats going on with hybrid renderer

#

is it beneficitial to us peasants ?

scarlet inlet
#

some coders are put off by boilerplate code, so it makes sense to not promote IJobForEach, especially after all the work they have done to optimize ForEach. However I find the pattern still awkward when you need to iterate over entitites of separate archetypes

opaque ledge
#

i see many "huge performance increase" so there must be πŸ˜„

sour ravine
#

@opaque ledge you can do whole categories of efficient algorithm now

#

clustered shading on CPU, etc.

#

GPUs can choke on cluster construction a bit while CPUs have no issue

bright sentinel
#

I'm just wondering if there was ever a reason to use IJobForEach over IJobChunk

sour ravine
#

ForEach eats components, Chunk eats ArchetypeChunks

opaque ledge
#

yeah basically πŸ˜„

#

but i am on the same boat, i never used IJobForChunk, i always used ForEach

remote coyote
#

Hyped for Hybrid V2, this looks very promising!

sour ravine
#

this is cool since you can do really bonkers instanced rendering, etc.

#

probably where the perf benefits come from

scarlet inlet
#

IJobChunk is less intuitive for sure

bright sentinel
#

But I mean, deprecation of IJobForEach means that it's going away at some point. That would mean that Entities.ForEach() would be invalidated (which is obviously not happening)

vagrant surge
#

ijobchunk is crazy useful tho

#

being able to move some branching to the per-chunk level is great

bright sentinel
#

So I'm just wondering if the lambda uses an IJobChunk or IJobForEach underneath

sour ravine
#

@bright sentinel the struct approach is being deprecated in favor of the lambda

opaque ledge
#

Yes, IJobChunk is used when you do ForEach

scarlet inlet
#

I wouldn't be surprised if the code is similar to what IJobChunk does

bright sentinel
#

Thanks @opaque ledge

opaque ledge
#

IJobChunk can be more efficient because you can access the chunk data as how its laid out in memory, at least thats what their doc says

bright sentinel
#

Yeah, so I doubt the lambda uses IJobForEach, considering the lambda will always work on chunks of archetypes

sour ravine
#

any ForEach can be written from/in a Chunk

#

it isn't a functionality thing, just boilerplate removal

#

common use case, etc.

opaque ledge
#

dont forget to add "ENABLE_HYBRID_RENDERER_V2" in project settings for new hybrid renderer btw

scarlet inlet
#

@opaque ledge I have used them only once but with ArchetypeChunk is easier to iterate over archetypes of different entities

coarse turtle
#

speaking of the lambda foreach...anyone have an idea of how to pass a ptr to the foreach statement?

scarlet inlet
#

less intuitive, but less awkward too

opaque ledge
#

you dont pass anything to ForEach lambda, you have to capture it locally

sour ravine
#

yeah was gonna say p sure it's a regular capture

coarse turtle
#

cool - I think I had an error statement saying I had to use a function like CaptureVariable... or something like that before - but I'll check again - haven't touched it in a week

sour ravine
#

you might need to assign it to a local as a hack or something

coarse turtle
#

ah - alright I'll give it a try later today

loud matrix
#

@fallow mason Thanks, I got it working but that's a cleaner way of doing it, I was using a constructor class to make a single instance of the Entity Manager

amber flicker
#

wooo hrv2!

round summit
#

How should i disable gravity on spesific rigidbodies?

opaque pilot
opaque ledge
#

hmm, when i activate v2 it gives me an error in package, i guess i have to stick with old one 😦

opaque pilot
#

Also not sure why planetEntities need to be read only (error given by the runtime) Is it because it is the entity that has the trigger component?

bright sentinel
#

@opaque ledge Are you on 2020.1?

opaque ledge
#

yeah

bright sentinel
#

Β―_(ツ)_/Β―

opaque ledge
#

πŸ˜„

remote coyote
#

how stable is 2020.1 for people now? I've been holding off on upgrading to it, and will probably wait a little longer yet

opaque ledge
#

@opaque pilot i think you need to do trigger events BEFORE EndFramePhysics and AFTER StepPhysics

#

i keep getting some weird ass error in 2020.1 πŸ˜’

#

so wait a while πŸ˜„

mystic mountain
#

go for f:s x)

coarse turtle
#

meanwhile I just downloaded it and abt to jump to it πŸ‘€

loud matrix
#

I'm getting a tonne of errors in 2019.3.4 so I'm trying out 2020

#

Installed physics package and everything decided it wasn't compatible, and it refuses to let me downgrade

opaque ledge
#

@opaque pilot you also probably want to readonly both components and pass "true" to GetComponentDataFromEntity

opaque pilot
#

@opaque ledge Ah, really? I'm partially copying the Unity example

#

Is there a reason for it need to be read only:?

junior fjord
#

lol a new entities package again