#archived-dots

1 messages ยท Page 281 of 1

hot basin
#

I think it would be simpler because you have only one job

#

so less code to maintain

solemn hollow
#

i stay away from generalization if i can. but if i want complete freedom for my designer i often have to use generic stuff

hot basin
#

but I wonder about performance of such solution

solemn hollow
#

performance is the same

rose warren
#

I think dots is associated with jobs so ill post this here :

So I am working on a script to cut objects, It worked fine but the program doesnt handle high poly meshes well. So i started to try parallel jobs with burst.
Now the problem is that each time I add a triangle or vertex I must check if they already exist in the upper or lower half array. This is so that i dont add it and I find its corresponding index for the index list.
Now each thread is independent of the other, and will be adding to their own lists.
How on earth do I now make a mesh whilst being unable to have each thread read and effect the same data?

hot basin
#

I think dots is associated with jobs so ill post this here : it is, Jobs are considered a part of DOTS

solemn hollow
#

if you really want full parrellelism you could maybe generate multiple submeshes. one on each thread and stich them together?

hot basin
hot basin
solemn hollow
#

โค๏ธ catlikecoding

hot basin
#

yeah, he has good tutorial, I was learning SRP from there way back when it was a new thing ๐Ÿ˜„

rose warren
rose warren
solemn hollow
#

anyone got some whacky physics behaviour when game is started with subscenes in edit mode? my raycasts dont hit anything then. if i dont have them in edit mode everything works fine.

rotund token
#

Because netcode just explodes

solemn hollow
#

but shouldnt it just run through conversion then? whats the thing that can go wrong here?

#

is the old not newly converted subscene used instead?

rotund token
#

Do you have live conversion on?

solemn hollow
#

yes

#

authoring state in scene view

#

and its inconsistent.. now i restarted unity and everything is fine again.

hot basin
#

should I watch on something to get my generalised jobs be busted in a good way?

solemn hollow
#

its rather embarrassing to admit but i wasted the complete day just figuring out some basic raycasting...

solemn hollow
hot basin
#

can I somehow get data lenght from within IJobParallelFor or should I make a field for that?

solemn hollow
#

do you mean for looping or do you need it for sth else?

#

btw you should use IJobFor.ScheduleParallel()

hot basin
#

IJobParallelFor is obsolete?

solemn hollow
#

yes thats the old version

hot basin
solemn hollow
#

then i think you need to pass it

hot basin
#

ok thanks

rose warren
#

can i share a list/array between threads in unity jobs ?
or must they be completely independent

hot basin
#

latter one

solemn hollow
#

well technically you can share with [DisableNativeParallelForRestriction]. but then youd need to make sure to not produce raceconditions

hot basin
#

you can always have [ReadOnly] that is shared, writing is problematic

rose warren
#

So with my code, i only need to add to the end of a list, i dont need to insert anywhere else.
would this be problematic.
(need to add a vert array, but cant have any dupes)
Im so sorry for all these questions, not much time left and havent ever touched jobs

hot basin
#

you can use NativeList.ParallelWriter for that afaik

gusty comet
#

I haven't deved anything unity in a couple years. That being said...

  • Is it any easier to animate entities?
  • Is there a DOTS-capable SkinnedMeshRenderer or something similar?
hot basin
#

but it wouldn't be sorted

rose warren
hot basin
rose warren
gusty comet
#

I also remember a while back it mattered if you used the alpha/beta version of unity for anything related to DOTS - is that still the case?

hot basin
solemn hollow
#

well version matters yes but you dont need alpha/beta anymore

hot basin
#
- Unity 2021.3.4+
- Unity 2020.3.30+```
rose warren
# hot basin you can use `NativeList.ParallelWriter` for that afaik

So I see that nativelist.parallelwriter uses the unsafelist, but the unsafelist then also has a unsafelist.parallelwriter.
What is the difference between them ?

I also noted that these lists cant/dont seem to be able to be resized.
I have no idea how large these lists are as I could need to store a pinky upto a whole body of verts

hot basin
#

Then use best thing ever I found: NativeStream

#

I use it everywhere I don't know lenght of the data

rose warren
dapper arch
#

i started learning ECS so I could have about 300+ enemies in a horde sort of game, but after looking into it i'm getting comparable fps with just normal gameobjects, when it comes to around 300 units does it make a difference what you use or have I perhaps just done something wrong

solemn hollow
#

id say 300 is enough to see benefits. especially if everything is bursted

hot basin
#

it depends on many variables, your enemies could be just light overall

#

and moving your code to ECS doesn't change much

dapper arch
#

oh right okay, i haven't tried that burst compiler thing yet

solemn hollow
#

and do you go wide with your jobs? like 300AIs in parallel should be quite a lot more performant than the GameObject implementation

dapper arch
#

i dont really know what that means to go wide or parallel, i have just tested 300 basic AI enemies

hot basin
#

yeah, so it seems you just moved your code to ECS without rewriting it to be parallel

#

that's why you don't see any improvements in performance

dapper arch
#

ah right okay i will research this more tomorrow thanks

robust scaffold
#

If it's rendering, hybrid isnt in a good state right now but in the future (2022 LTS probably), the new hybrid rendering system promises a lot, and delivers quite a bit even now in alpha.

hot basin
#

is there any build-in sort for NativeArray?

robust scaffold
#

It's not the best due to it's flexability

#

but it works for all sorts of cases, heh

hot basin
#

can I use it inside a job?

rotund token
#

anyone know off the top of their heads if possible and how to invoke an unmanaged function pointer within burst?

hot basin
#

I know it's possible

#

can't you just do it?

#

in unsafe context?

rotund token
#

i thought i could use Marshal.GetDelegateForFunctionPointer
but burst isn't liking it
ok it's because it's returning a struct

robust scaffold
solemn hollow
#

what are you implementing with it?

hot basin
#

UtilityAI XD

#

wtf? ISystem doesn't support ECBS?

solemn hollow
#

u sure you need that right now?^^ is it that performance critical? 1.0 hopefully has support for it. until then i wont need that performance

rotund token
#

you can't use managed code in ISystem

solemn hollow
#

hm k. why did unity not do it then :S

rotund token
#

because the way i'm doing it is gross

#

that said, i'm not certain 1.0 will even support it

#

unless they rewrite it as an ISystem

solemn hollow
#

it cant be that hard to rewrite as an Isystem can it?

hot basin
#

but ECB can be used within ISystem?

rotund token
#

yes

rotund token
hot basin
#

ok, then I misread previously

rotund token
#

but you make a good point manarz, maybe i just write an ISystem version where I skip debugging

#

probably better than this memory hack i'm doing

#

pinning the buffer system

#

and creating pointers to the methods

solemn hollow
#

and while you are at it look at DreamingImLatios optimizations for them

hot basin
#

is ISystem a huge improvement in performance?

solemn hollow
#

well all code in ISystem can be bursted.

hot basin
#

most of my SystemBase systems are just scheduling so I don't see much to be improved

rotund token
#

never mind

#

EntityCommandBuffer isn't unmanaged while ENABLE_UNITY_COLLECTIONS_CHECKS

robust scaffold
hot basin
#

so probably will never use it XD

solemn hollow
#

also you need to call all the gethandles which are then bursted too right?

robust scaffold
solemn hollow
#

yes but the handle.Update function still might be bursted. havent digged deep into the code though

#

honestly i expect like a 30% speedup. if not im disappointed ^^. since they said they want to get the overhead of systems so low that even with 1 entity its as fast as with 1 gameobject

robust scaffold
#

It is, it's intended for use in ISystems. If you notice you can squeeze out a bit more performance, you can do that. Using ForEach code gens the caching of the handles at creation anyways.

solemn hollow
#

i do have massive amounts of small generic systems. will be fun to update them. ill get alot of performance but im not sure i can do it without managed types

viral sonnet
#

yeah, I don't know why no ECBs exists as ISystem. I think I'll just write one. It doesn't like like there's any showstoppers

rustic rain
#

Does Unity have any sort of unmanaged graph types?

viral sonnet
robust scaffold
viral sonnet
#

pretty much any code that interacts with NativeContainers sees huge improvements. Just getting component type handles and scheduling doesn't gain much

rustic rain
#

and where I can put number between 0 and 1

#

and get value according to graph

rotund token
#

i just wrote the whole thing in 7 min

#

except i had to remove buffer support

viral sonnet
#

oh cool! can you share? why are buffers not working?

rotund token
#

the problem is safety doesn't work

#

i can't store command buffers in an unmanaged ISystem implementation

#

because command buffers have safety

#

(dispose sentinel etc)

viral sonnet
#

ohhh snap

rotund token
#

and if i turn off safety on the command buffer

#

then i can't create buffers because the constructor needs to be able to pass in safety info

#

while ENABLE_UNITY_COLLECTIONS_CHECKS is active in the editor

#

so yeah, this basically needs the collections update without dispose sentinels

viral sonnet
#

i'm pretty sure you can confuse it with another safety struct

solemn hollow
rotund token
#

i probably could but at the stage of taking more than 10min i no longer have the effort

viral sonnet
#

post what you have and i can take a stab at it

rustic rain
#

I need it inside of bursted code

#

somehow...

rotund token
viral sonnet
#

haha

rotund token
#

literally just copy ecb into your own copy

#

and find&replace ENABLE_UNITY_COLLECTIONS_CHECKS with anything

solemn hollow
solemn hollow
#

so just copy the keyframearray to a struct

rotund token
hot basin
#

yeah XD

#

sry

rotund token
#

hmm i think i have a better way of doing this

hot basin
#

Can I open stream to writing at same index than before?

#

in NativeStream

solemn hollow
#

cant you create a fake safety handle? Like the NullObject pattern?

solemn hollow
hot basin
#

bummer

viral sonnet
#

yeah, haven't realized EntityCommandBuffer is also a NativeContainer. eh, not worth the effort haha

hot basin
#

if ISystem is bursted can I schedule jobs from it?

hot basin
#

so can I schedule jobs from other jobs? ๐Ÿ˜„

solemn hollow
#

are there other problems with Isystem right now or is it just the ECBS thing?

solemn hollow
viral sonnet
hot basin
#

oh I get it... is ISystem bursted but not in parallel?

viral sonnet
solemn hollow
viral sonnet
#

ISystem is not a job. it's the equivalent of SystemBase but as struct and unmanaged memory which can be bursted

hot basin
#

๐Ÿ‘Œ

viral sonnet
#

EntityCommandBuffer has been weirdly implemented. so much setup and code is in the NativeContainer space.

#

if it was implemented better we could just use EntityCommandBufferData

hot basin
rotund token
#

wait i've just realized you can't even create an ECB inside burst

#

i thought that was supported

#

i actually had this working apart from that minor detail >_>

solemn hollow
rotund token
#
void ISystem.OnUpdate(ref SystemState state)
{
    var test = new EntityCommandBuffer(Allocator.TempJob);```
this alone fails burst compiling
solemn hollow
#

and its the creation only? ecb itself is unmanaged?

rotund token
#

it's this pesky field atm

#

private static int ms_CommandBufferIDAllocator = 0;

#

can't use static non-readonly fields in burst

solemn hollow
#

you could have a managed system that passes EBS to Isystems :S

#

ah damn

rotund token
#

enzi is right about this

if it was implemented better we could just use EntityCommandBufferData

#
{
    EntityCommandBufferData* data = ecb.m_Data;```
#

literally just does that but i'd have to rewrite chunks of this to make it not use ECB and just use EntityCommandBufferData

#

that i cbf with

#

just change UnsafeListPtr to an UnsafeList and fix up write backs

#

alternatively just need a re-usable ECB

viral sonnet
#

thanks but we'd have to write much much more than just the ISystem

#

how would I create an entityQuery in a performance test? can I even use entities inside a performance test? ๐Ÿ™‚

rotund token
#

this above works

#

it compiles fine

#

i think easiest approach would just to make it so ECB can be re-used

#

then you create it in OnCreate

viral sonnet
#

ok cool! thanks then

rustic rain
#

what's the purpose of this whole ISystem?

#

only perfomance?

viral sonnet
#

yeah, enough reason ๐Ÿ˜„

solemn hollow
#

@rotund token did you profile it? how much faster was it

rotund token
#

ISystem over SystemBase?

#

it can be significant if you have a lot of queries and dependencies

solemn hollow
#

i meant specifically your ecbs

rotund token
#

i can't use it in a burst ISystem

#

because i can't create an ECB

#

and it does the exact same playback so i'd expect no different

solemn hollow
#

ah sry i thought you had an ugly hack somehow with your functionpointers ^^

rotund token
#

got it working

#

void ISystem.OnCreate(ref SystemState state)
{
    var ecbs = state.WorldUnmanaged.GetExistingUnmanagedSystem<UnmanagedEntityCommandBufferSystem>();
    this.commandBufferPtr = ecbs.Struct.CreateCommandBuffer(ref state);
}

[BurstCompile]
void ISystem.OnUpdate(ref SystemState state)
{
    var buffer = UnsafeUtility.AsRef<EntityCommandBuffer>(this.commandBufferPtr);

    buffer.CreateEntity();

    var ecbs = state.WorldUnmanaged.GetExistingUnmanagedSystem<UnmanagedEntityCommandBufferSystem>();
    ecbs.Struct.AddJobHandleForProducer(state.Dependency);
}```
#

basically do it the same way i do my event system 2.0

viral sonnet
#

noice!

rotund token
#

UnmanagedEntityCommandBufferSystem itself isn't burst compiled

#

but anything that uses it can be

solemn hollow
#

now id like to have just one of those UnmanagedEntityCommandBufferSystems where i could get pointers to a new ecb which i could then playback at any other ECBS. more like a ECBProviderSystem than an ECBS itself

#

not sure if thats possible but then youd not have to have multiples of this system for every syncpoint

rotund token
#

i only intend to implement one

#

i only ever use 2 max ecbs in a project (either endsimulation or beginpresentation and end initialization)

#

but i can live without end init as it's so rarely used

solemn hollow
#

hm i need two. cause i always make changes in one and destroy in the other.

#

so i dont have to care whether or not i give the destroycommand in order

rotund token
#

oh that's fair

#

but i won't be destroying anything in here

#

but yeah

#

copy paste

#

๐Ÿ˜„

#

managed to add all the ECB safety and logging back as well

#

think i'll leave it there

#

happy

solemn hollow
#

nice!

rotund token
#

(well not hard since the UnmanagedEntityCommandBufferSystems isn't burst compiled so it's just the same)

solemn hollow
#

you post it to your repo?

rotund token
#

yes but my repo is private ๐Ÿ˜›

#

you'll need some stuff

solemn hollow
#

ooh no fuck that xD

#

im afraid of importing too many things i dont know how to fix myself if an update breaks it ^^

#

thought that is a uninvasive upgrade ^^

rotund token
#

oh yeah i was going to release my core library

#

maybe tonight

solemn hollow
#

the only third party package in dots i use a little is your eventsystem

#

for ui

solemn hollow
viral sonnet
#

if you google for VS bugs this is the default: Sorry, i can _not_ reproduce it. Yesterday, i wasn't able to get around that problem. Today, it just works.

rotund token
#

without modifying it at all

#

and just adding a bunch of extensions etc that you can use

solemn hollow
#

yes but i somehow expect those extensions to be super lowlevel ๐Ÿ™‚

rotund token
#

not really, very few of the outward facing extensions require low level knowledge and nearly nothing requires unsafe

#

List.AddNative
NativeArray.Set
Aabb.Shrink
AABB.Encapsulate

#

x100

solemn hollow
#

well ill use it if that means i can get full support for Isystem already ๐Ÿ™‚

rotund token
#

yeah i'm kind of torn on this UECBS

#

because the rule of this library was no systems

viral sonnet
#

I don't get why Unity hasn't provided yet

#

sometimes I get the feel they have like 3 people on dots ...

#

it's not that they didn't have the time to get an unmanaged ecbs up and running

rotund token
#

who says it's not done?

#

the entities we use was branched over 9 months again from their master

viral sonnet
#

i say that, because when it would be already done, it's even worse ๐Ÿ˜„

#

but eh, I'll be whining at least till december and then we have 1.0 ๐Ÿ˜„

solemn hollow
rotund token
#

oh the only thing you need is UnsafeListPtr

#

which is just a ptr wrapper for usnafelist

#

can replace it and just write back

#

(basically nativelist without safety)

solemn hollow
#

i see. but since i have 0 experience with pointers id prefer to get it from your core lib. at some point i need to learn it but atm there is so much else to do

viral sonnet
#

it's unbelievable. i profile in VS. works fine 2 times, now I get "an error occured getting source file information" and there's literally just 1 post on the internet with it

solemn hollow
#

maybe u need to use bing to find it ๐Ÿ˜„

viral sonnet
#

good one, bing is not even able to find this one thread ๐Ÿ˜„

rotund token
#

that's weird

#

i get 1 result on google and pages of results on bing

#

maybe i should switch

#

(that said, the bing results seem mostly unrelated >_>)

viral sonnet
#

exactly ^^

viral sonnet
#

why dis so expensive?

#

pointer to an IComp with blobAssetReference

#

Either this completely destroys locality or I dunno

rustic rain
#

Hmmm, so turns out I can put Graph data into blob

#

But how can I evaluate value from raw keys? hmm

#

All right, found some ready solution xD

rustic rain
#

bbbrrrruuuuuuuh

#

polymorph structs doesn't support blobs

solemn hollow
# rustic rain But how can I evaluate value from raw keys? hmm

how i do it is to not even use the keys. i set the keys only to have a visual representation of my curve in the editor. then i only write the parameters that i use to draw the curve to the blob. at runtime i evaluate the mathematical formula and dont interpolate between keyframes.

rustic rain
#

ahem

#

how is it even possible to create math formula from graph during authoring?

solemn hollow
#

by creating the graph with the formula itself in the first place

rustic rain
#

so just function pointer with extra steps xD

solemn hollow
#

thats how a consideration looks in authoring

rustic rain
#

I assume you just predefined curves?

solemn hollow
#

MKBC are the parameters like dave mark uses them in IAUAI

solemn hollow
#

and then whenever i change a value i create a new kayframearray based on that curvefunction just to display the curve in editor

#

but i dont need to use those keyframes at runtime

#
public struct ResponseCurveParameters
{
    public ResponseCurveType curveType;
    public float m;
    public float k;
    public float b;
    public float c;
}```
#

thats all data i need

late mural
#

when you are dealing with a blob asset store thingy in a mono behaviour, do you need to dispose of it in onDisable()?

#

im tryna debug a few errors, which appear to have something to do with a blob thingy

#

blob asset reference, that was what it called it i think

#

yup here are the 2 main errors that kept popping up

rustic rain
#

you dispose it when you want to unload that memory chunk

late mural
#

oh ok, thanks!

late mural
#

aha, i appear to be getting errors that i have not enabled my mesh to be readable, how do i do this manually, and for later, how can i make this automatic in import settings (also where are they as i cannot find them)

#

i found a bunch of import settings, yay! But none of them are useful so far, the plot thickens!

#

aha i figured it out, there is no way to do it automatically, you have to manually move it to your asset, change a bunch of stuff, move it back to where you need it,

#

very painful proccess but oh well

solemn hollow
#

did you create that mesh in code?

rotund token
#

there's just a setting on mesh imports to enable read/write

karmic basin
solemn hollow
#

yes

#

especially in combination with filtering collisions based on layers it got really buggy

late mural
#

during my search i discovered an oddity with friction

#

and that is that 0 friction means no grip, meaning it acts the same as infinite friction, only it can be pushed by other objects

rustic rain
#

oh god, this Tween thingy drives me mad. I literally want to make it managed component xD

#

It was all fine until I realised I need to edit source generation algorithm to allow BlobAssetReference in generated code

solemn hollow
#

they just dont use the apis that rely on codegen? write the job yourself

rustic rain
#

I wrote job myself

#

it's actually polymorph components

#

that need generation

#

and potentially I can make them myself, but I will certainly lose my mind completely if I try xD

#

I'd rather learn codegen

#

and fix it

late mural
#

is it possible to have some grip, while also having no friction?

solemn hollow
#

grip is literally friction though

late mural
#

and my spheres need no friction for when they fly over ledges

#

but on hills they dont roll, no matter the steepness

solemn hollow
late mural
#

im literally gonna have to write a script to make my spheres gain momentum in the direction of the hill downwards if they come into contact with my ramps!

#

cause they just sit there if i dont!

solemn hollow
#

can you show the settings of the physics components?

late mural
#

sure

solemn hollow
#

hm cant spot anything.

late mural
#

same, perhaps ive underflowed somehow?

#

ive got to go to bed now, so imma mess around more with this in the morning, but thanks!

solemn hollow
#

gn8

#

omg

    [UpdateInGroup(typeof(SimulationSystemGroup), OrderFirst = true)]
    [UpdateAfter(typeof(BeginSimulationEntityCommandBufferSystem))]
    public class FixedStepSimulationSystemGroup : ComponentSystemGroup```
#

this OrderFirst effectively blocks you from updating your own systems before FixedStepSimGroup

#

Ignoring invalid [UpdateBefore(Unity.Entities.FixedStepSimulationSystemGroup)] attribute on ConsiderationUpdateGroup because OrderFirst/OrderLast has higher precedence.

#

so id need to flag my group as orderfirst = true too. which messes up other ordering...

solemn hollow
#

main reason why i want to update before physics is because physics has some big gaps on worker threads and i can fill them with heavier work if i schedule expensive stuff before physics

viral sonnet
#

my job scheduling got a lot worse in 2021. not sure why, there are big gaps and some threads are dormant for the last bit

solemn hollow
#

same. but at the same time my jobs are performing better. so i figured thats why i have more gaps

karmic basin
karmic basin
solemn hollow
#

that alone would be ignored. what you can do to solve it is this: [UpdateInGroup(typeof(SimulationSystemGroup), OrderFirst = true)] [UpdateAfter(typeof(BeginSimulationEntityCommandBufferSystem))] [UpdateBefore(typeof(FixedStepSimulationSystemGroup))] public class EarlySimulationUpdateGroup : ComponentSystemGroup { }

#

every system that needs to sort itself before a system marked with orderfirst in the same group needs the orderfirst too

karmic basin
#

I see. (I don't dots these days so couldn't try quickly myself)
And running your considerations in the init group is a no-no ?

solemn hollow
#

yes because the begininitbuffersystem produces a syncpoint. so all my heavy jobs would be completed before fixedupdate. which defeats the purpose

viral sonnet
solemn hollow
#

๐Ÿ˜ฆ

solemn hollow
#

can someone explain why i have spikes like this

#

does that WaitForPresentOnGFX only happen in editor and i can ignore that spike for now? I cannot build and test it atm....

rustic rain
#

ok I'm done, I'll just make animations managed xD

rustic rain
#

Is there a handle for managed components?

#

component type handle I mean

#

for chunk iteration

#

ManagedComponentAccessor

#

looks like this is the one

#

ah, I see

solemn hollow
#

so you wanna use the animator now?

rustic rain
#

it's accessor

#

nah, I'll just create managed ECS Tweener

#

kek

#

with minimum amount of tweens I personally need

solemn hollow
#

hmm you should be able to use getcomponenttypehandle with managed Icomponentdata

rustic rain
#

yeah, looks so

#

I actually wonder

#

what if I make managed component

#

which contains...

#

function pointers

#

xD

#

and then these function pointers are passed into Execute method of chunk

#

and get called bursted

karmic basin
# solemn hollow does that WaitForPresentOnGFX only happen in editor and i can ignore that spike ...

Gfx.WaitForPresent: When the main thread is ready to start rendering the next frame, but the render thread has not finished waiting on the GPU to Present the frame. This might indicate that your game is GPU bound. Look at the Timeline view to see if the render thread is simultaneously spending time in Gfx.PresentFrame. If the render thread is still spending time in Camera.Render, your game is CPU bound and e.g. spending to much time sending draw calls/textures to the GPU.
From https://github.com/UnityCommunity/UnityLibrary/wiki/Profiler:-Overhead---Gfx.WaitForPresent-explained

solemn hollow
#

yes i found that thread too but looking at my render thread its empty...

karmic basin
#

ah

solemn hollow
#

but its off.

viral sonnet
#

huh but yours a litle high

karmic basin
#

vsync should be WaitForTargetFPS though ?

solemn hollow
#

i am CPU bound thats for sure.

viral sonnet
karmic basin
solemn hollow
#

enabling VSync just makes the spikes more consistent but they look the same for me

#

its also WaitForPresent. cant find WaitForTargetFps (but i might also be just blind)

karmic basin
#

Damn. Profiling is a nightmare ๐Ÿ™‚

solemn hollow
#

hmm it might also differ based on renderpipeline?

#

thats with Vsnyc

viral sonnet
#

Yeah, I also remember a mix of these. Not sure if it has to do with applying an Application.targetFrameRate or not

#

the odd thing is that it should be a straight line and not some sawtooth pattern

#

but maybe that really changed with the new srps

#

doesn't look right though

solemn hollow
#

thats a frame before the spike

#

here the renderthread waits for the MainTHread. next frame the mainthread waits for the renderthread (which does nothing??)

#

And sry for another Profiler related question but what is up with all those fallback allocations? the thread about it i found says it comes from memory leaks. but i have leak detection enabled and do no unsafe lowlevel allocations without safety i might forget to clear.

#

if i remember correctly i just had 1 or 2 of those in Entites 0.17

#

is that size in kb?

viral sonnet
#

it comes from leak detection enabled ๐Ÿ˜€

#

try disabling and profile again

solemn hollow
#

it was off though. then i enabled it to check if i have any leaks. no leaks but still those FallbackAllocs without leakdetection

#

safety was on though. maybe i need to disable that

#

I am about to reduce the number of allocations i do in jobs considerably based on tertles suggestion to only allocate once per thread

#

this

#

but cannot get it to work yet. curious if that changes sth with the fallback allocations. maybe i just alloc too much

solemn hollow
#

hmmm there was a leak which was not catched by leakdetection actually. 0.o

#

i did sth like that : ```var chunks = considerationQuery.CreateArchetypeChunkArray(Allocator.TempJob);
Dependency = new GenConsiderationJob
{
chunks = chunks,
}.ScheduleParallel(chunks.Length, 1, Dependency);

if (systemSettings.Value.actionSettings.Length > 0)
{
Dependency = new OutputBufferToDecisionJob<C>()
{
chunks = chunks,
}.ScheduleParallel(chunks.Length, 1, Dependency);
}```

#

and in the second job i used DeallocateOnJobCompletion on the chunks.

#

now before i added that if i had no leak but i would schedule a useless job.

#

after i added that if leakdetection didnt catch that i dont dispose the chunk array if the second job is not scheduled

viral sonnet
#

the tempjob allocation?

solemn hollow
#

yes

viral sonnet
#

did we discuss this? that temp allocations don't need to be disposed?

solemn hollow
#

i was getting a runtime error telling me its leaking though

viral sonnet
#

i'm not sure anymore about tempjob. that shit is so unintuitive

solemn hollow
#

i think it needs to be disposed if allocated on mainthread

#

in job you dont have to

viral sonnet
#

ok then it's clear. i also dispose tempjobs usually

#

haven't used one in my project though so i wasn't sure

#

so then you have no leaks but still fallback allocations?

rotund token
#

Temp job needs to be disposed

#

Only temp does not

viral sonnet
#

might allocate too much then for a single frame

rotund token
#

Even if temp falls back out it does not need dispose

hot basin
#

how much of an impact would a thread make in DOTS application?

#

I mean I know it will take the CPU time and all

#

but how it will behave, like will it steal working threads?

viral sonnet
#

oh you mean like a default c# thread?

#

yeah of course it will "steal" some performance

hot basin
#

hmm but will it stall unity's workers or other conflicts will be present?

solemn hollow
#

it makes no difference for nativecontainers whether i pass them as ref or not right?

woeful comet
#

Reminder to initialize your Rotations.

#

I just spent 3 hours debugging an issue with physics raycasts not working on my terrain.

#

Found out it was because I had done EntityManager.AddComponent(entity, new Rotation()) instead of EntityManager.AddComponent(entity, new Rotation{Value = quaternion.identity}).

#

Everything else works (including collision), it's only physics collider raycasts that don't, and they fail silently. Facepalm

solemn hollow
#

@rotund token i am very confused RN. i did implement the sharing of a NativeHashMap instead of allocating one per entity. i defensivly allocated the Hashmap with a size of 1000. It got ALOT slower. like 10x slower on workers. So it seems in my case its better to allocate alot of very small and some bigger hashmaps instead of allocating one defensive one per thread. feels wrong TBH

#

the overall performance diffrence is :
less but big allocs -> 1ms Mainthread ; 2 ms on workers ;
more but small allocs -> 1ms Mainthread ; 1ms workers

viral sonnet
#

several threads write to a nhm vs several threads write to several nhms?

solemn hollow
#

no. 1 big hashmap per thread shared between entities vs 1 small hashmap per entity

#

but thinking about it now its maybe because the entitycount is not high enough to matter atm. i update about 25 AI Entities per frame in around 60 systems. only 10% of those systems need bigger hashmap allocs

viral sonnet
#

the 1ms on mainthread is pretty huge. the 2ms are no wonder because nhm as parallelwriter isn't fast

#

are you allocating per frame or persistent?

solemn hollow
#

in both cases its 1ms mainthread since i only alloc in jobs

solemn hollow
viral sonnet
#

are you doing anything else than just scheduling?

solemn hollow
#

no. but as i said mainthread is the same. just workers have a lot more to do with less but bigger alloc

#

ill try what happens if i reduce the loadbalancer

viral sonnet
#

hm, 1000 isn't a lot but nhm also clears the bucket array with -1 so it's not just allocating. best would be to do it persistent or in a job

#

so it's bursted

solemn hollow
#

it is in a job

viral sonnet
#

then what takes 1ms on main thread? that doesn't make sense when it's just scheduling. that stuff should be in the <0.001ms range

solemn hollow
#

aaah now i see why you are confused. sry. All my 60-70 AI systems together take 1 ms on mainthread. just scheduling

viral sonnet
#

ah i see ๐Ÿ˜„

solemn hollow
#

and all those jobs of all systems on all workers need 1ms vs 2ms for both approaches

viral sonnet
#

ok, then. yeah as I said I'm pretty sure the Interlockeds of the NHM.ParallelWriter is what makes the shared NHM approach slower

solemn hollow
#

but its per thread. there should be no interlock happening right?

viral sonnet
#

do you cast it to a parallelwriter?

solemn hollow
#

no only one entity writes to it at a time

viral sonnet
#

hm, I'd need to see code to say more honestly. something is fishy ๐Ÿ™‚

#

it shouldn't be that much slower, that's for sure

solemn hollow
#
    {
        [ReadOnly]public NativeArray<ArchetypeChunk> chunks;

        [NativeDisableContainerSafetyRestriction]
        private NativeParallelHashMap<EntityDouble, float> entityToAxisMap;

        public void Execute(int chunkIndex)
        {
            if (!entityToAxisMap.IsCreated)
            {
                entityToAxisMap = new NativeParallelHashMap<EntityDouble, float>(1024, Allocator.Temp);
            }
            
            
            for (int iEntityInChunk = 0; iEntityInChunk < entityChunkArray.Length; iEntityInChunk++)
            {
               //Do Stuff 
            }
        }
    }```
#
    {
        [ReadOnly]public NativeArray<ArchetypeChunk> chunks;
        
        public void Execute(int chunkIndex)
        {
            for (int iEntityInChunk = 0; iEntityInChunk < entityChunkArray.Length; iEntityInChunk++)
            {
                var entityToAxisMap = new NativeParallelHashMap<EntityDouble, float>(10, Allocator.Temp);
                //Do Stuff 
            }
        }
    }```
#

the second approach is the faster one. i dont actually alloc a size of 10. i evaluate some logic to see how big it needs to be and then allocate this. it can range from 0 to 10000 actually

viral sonnet
#

if (!entityToAxisMap.IsCreated) 95% sure this is a race condition

#

debug.Log how many are actually allocated

#

oh wait you have it per thread, i forgot ๐Ÿ˜„

#

i'd still check ๐Ÿ™‚

solemn hollow
#

i just checked what happens if i update all my AIs every frame (easily tripple the load but hard to say exactly):
4,7 for slow approach on workers
2,2 for faster approach

#

and the threads are much emptier overall with the faster approach

solemn hollow
viral sonnet
#

one way woukd be to schedule just once and count

#

if you debug log in the mainsystem you have a seperator

#

and you can output the threadId

solemn hollow
#

ah i got it

#

so it allocates once per chunk

#

basically every time

viral sonnet
#

and not per thread. found the culprit

#

I had a similar case, other datatype and I changed it to a pointer

#

I'm honestly not sure why that doesn't work but structs are always reset or smth

solemn hollow
#

but its a nativecontainer though

viral sonnet
#

the bool isn't

solemn hollow
#

hm

#

maybe the problem is that im using manual chunk iteration

viral sonnet
#

no you are right, it actually checks UnsafeParallelHashMapData* m_Buffer for null

solemn hollow
#

seems like that job struct is not really reused for multiple iterations of execute then?

viral sonnet
#

very possible

solemn hollow
#

im a bit out of my depth here ^^

viral sonnet
#

per thread values are kind of missing sadly

#

the only thing you could do is pre-allocate 128 NHMs but that's ... yeah

#

or allocate with interlocked and unsafe containers

solemn hollow
#

thats probably alot slower

viral sonnet
#

all in all, I don't think it's worth it much

solemn hollow
#

yes performance is fine. main thing i wanted to get rid of were the fallback allocs

#

but this was a leak and not too much allocs

viral sonnet
#

you have the fallback with the 2nd appraoch too? small allocs?

solemn hollow
#

nope they are gone now

viral sonnet
#

ah cool

solemn hollow
#

but it didnt impact performance at all

#

uh wait i said sth wrong i think

rotund token
solemn hollow
#

it allocs every iteration but it does multiple iterations with a struct

rotund token
#

Instead of 1 small hash map per thread like it was previously

#

Though I gave by followed up convo so maybe you solved it

solemn hollow
#

no its either 1 defensivly big hashmap per thread or one perfectly sized small Hashmap per entity

rotund token
#

Why

#

The whole point of sharing is to do the exact same thing as you were doing previously

#

Except remove initial allocation

#

Why are you changing logic when sharing?

solemn hollow
#

i need a hashmap per entity to multiply multiple axis together. each entity has multiple buffers which are the axis of the utility AI. the hashmap is there to calculate the score for every TargetEntity. So based on the lenght of the axis of an entity i can size the Hashmap perfectly

#

if i implement sharing to reduce the number of allocations i need to size defensivly

#

as if one of those many entities has an axis with 1000 targets

rotund token
#

The map will resize by itself though

solemn hollow
#

but thats also very expensive right?

#

hmm i might try allocating a very small map

rotund token
#

Also I don't see a clear

solemn hollow
#

i do the clear inside the //DoStuff

rotund token
#

What type of entity count we looking at anyway?

#

And per chunk

solemn hollow
#

that really depends. i tried with above 1000 entities and with 25. the AIs are diffrently complex so some chunks only have 3 entities (yes i need to change that somehow) and some have 30

rotund token
#

Of containers to reuse I do think hash map is the worst

#

If you have large changes in data size

#

Because a large empty hash map has detrimental performance on lookups

#

While say an empty list is no different

solemn hollow
rotund token
#

And clearing

#

In particular

#

List clear is length =1

#

Hash map clear requires 2 mem clear, menset and a loop from memory

#

Which it does on creation as well, but if it's large its going the same thing for all instances now

solemn hollow
#

that explains alot. even if i start with an initial size of 10 the worker threads are still slower. but its much closer now

#

buts its amazing that i can do some logic to actually evaluate the perfect size for the hashmap per entity and still be faster than sometimes resizing

#

oh wait. how much is it resized by ? is it always doubled?

#

still ill keep your sharing pattern close to heart. pretty sure i have some usecases for it already that do increase performance

viral sonnet
#

lol, job scheduling is exactly the same in 2021. my computer just had way too much stuff running and ScriptedSandbox64.exe from VS2019 literally used 1 whole thread -.-

#

a min/max/avg of jobs over several frames in the profiler would be nice.

solemn hollow
#

btw i checked on a different PC if i get those renderspikes too. Nope. might have sth to do with metall API. idk

viral sonnet
rotund token
#

what have you done

viral sonnet
#

that's a big one ๐Ÿคฃ

#

what's going on here?

rotund token
#

a very slow write

viral sonnet
#

huh, i know with big structs there's usually a memcpy

#

question is how can i fix that?

#

use memcpy instead of WriteArrayElement?

rotund token
#

usually that's slower for small writes

viral sonnet
#

i know but in that case? hm

#

i'm surprised burst or llvm hasn't figured this out

rotund token
#

it probably has

#

and considers this to be the fastest way

viral sonnet
#

i'll just test it. let's see how this goes

#

MAN vs MACHINE

#

I don't have much chance

#

huh, I won

#

by a pretty big margin

rotund token
#

Enzi holding off the inevitable machine takeover 1 battle at a time!

#

how large is this struct out of interest?

#

looks like a big boy

viral sonnet
#

72 bytes

rotund token
#

big but not that big

#

interesting - taking notes

viral sonnet
#

yeah, gonna need to research where the breakpoint is for memcpy

#

i got pretty tired of optimizing from source, so hard to figure out so now I'm just reading assembly and going over big blocks that stick out

#

and hold off on the final verdict because some error cropped up :/

rotund token
#

do you merge jobs as frequently as i do?

solemn hollow
rotund token
#
var effectTimeRemainings = batchInChunk.GetNativeArray(this.EffectTimeRemainingHandle).Reinterpret<float>();
var attributeDestroys = batchInChunk.GetNativeArray(this.AttributeDestroyHandle).Reinterpret<byte>();

for (var i = 0; i < effectTimeRemainings.Length; i++)
{
    effectTimeRemainings[i] -= this.DeltaTime;
    attributeDestroys[i] += (byte)math.select(0, 1, effectTimeRemainings[i] <= 0);
}

// Job 2
for (var i = 0; i < effectUseRemainings.Length; i++)
{
    Check.Assume(effectUseRemainings[i] != 0);

    effectUseRemainings[i] -= (byte)math.select(0, 1, effectActives[i]);
    attributeDestroys[i] += (byte)math.select(0, 1, effectUseRemainings[i] == 0);
}

// New Combined Job
var attributeDestroys = batchInChunk.GetNativeArray(this.AttributeDestroyHandle).Reinterpret<byte>();

if (batchInChunk.Has(this.EffectTimeRemainingHandle))
{
    var effectTimeRemainings = batchInChunk.GetNativeArray(this.EffectTimeRemainingHandle).Reinterpret<float>();

    for (var i = 0; i < effectTimeRemainings.Length; i++)
    {
        effectTimeRemainings[i] -= this.DeltaTime;
        attributeDestroys[i] += (byte)math.select(0, 1, effectTimeRemainings[i] <= 0);
    }
}

if (batchInChunk.Has(this.EffectUsesRemainingHandle) && batchInChunk.Has(this.EffectActiveHandle))
{
    var effectActives = batchInChunk.GetNativeArray(this.EffectActiveHandle).Reinterpret<bool>();
    var effectUseRemainings = batchInChunk.GetNativeArray(this.EffectUsesRemainingHandle).Reinterpret<byte>();

    for (var i = 0; i < effectUseRemainings.Length; i++)
    {
        Check.Assume(effectUseRemainings[i] != 0);

        effectUseRemainings[i] -= (byte)math.select(0, 1, effectActives[i]);
        attributeDestroys[i] += (byte)math.select(0, 1, effectUseRemainings[i] == 0);
    }
}```
#

like this

#

i have 2 small jobs writing to same component

#

instead i merge it into 1 job

#

halve job scheduling, query lookups

solemn hollow
#

Sidenote : i replaced all GetComponentTypeHandle with the cache + Update workflow. i saw a 6-8% performance increase on mainthread

rotund token
#

improve thread performance (jobs don't have to wait on each other)

rotund token
viral sonnet
#

machine gave me a short burst of victory only to crush it with unemphatic coldness. the memcpy makes zero difference

solemn hollow
rotund token
#

does the burst look any different?

viral sonnet
#

let me check and yeah I've merged a looot of jobs into one.

#

basically the reason why i have 10 rainbows in the burst assembly ๐Ÿ˜„

solemn hollow
#

maybe its time to invent SubJobs

rotund token
#

to get some AI stuff running on consoles

#

like 20+ files each basically just looks like a standalone job

#

with 1 file dispatching them all

solemn hollow
#

yap i have "processors" now which are basically the same thing

rotund token
#

i optimized main thread on xbox from 6ms down to 0.35ms

solemn hollow
#

structs that are called by a job execute

rotund token
#

original implementation, lots of little systems - 6ms
merging to single system, lots of little jobs - 2.5ms
1 single system, merging into 1 large job (reusing Gets) - 0.75ms
1 single system, 1 large job, burst compiling Gets - 0.35ms

#

this was before Update on type handles

#

instead I burst compiled all the Gets in a function pointer

solemn hollow
#

omfg

#

im at the lots of little systems step

rotund token
#

(reusing Gets) is similar to Update()

#

this was xbox one performance, so like 10 year old hardware

#

this level of optimization much less required on modern cpus

solemn hollow
#

so what kind of game was it?

solemn hollow
rotund token
#

i do like living in the environment

viral sonnet
viral sonnet
#

i've been preaching this since the beginning. the architecture of several jobs and systems is cool but really bad for performance

rotund token
#

you say as I'm writing a lot of individual systems atm

#

for this attribute library

#

(though they are all ISystem so we'll see how much this bites me)

#

atm it's updating 10 systems on main thread in 0.06

#

so burst is doing it's thing

solemn hollow
#

well maintainability matters

viral sonnet
#

it really depends if you are even able to merge. but if you can, you should.

solemn hollow
#

but rly im impressed that you can optimize it down to 0.35ms. nice game

rotund token
#

there's no reason a game /needs/ more than 1 system

#

๐Ÿ˜„

#

so i could totally merge

viral sonnet
#

like my first iteration basically iterated over the same data/chunks over and over again with different jobs

rotund token
#

but i care more about maintainability than saving 0.05ms atm

#

oh none of these jobs iterate over the same data (but do a lot of the same chunks)

#

most of my components are single fields atm, i've managed to simd every single job so far

viral sonnet
#

that's what I expected from you actually ๐Ÿ˜‰

rotund token
#

still a bit concerned about scalability atm

#

and i think the most annoying thing is i won't really know until everything is put together

viral sonnet
#

as long as data access stays unique it's not too bad to have them split up

#

yeah that's the annoying part :/

rotund token
#

but i'm not actually sure what level of performance i'm targeting

#

usually i like to aim for 250k
but am i aiming for 250k targets or effects

#

because 250k targets would be 2.5mill effect goal

#

atm i'm just testing 10k targets, 100k effects

viral sonnet
#

oh boy that would be a lot ๐Ÿ˜„

#

so yeah, the burst assembly I've posted above. the memcpy is just a mov. I mean it's not really measurable even over a lot of copies (250k) but a lot less commands. funny that it matters so little

solemn hollow
#

if you have your effects reactive i think you can go for 250k

rotund token
#

a lot of effects will exist permanently

#

stats on armour, abilities unlocked, buffs, etc

#

i'm estimating only 10/actor just because npcs will likely have a lot less than player

viral sonnet
#

oh wait a minute, there's a jmp. looks very much the same. what?

solemn hollow
rotund token
#

yeah they won't

#

though an active affect might bump the change filter and require a re-calc

#

though good chance that will be a different chunk anyway

solemn hollow
#

maybe you should tag static effects to split up into static chunks

rotund token
#

thinking about it, i think that'll just come naturally

solemn hollow
#

so a recalc of one stat only triggers recalcs of non static chunks

rotund token
#

they won't have components like, EffectTimeRemaining, EffectUsesRemaining

#

and often won't even have Conditions

solemn hollow
#

ah yes makes sense. works the same in my system

rotund token
#

i have some ideas to group effects loosely on targets

#

but i can't do all effects of target in same chunk

#

too much wasted memory

#

outside of player most chunks would be empty

viral sonnet
#

i have a hashmap for that. okay i have a hashmap for everything...

solemn hollow
#

i do it the other way around. my effects have lists of entities they effect. and when an effect updates it randomly accesses the entities and updates their values

rotund token
#

OH i had a question for you enzi

#

just something i was randomly thinking about yesterday when a developer was trying to implement something at work

#

do you have a good way to record recent damage to a target and in particular killing blows?

rotund token
#

but yeah that's how i'm doing it

#

except i'm not doing an entity lookup, i just made target + effect have a shared pointer I write to =S time will tell if this bites me

solemn hollow
#

im not sure you actually gain much from that. since CDFE will hit the cache alot

viral sonnet
#

i don't maintain a history though

rotund token
#

nice! though adding history wouldn't be hard with that setup anyway

#

a lot of games don't need history but some like it for death screens

viral sonnet
#

yeah, pretty much the reason why I optimized this path so much. at some point you need the data anyway

#

yep, the history could be client/player only

frosty siren
#

I'm feeling like asking some noob question, so i'm sorry, but why my system updates if there is no match? What can trigger its update? I have no [AlwaysUpdateSystem] attribute

rotund token
solemn hollow
#

i think Getsingleton also causes updates. but not sure

rotund token
#

that should still show in query list

solemn hollow
#

ah true

frosty siren
rustic rain
#

Why not just use RequireForUpdate?

#

From what I noticed, it breaks automatic update detection and uses whatever you define instead

frosty siren
#

anyway i'm trying to use no GetSingleton, because AFAIK it causes dependency completion

solemn hollow
#

can you share system code?

frosty siren
solemn hollow
#

Quick question about EntityTypeHandle. can i just cache it in OnCreate and be done with it? i dont think it ever needs an update right?

solemn hollow
#

can [UnityEngine.ExecuteAlways] public class TransformSystemGroup : ComponentSystemGroup { } cause subsystems to always execute?

frosty siren
#

let me try to remove filtering and system group

solemn hollow
#

well and last resort might be to add RequireForUpdate to all queries just to test if it would work. wont work for your logic i guess

frosty siren
#

๐Ÿ‘€

rotund token
#

ignore me

#

i can't read code

frosty siren
#

is it so bad (my code)? ๐Ÿ˜…

viral sonnet
#

is this assembly building a jump table for the switch?

frosty siren
#

ok, it is combination of TransformSystemGroup always execute and using filtering

#

so there is no RequireForUpdate with Any mode

solemn hollow
#

what i find strange is that it takes 0.18ms for the filters then. should be faster no?

solemn hollow
#

yes

frosty siren
#

it is because i use .Complete()

#

it waits for all threads

solemn hollow
#

well get rid of that by managing dependencies correctly and just update it every frame.

rotund token
solemn hollow
#

0.02ms budget should be ok for a transform system ๐Ÿ™‚

frosty siren
#

but yes, filtering takes time, because it is just IF per chunk, i guess

rotund token
#

also i'm pretty sure this will be significantly faster anyway i can write 100,000 effects to 10,000 entities in 0.17ms

#

no threading issues

solemn hollow
rotund token
#

yeah i won't do that many writes per frame obviously

#

but the big issue is more the inability to parallel the work

#

unless i do it over 2 jobs and group by entity target in hashmap or something first - which is much slower

solemn hollow
rotund token
#

this was definitely very much an experiment on being able to have a many-to-one parallel writing without locks

#

a common issue in ecs

#

honestly, i'm not really developing a game or anything

#

i just like to find a problem and try to solve it

#

many to one writing, unmanaged entity command buffer system (i don't even use it)

#

etc

solemn hollow
#

yes i also like those design problems more than actual gameplay code. my "game" is just a testingground for the AI framework atm...

rotund token
#

yeah i wrote my ai system more than 18 months ago

#

never used it

#

i tried to build an interesting sample game and got bored

solemn hollow
#

thats sad. i would love to see the architecture

rotund token
#

it was glorious for its time! it alone found 5 burst bugs (though 2-3 may have been the same just manifested in different ways)

solemn hollow
#

dont wait too long with updating it to new Entities Version ๐Ÿ˜„ will only get harder

rotund token
#

oh that's already done

#

entities 0.50 threw me a spanner

#

my generic component could no longer work in il2cpp builds

solemn hollow
rotund token
#

oh no

#

thats 0.51

#

this was a 0.50 change to property package

#

and how il2cpp generates generics

solemn hollow
#

ah ok. i didnt try to build with 0.50 would have run into the same problem

rotund token
#

the issue isn't fixed

#

so if you aren't having issues in 0.51 you don't need to worry

#

it basically manifest like this in a build

solemn hollow
#

okay so i answered my own question with EntityTypeHandle. you cant cache it...

rotund token
#

MissingPropertyBagException: No PropertyBag was found for Type=[BovineLabs.AI.Data.AIGraphs`2[[Shattered.AI.Core.AIContext, Shattered.AI, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[Shattered.AI.Core.AIStorage, Shattered.AI, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]]. Please make sure all types are declared ahead of time using [GeneratePropertyBagAttribute], [GeneratePropertyBagsForTypeAttribute] or [GeneratePropertyBagsForTypesQualifiedWithAttribute]
and
[assembly: RegisterGenericComponentType(typeof(AIGraphs<AIContext, AIStorage>))]
does not fix it - it only fixes it for entities not for il2cpp

rotund token
solemn hollow
#

hmm i didnt see that particular error. my build still fails with il2cpp atm though

rotund token
#

this error happens after starting the game not during build

#

the issue is mostly the generic and implementation are in different assemblies

solemn hollow
#

ah. no my generics luckily work fine

rotund token
#

(it's because AIGraphs is a class based ICompnentData)

#

it basically just holds the reference to my scriptable object that owns all the graph data

rotund token
#

it's writing a struct

#
{
    /// <summary> The stat type this affects. It matches the index in the stat schemas. </summary>
    public ushort Type;
    public ShortHalfUnion Value;
    public StatModifyType ModifyType;
}```
#

i wish i could remove a byte from this

#

but it'd limit me to 255 stats

#

maybe that's enough ๐Ÿค”

solemn hollow
#

sry i dont know the specifics of those types but did you consider padding?

rotund token
#

it is padding 3 bytes

#

that's the issue i'd like to remove

#

if i reduce a byte the struct is just 4 bytes instead of 8

solemn hollow
#

are those properties sorted after size?

rotund token
#

sorry i don't follow

solemn hollow
#

you can sometimes reduce padding by ordering the properties in the struct after their bytesizes

rotund token
#

this is ordered as well as possible

#

2 bytes, 2 bytes, 1 byte

#

shorthalfunion is what its name suggests

public struct ShortHalfUnion
{
    [FieldOffset(0)]
    public short Short;

    [FieldOffset(0)]
    public half Half;
}```
solemn hollow
#

ah ok. wasnt sure how much shorthalfunion is

late mural
#

unrelated but i misread that as "short half onion"

solemn hollow
#

do you actually need that statmodifytype? cant that be encoded in the type itself?

#

or can a type have different statmodifytypes?

#

ah that is whether its add, increase or more right?

rotund token
#

yeah

#

public enum StatModifyType : byte
{
Added,
Increased,
Reduced,
More,
Less,
}

solemn hollow
#

damn you. thats way more efficient than having my 3 values for add,increased,more in 1 struct ๐Ÿ™‚

rotund token
#

honestly at some point i will probably get frustrated and bit pack it in

#

while i want more than 255 stats

#

i dont need 65k

#

i can take 3 bits away and still have 8k stats

solemn hollow
#

yup.

rotund token
#

and just wrap it with a few properties to hide this

#

i actually just did a bunch of stuff like this at work

#

halved our dynamic grid size

solemn hollow
#

its always amazing how much you could optimize. i know a few things about what is possible but i never get around to it ๐Ÿ˜„

#

and after you optimzed your gamedesigner comes around and tells you he wants an effect that at the same time adds but reduces. and both with diffrent values

rotund token
#

oh thats expected

#

items can have multiple effects

#

they are just created as separate entities

#

just a design choice i decided on

#

this way i have no limit on what can be added to something

#

if i want a god tier 4000 effect item

#

go for it

solemn hollow
#

yes i know you could handle it with the system. just an example where sometimes an optimized datastructure makes things complicated

solemn hollow
rotund token
#

i'll put the code for unlocking this item 70% down the page of the TOS

#

and this code can only be applied to your account within 5min of reading the TOS ๐Ÿ˜ˆ

late mural
#

i would do that to my game, except my game is a fluid puzzle thing, so i dont see how items could really be used apart from cheating the puzzles lol

solemn hollow
#

roguelike puzzler. items modify the puzzles. make it harder in one way easier in another.

#

gl designing the puzzles though lol

late mural
#

ooh i like that idea! I was already gonna have different puzzles depending on how good the player thought their computer was, so why not, it may be difficult to design then, but oh well!

#

that does raise in interesting logistical question i hadnt thought about: How am i gonna test the good computer puzzles when my computer is quite low spec and can only handle low spec puzzles

rotund token
#

game should always be designed around min specs?

late mural
#

not during fluid simulation (ish) stuff

#

cause my computer can handle around 3000 particles at once, whereas one of my friend's computer can handle around 60 thousand particles at once

#

large difference in amount of fluid emitters that can be used, how much water is allowed to stay active during the level, and in general it affects the whole puzzle design, hence why it is more fun to design different puzzles for different specs, cause more specs means more fluids means more fun

solemn hollow
#

id really need to see one of your puzzles now. but id say you probably dont need a fully maxed out fluid sim for the gamelogic. ofc you can render diffrent amounts of particles based on spec anyways.

late mural
#

ye, my fluid sim is completely nonsense, it follows none of the principles of fluid simulation, it just gives spheres a lot of bounce and no friction

#

and it looks like they merge when close, although not very well, i havent fully figured out meta balls yet

solemn hollow
#

so you can do 1 gamelogic sim that drives the boundingvolume of the fluid and 1 render sim thats inside the volume.

late mural
#

ooh that sounds fancy, ill probably do some research on those, thanks!

viral sonnet
solemn hollow
#

cant blame them. love it myself ๐Ÿ˜„

#

its so slow....

#

it seems like adding empty ECBs is really slow

#

all those little lines are empty command buffers that try to execute anyways

#

as far as i can tell

viral sonnet
#

tertle from what i gathered you iterate on the effects (10k) which have stats(10?) and write them to your unmanaged block? the stats are dynamic buffers?

solemn hollow
rotund token
#

i think that goes down a lot in builds

#

because you can't remove safety from main thread in editor

solemn hollow
#

ah

#

still it would be nice to first create a buffer and only if it contains anything it gets added to update

rotund token
rotund token
#

in playback

solemn hollow
#

well it first completes the dependency. which also wouldnt be necassary

rotund token
#

well the dependency isn't stored separately

#

so it'd be hard to not do that (though you could change this i guess)

#

but yes, avoiding scheduling a job with a buffer is ideal

#

if possible

#

using things like IsEmptyIgnoreFilter etc

solemn hollow
#

id like it for the ecb only gets added to the update list of the ecbs if you declare the dependency. instead of already when you create an empty ecb

viral sonnet
rotund token
#

effects modify stats

#

they aren't a stat

#

like add, reduce, more, less etc

#

effects just write to the stat modifier buffer using a ptr directly

#

so there is no safety issue

viral sonnet
#

and this stat modifier buffer is your unmanaged memory block?

rotund token
#

it points to the block yes

#
{
    [NativeDisableUnsafePtrRestriction]
    internal StatEffect* Effect;
}

[InternalBufferCapacity(0)]
public unsafe struct StatValueBuffer : IBufferElementData
{
    [NativeDisableUnsafePtrRestriction]
    internal StatEffect* Effect;
}```
#

StatValue is on the effect
StatValueBuffer is on the actor with the stat

#

each element in StatValueBuffer maps to a StatValue

#

if the buffer resizes etc it doesn't matter

#

i don't even need to worry if the target entity has been destroyed

#

(though I clean this up already)

#

anyone then a separate system just iterates all StatValueBuffer and calculates each final stat value

#

this is why i needed to get that manual change filter triggering working

#

so i could trigger a change filter on StatValueBuffer without actually writing to it

#

so i didn't have to update every StatValueBuffer every frame

viral sonnet
#

really nice. wait, is that change filter only for the buffer? what if something else on the actor changes?

rotund token
#

its only on the buffer

#

what else on actor changing would matter?

viral sonnet
#

what do you use to get that info? i had the problem that if anything on a chunk changes it triggers a change filter

rotund token
#

ah that shouldn't happen

#

change filtering is done per component

viral sonnet
#

what the ... I stopped using change filtering because that wasn't happening. hm

rotund token
#

adding/removing an entity into a chunk or adding/removing components might trigger it if the chunk changes

#

but simply changing another component shouldn't trigger it

viral sonnet
#

what's the code to check a specific comp?

#

I only know chunk.DidChange and CDFE.DidChange

#

query? hm, did I actually miss this. I was complaining about that ๐Ÿ˜„

rotund token
viral sonnet
#

yeah Manarz, that was triggering even when another comp changed. seems I need to test this again

rotund token
#

that usually happens if you just access with write by accident

#

i can say that all my systems don't do anything atm if there's no change

#

also i actually used DidOrderChange for the first time! I use this for checking if target chunk has changed at all invalidating my cache.

viral sonnet
#

I totally believe you. yeah, seems that got mixed up with write access version bumping

#

ah right and you had this funky way of determining if you need to write

rotund token
#

yeah i store all archetypechunks that effects reference in a chunkcomponent

#

this whole implementation is not something i'm going to recommend to anyone anytime soon

#

it's a huge experiment to see what's possible and atm it's not feeling /that/ gross. all the jobs are quite independent and small making the hackiness quite manageable and hard to break.

viral sonnet
#

i think you're on the right track with this. i'm pretty much doing the same thing on one level but what's nice about yours is that you have a well designed block that you can simd

#

my stats work very different, I'm still searching where I could apply this. sadly I'm not finding anything ๐Ÿ˜„

solemn hollow
#

man this whole thing with empty CommandBuffers is annoying me... in systems where i schedule multiple jobs that could share an ecb its really hard to find a decent way to not create it in the first place.

viral sonnet
#

stat calculation is just a really nice application for simd

solemn hollow
viral sonnet
#

sure but I have stat snapshotting. stats are calculated on a per-spell basis

rotund token
#

i can simd the final stat calculation nicely, but the actual writing stats to actor is far from simd - completely random memory access

viral sonnet
#

and my stat system isn't generic nor does it have 500 stats so it's quite fast.

solemn hollow
viral sonnet
#

yes

#

like you can't buff a damage over time just because you get a %dmg modifier later

#

or a projectile that's already flying

solemn hollow
#

ah i do that by basically treating spells as secondary characters with stats.

#

so my effects work for characters and abilities

viral sonnet
#

right same here

#

maybe I'll need to pimp my stat system later on ๐Ÿ™‚ who knows

solemn hollow
# rotund token yeah that's good design

well i do it too BUT imagine a game where your buffs are super short and you do combos like fireball -> splitshotbuff -> explosion to actually make the player cast a spell with timing his buttonpresses ๐Ÿ˜„

rotund token
#

i haven't really thought much about a spell/skill/combat system yet - how could i compete with enzi anyway

#

i'll just wait for him to release it and use that for inspiration

viral sonnet
#

you're too nice ๐Ÿ˜Š

#

how do you share a bunch of methods for jobs? them being static leaves me with too few options for datatypes in parameters

#

and I need to get around a very lazy workaround

solemn hollow
#

"inspiration"๐Ÿ•ต๏ธ

#

how do i best post some bigger code block rn?

#

upload the file itself?

viral sonnet
#

yeah

solemn hollow
rotund token
#

do those burst compile tags even do anything?

solemn hollow
#

damn unity crashed again... second file with the system incomming

#

no lol

rotund token
#

it made it very confusing as a first read

#

i was like, are these function pointers, hang on they are not static

solemn hollow
#

yes sry i didnt clean it yet.

#

you remember when i asked why my functions dont turn up in burstcompiler? i was just desperate there lol

#

i probably do some roundabout stuff i could get rid of. but atm its a nice way for me to define scriptable objects and assign them to those basefiltersystems to run any logic i like

#

@viral sonnet sry i forgot to ping you there. thats how i handle reusing code between multiple systems and get some polymorphism

#

its not the complete code you need for it to run though since how this is authored atm is deeply embedded into my AI

#

I think this is pretty much what i meant with SubJobs before. im just not sure if you could somehow get rid of that PrepareProcessor() and still be able to use any ComponentDataArray without it beeing specified inside the system.

viral sonnet
#

not sure what I'm looking at. my lazy workaround just shares a struct that has the methods. the methods don't use any public fields. it works but the design is bad

solemn hollow
#

yeah its a bit of a chaos sry. just too tired to clean it up now. you look at a way to get a "processor" struct thats completely defined outside of the System to run without the system even having to know what data to pass in.

viral sonnet
#

that's essentially what i'm doing too. hm, maybe i'm too strict on my "workaround"

solemn hollow
#

Im not super happy with this but for a quick first iteration to get any new logic i ever want per drag and drop into my AI graph its really amazingly easy

viral sonnet
#

that's why I've been doing it too ๐Ÿ˜„ I'd rather use statics but those don't work for most datatypes so sadly not an option

solemn hollow
#

shit. 3:33 am. gotta go :S

viral sonnet
#

o/

remote crater
#

I never got this error/warning before: WARNING: Hybrid Renderer using error shader for batch with an erroneous material:

solemn hollow
#

Anyone got a good way of skipping the conversion of a certain UnityComponent? In my case i dont want old Phyiscs components to be converted (but i also imagine stopping conversion of a spriterenderer might be quite useful). I use the old physics components to build a navmesh but dont want them at runtime. Should i just disable the system (e.g. LegacyRigidbodyConversionSystem) with a system running earlier or do i have better options?

rustic rain
#

anything about conversion is hacky

#

so just use whatever is going to make your conversion faster

solemn hollow
#

there is no way to see the conversionsystems running in the systems window right?

rotund token
rustic rain
#

all right, I'm done with pure ECS in that project xD
I'm trying to figure out now, how to combine best out of ECS and Classic Unity
I'll be happy to have Entity bookkeeping, but how would I combine it without conversion... hmm

karmic basin
solemn hollow
solemn hollow
#

i had that without the subscene workflow and it ended up in a branch that gets converted and a branch that doesnt for alot of prefabs which was really annoying

rotund token
#

easiest way is probably just remove the components in post

#

rather than hacking in something

solemn hollow
#

hmm thinking about that i guess for physics it would be enough to remove the physicsworldindex component. then id still have the colliders available if id need to do sth else with it (runtime navmeshgeneration is planned anyways)

#

i just wonder how much that bloats the subscene data

#

(but since most of it will be randomly generated at runtime who cares)

rotund token
#

so it was never saved

#

for example, i have like a NoTransform component for completely stripping transform stuff and optionally from children

#

(instead of just leaving static/localtoworld)

#

that just runs after transform conversion

solemn hollow
solemn hollow
#

since you cant render them without localToWorld

rotund token
#

they don't render

#

they're just settings files

#

didn't seem much point including ltw on settings entities

solemn hollow
#

hmm interesting. havent thought about having a setting entity as a child yet. id probably do sth like that with CreateAdditionalEntity and keep the authoring on the main entity

rotund token
#

oh i don't think i actually use it anymore

#

as in children

#

it's all just 1 entity atm

#

but yeah still strip the transform fully

solemn hollow
#

ah i see its global settings. i thought you had some per entity settings in childentities

rotund token
#

yeah just global

rustic rain
#

ngl, I quite enjoy managed ECS

rotund token
#

get out of here with your filth!

rustic rain
#

I couldn't bear with being forced to create code gen framework just to make tweens work

remote crater
#

Having a brain fart. If I want an entity to render right in front of the camera like it was on the UI plane, do I have to tightly couple it with my moving camera, or do I make like a 2nd camera to render it on? This may not be a DOTS question.

rustic rain
#

and draw whatever you want in front of it

devout prairie
rustic rain
devout prairie
rustic rain
#

basically ECS keeps references of everything I mark with IComponentData

#

and then I iterate through them in SystemBase

#

code is almost same as pure ECS

#

Hands are way less tied without being stuck in unmanaged world

#

but everything is stuck on main thread

devout prairie
#

Ah that's interesting, i didn't realise that was possible

rustic rain
#

kind of like this

devout prairie
#

i take it you have no choice but to use dirty managed objects

rustic rain
devout prairie
#

to lower yourself to such depths

rustic rain
#

I just want to focus on making game, not frameworks

#

that's why I went on this path

#

this way I don't have to work in OOP

#

and I also get to work on game using classic Unity components/DoTween and etc

solemn hollow
#

how do you handle conversion though? the gameobject is destroyed. or do you use convert and inject or sth?

rustic rain
#

entities in my case are just reference containers

#

Currently I am working on destroying of them

#

So far I decided to make it this way:

#

only objects with special component can be destroyed legitimately

#

so everything is handled in system that destroys entity/gameobject

#

which uses this component for query

solemn hollow
#

haha you are basically doing what conversion is doing in the Conversionworld. spawn an entity for every gameobject and add references to the monobehaviours to the entities so that you can query them in conversionsystems

rustic rain
#

welp, I invented a bicycle

#

existing objects converter looks like this, kek

solemn hollow
#

so you do it purely for the SystemArchitecture? 0 memory layout benefits, 0 built in parallelism (you still can do normal jobs though), 0 burst

rustic rain
#

sadly, yep

#

maybe in the end

#

there will be a window for burst

#

or something

solemn hollow
#

why dont u use the hybrid workflow as intended?

rustic rain
#

and in order to get simple stuff