#archived-dots
1 messages ยท Page 258 of 1
:))
Please wear a seatbelt when using burst. It's very fast.
In the past I tested DOTS, it was very basic (for loop in for loop in for loop xD). From 170 FPS I got 700FPS using Jobs System and Burst Compiler xD
I think I found the offender why I couldn't update to .50... It was windows platform package.
So I've done everything for round 1 before going to the land of uncompilable.
2021 lts means new entities?
or did they not link the releases in any announcements yet
just that they will support 2021 lts
I was wondering the same thing
does 2021 LTS have entities now?
oh okay
Check 2021 jobsutility if it has a panic function
When it's been included you can port entities
@rotund token with regard to saving and the [Saved] attribute, how do you register this for 3rd party libraries?
You create a new SaveComponent(type index)
All the attribute does is generate this for you
No code implementation required
Do we have a reliable way to get the current worker count? The hardcoded "public const int MaxJobThreadCount = 128;" seems a little high
how does this relate to the profiler window then where it doesn't exceed 8? I assumed it's always tied to cores
There is another property you can get / set though to limit this I think
maybe I need the worker count?
JobsUtility.JobWorkerCount
Yeah that's the one
@rotund token sorry Im dense, still dont quite follow: save attribute goes on the component that has a reference to the prefab? or save attribute on other regular ICD?
Hm, this throws me off somewhat. Basically I want to have a thread safe buffer for an entity but it was unclear to me how much memory I should allocate. DreamingImLatios always uses JobsUtility.MaxJobThreadCount. My thinking was to reduce this somewhat
Save component goes on any component you want saved (icd, buffer)
You need to use Max
This is how my event system works as well
Max relates to the thread index
Which is as far as I'm aware the only real data you can get in your job
doesn't that leave a lot of memory that's never even used?
Sometimes but all 128 can be used
And well I just don't allocate in the thread till it's first used
how do you deal with bultin components(translation etc)? or do you just not use it on those things?
I see, thanks then! ๐
I just manually create the container
new ComponentSave(Type Manager.GetTypeIndex(typeof(Translation)))
All the save system does is check each component type to see if it has the Saved attribute then create one of these containers for you
But you can manually add your own
You aren't limited to component saving either
It just implements an isave interface that you can implement for other type of save data
Maybe world grid etc
thanks, beginning to get a bit clearer(i think) ๐
I want to implement partial saving this weekend (which is also fundamental to subscene saving)
I realised there are some really cool dev tools you could make for this
By partial saving I mean filtered saving
Where you can specify a filter on what to save
Eg maybe only things with building component
I think you can make some really interesting tooling for development
Might make a quick video about the features after, I'm actually really into this surprisingly
Thought it'd be a chore
by filtered saving do you mean ArchetypeA with 123Component but ArchetypeB without 123Component? or something else?
Basically just passing in an Entity query
Does it match this query? If so save it otherwise ignore
By default it saves anything with the savable component or children with a savablelink component
But what if you only want to save or load 1 subscene while you run around the world open closing them
Or maybe you can create destructable buildings
It'd be cool for testing if you could only save that
Then destroy it
Don't like it? Undo
Tweak settings, destroy again
Without having to roll back entire world
Hey I'm trying to use these two methods to get voxels from a nativearray inside a burst job
this is used for initializing the job
job.voxels = NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr<Voxel>( chunk.voxels );
this is used inside the job
Voxel voxel = UnsafeUtility.ReadArrayElementWithStride<Voxel>(voxels, access, sizeof(ushort));
however it doesn't output the correct data from the NativeArray, is there anything i am missing?
Im not trying to edit the array i just want to read the array
Why are you reading with stride?
i tried ReadArrayElement it didnt work either ;/
I'd need to see more code but I don't think stride is what you want
It let's you partially read data
Eg if you have an array of structs of 2 ints you can stride read only the first int from all of them
because it was starting to lag so I wanted to convert it to a pointer instead
A native array is only a ptr though
Also you're getting the ptr of the native array
Not the pointer the native array holds
Chunk.voxel.getunsafeptr()
But yes this won't be any faster
can i pass a nativearray straight into a job without it complaining?
Also if you're starting with an initial capacity for a NativeList<ChunkVertex> of size 0, this will make your NativeList reallocate as the initial capacity is 0 and generally have more asm instructions executed per step
what is it complaining about?
it was canceling the job and disposing the nativearray due to race condictions because the nativearray was being used by multiple jobs
im not sure how you're scheduling the job, since that sounds like your dependencies weren't setup nicely for the scheduler to understand which jobs to execute first and which jobs to execute afterwards
im trying to get it so neighboring chunks have access to each others voxels in the job however I haven't really found a way to get that working with unity jobs
well i got it working by copying the data onto a new nativearray but that ended up slowing down the system
You have to turn off safety
how do i do that?
[NativeDisableSafety something blah blah
does your entire voxel world need to be 1 array though?
usually pretty standard to break it into chunks
which you seem to have already done
haven't really heard of it being merged back!
yeah its in chunks im just trying to get it so at the border of the chunk it can tell if theres a block visible in the chunk next to it
sadly 2021.3 does not add the required jobsutility methods/properties to port entities
guess they aren't going to release this early
bit weird you can run it in 2022 and 2020 but not 2021 ๐
Am I doing something wrong here? This has terrible performance with 250k entities. Around 6-7ms
i didn't write something silly >_>
anyway i'm not really sure what performance you expect with 250k entities (that's a lot) with such random memory access
i expect it to be faster than my other solution which just handles the race condition with an Interlocked
the problem is values in a multi hash map are not stored linearly
they can be anywhere
and in general native hashmap is not particularly fast to lookup
Hm, any good alternatives?
I'm already so frustrated about the NativeContainers. They all seem terrible, especially when it's about multi threading
do it in parallel?
you have a unique set of keys which are your target
which is the only data you're writing
so no reason each target can't be a different thread
It's the same target. it's a list of targets with a list of combat events.
It's setup so I don't have random access to all targets from the combat events
that's why I iterate over the keys and get its health component
so for my deserialization i can write like a million components back in less time than this
but what i do is i don't iterate the hashmap
i iterate all entities in a ijobentitybatch
then check if the entity exists in the hashmap
if not continue
no idea if it'll be faster for your implementation
depends on the % of entities in world to taking damage i guess
if I do this in parallel I have the race condition to the health component again
wait, can I use the multi hash map for an ijobentitybatch?
you simply go
entity target;
if (!_combatEvents.ContainsKey(target))
{
continue;
}
your query is just Health
everything with health
for my use cases this has been much faster than iterating the hash map
cant be certain it will be for you
okay makes sense. and then GetValuesForKey like I did?
hey i make my system to use NativeDisableContainerSafety thing but it still dosn't work how ever there is no errors it just returns a empty array
I'm 99% certain that I lose most of the time in the enumerator iteration. My test has a boss mob so I actually just have 1 target with lots of received combat events
If that's the case won't really help if you can't go wide
Guess I'd need a better data type where iteration doesn't hold me back
Or, for my sanitys sake, I just ignore this absolutely fruitless endeavour
I've clocked so many hours for this. It's getting to the point of insanity lol
still a damn shame, this is like the splinter in my head that keeps on nagging me
enzi... I know the feels... Been trying to make a MMO since 1992
I'm actually about legit 90 hours away from launch, but life man... Got really weird with family and stuff, keep the faith, keep the fight up, pray.
whats your game called?
My dots game now is https://www.starfightergeneral.com/ It is a precusor to a Tekken MMO I had working in house in 2003(like dragon ball Z), but my original mmo was turn based 2d written in Quick Basic abusing virtual disking for beating 640k memory called Intergalactic Bounty Hunter. IGBH was a poor format for a MMO anyway, so I rebooted it as a Table Top GM driven RPG and its better than anyone is using for D&D, but I borked the last build and want to get one live by June to play with friends again:
Igbh is here: https://www.crystalfighter.com/igbh/
I have about 5000 hours in my dots game and people I know put in about 600 on top.
The MMO launches in about 90 hours of dev time so probably 2 months earliest since I am moving place to place going broke. LOL
IGBH was based on an adaptation of D&D rules combined with Wasteland(before fallouts came out), and plays a lot like you'd think Cowboy Bebop mixed with Futurama, Spaceballs, Running Man and Demolition Man would be. It has this sick pulpy action that makes you want to take out dirty double crossing bounty hunters, makes you forget the grind completely until resolve, so you breathe in and boom, fun addictive grind there. Also crazy humor breaks stuff up. Everyone who plays IGBH goes,"This is the funnest pencil and paper RPG there is hands down." So I gotta publish it sometime.
IGBH universe is kinda the core of starfighter general... So we releasing action starfighter IGBH MMO and TTRPG within 2-3 months, just cuz I bounce between projects so much.
IGBH's been designed since 1989 and had thousands of hours of play test, it's sick and also a shame I never published yet.
My best trailer for Starfighter General now, is just out takes from devving, and this is a fun watch: https://www.youtube.com/watch?v=tq6Y5j9moR0&list=PLOQ-J23AJUfSCeuHkKQtL1Al70iAWnbSO&index=1
We unlock all your cores on your computer. Most all games well over 99.99xxx% of them only use one core. Today's games being released may use UNITY DOTS/ECS to unlock them all. - This allows 10-1000x as many things rendered and processed!
Networking as it hasn't been done before.Breaks all the rules that no one believes me except my beta tes...
If anyone wants on board, I use modern come and go rev share paradigm model where your revshare is based on hours * quality / total team hours* quality. I think it will break up actual game companies since I can literally be a game dev house and a game dev university at the same time training people as we go. I don't mind if I get talent sniped.
Quick question, how many projectiles do you have per frame (?) vs actors potentially being attacked (250k?)
E.g. What are the 2 worse case scenarios - max hits vs single target, and max targets hit
I don't have projectiles in that sense. They are like World of Warcraft instant spells. 250k on 1 target is my baseline for testing.
Which means, in a single frame 250k combat events can be produced. With my current method I clock at around 18ms altogether. I lose the most time on setting the IsCombat flag for a spellcaster because it's applied 250k times at the target (or at least needs to be checked, it's only written once) and applying a bitflag to for triggers like OnCrit/Hit/Dodge, etc... which are essential for some spells. Much of the overhead is because I can't linearize all the events to 1 target which would reduce a lot of the checks and data acquisition down
I've brought this problem up a LOT here already ๐ How to deal with a certain amount of combat events applied to random targets and how to accelerate the random access nature. I'm still in disbelief that my current solution is the best there is.
I'm using the UnsafeParallelBlockList from DreamingImLatios quite heavily in the project. It's like a NativeStream but a little faster. The latest thing I tried was having an UnsafeParallelBlockList for every spellcaster, so I could apply combat events in parallel to a target but the overhead of allocating and deallocating was around 700ms for 250k. I'd need some form of memory persistence but that just makes sense for this unrealistic test case and not really for a natural use-case, so I don't think persistence is the way to go. But maybe I'll give this another try
And I kept thinking about scraping the idea of, this has to work in 1 frame and spread things over more than 1 but as this should work eventually with the DOTS Netcode and prediction, it needs to work in the 1 frame budget
I'm probably overshooting the goal anyway. 10k in 1 frame is <1ms which is already unrealistic tbh
ok that's interesting
what i'm trying to figure out is if i can reverse it
because that's how i intend to implement my damage/spell system
which removes the whole concept of needing events
yeah, you can do that with projectiles and physics triggering on the collider.
makes sense. how do you plan to chain the data to the target though?
I honestly think that's the way to go. The problem is so deeply ingrained that turning the whole system on its head is probably a more fruitful approach
what do you mean by that sorry
like from the damage source to the target?
yeah
ok so im going to use projectiles (not instant attacks) just for the sake of an example
but say I have X projectiles and Y actors
instead of having each projectile X hit a target Y which requires making a spatial map of every actor Y
i'm going to build a spatial map of all the projectiles X and the Y actors are going to query if they are being hit
if so, take damage
i dont need to worry about thread safety or anything
because actors will only write to themselves
so in essence you still use physics, just a faster approach?
yeah i have a really fast nearest neighbour spatial map
i use for my orca implementation (rvo2)
which is just a nativehashmap with batchadd ^_^'
i do need to rewrite the lookup a bit though
but it's ridiculously fast to add to
that's crazy fast. makes me think if I could use this even for instant attacks. Thing is, the projectile works as a container for a delayed event so at some point this would very much converge in terms of performance
still 4x faster lookup than unitys bvh
but yeah what was that 0.56ms to add 200k elements
on a single thread
that was adding? ok, wtf ๐ to which data container is this added? the NHM?
nativemultihashmap
wow, I haven't timed my NHMs adds. Must be in the same ballpark because timings were still around 18ms when I tried NHMs. How do you consume them then?
this is my collection of native multi hash map high performance extensions
thx
thanks for sharing
so this is the performance difference on 100k
before
after
dear lord, you destroyed time!
the difference is i'm just memcpy the entire key and value arrays to the hashmap
then all i have to do is iterate the buckets and write the hash
instead of doing this 1 element at a time
it's called ClearAndAddBatch because it clears the hashmap first because it might have issues if you use it on a hashmap where you've added then removed elements
there are other addbatch methods i added in the last week for my saving
that have the same issue, but allow you to add multi values to a single key very fast
but should only be used on a hashmap that hasn't add an element removed
huh, that way you also have a memory aligned array for fast iteration
so yeah, AddBatch not 100% tested as i've only used it for a week though i have unit tests for them. use at own peril
i'm pretty confident in the stability of ClearAndAddBatch as i've been using it for months
rethinks life
If I have a multiple objects in my game with only a position component, but the position values are all different, would all of those objects still be considered the same archetype? And in DOTS, would it be possible to say "for anything of this archetype, I only want to interact with the one matches this position value"?
I have to think about this approach. If I can make this work so many problems could just vanish
see you can take this further if you want and something i'm probably going to do
since all values are actually grouped linearly
if you stored the start/end index you could just iterate like a native array
instead of the hashmap lookup that has to use the itearting and follow the buckets
i'm probably going to right my own version of a batch add only native hashmap
that i suspect will significantly increase lookup performance
i honestly expert a near magnitude in performance improvement for my orca when i get around to this
yeah, this trashes performance.
currently that lookup is by far my worst performance
its still great - i've been optimizing this orca system for like 18 months
it's like this optimization pet project of mine
i get stuck and leave it
and come back when i think of a new great idea
hehe, very nice!
sounds VERY useful, what you are making. spatial querying is like such a bread and butter for any engine
man, before rewriting all this which would take a few hours I need to figure out how much data is essential to allocate for my spell system. Basically every variable that would be needed for the target to calculate the spell it will receive from the caster has to be there. In the worst case, I'd need to write so much data that the cost outweighs the gains
yep unfortunately it's really hard to know any of this without doing it ๐ฆ
tertle can you just write all my systems, k thanks
i have spent many an hour optimizing something only for it to run slower =\
so true :/ worst case, I'd have random access the other way around. lol
you already get access to most of my libraries ๐
^^; ๐
that's pretty much the story of my spell system the last few months. although I've hardly worked on it this year when I was waiting for 0.50
have to hire you as architectural consultant ๐
@rotund token are your projectiles entities? how long does instantiating 200k take you?
i havent done any of this yet
my combat is just theoretical
but instantiating 200k entities takes at least like 20ms from memory so not really viable to do per frame
right, I was having that problem in the beginning when I modeled my spells as entities
i just like testing at 200k because if i can run a system at 200k entities i can run 20 similar costly systems at 10k entities!
which is much more likely to be the realistic scenario for my project
for targets to calculate their received spell I think I need a lot more processing power than I lose from the few bottlenecks. hm ... The problem is that I need to instantiate lots of data in some way
whereas now I can calculate in memory
damn, even machine learning image recognition was a more approachable problem
as I don't have a spatial query mechanism I even need a new stage where a target has to figure out from which of the 250k spellcasters it will receive a spell. feels like a dead end right now
Making something so fast that it can handle ridiculous edge cases that will never happen is both my passion and my downfall
when I'm stuck in optimizations I always get the Vikings theme in my head: This will never end 'cause I want more. More give me more give me more ๐
Optimising for 250k spellcasters while I'm working on a 2d rogue like that has 20 casters in a level. lol
and from all the errors I expected from importing my spellcasting package, I'd never have guessed that the only error that crops up is that a system can't find Camera.main
weird, I can only get the Camera.main in a system when "Enter play Mode options" is enabled
I'm trying to draw a mesh inside of a component system, but it requires a material and a mesh, I was thinking of just sending in my shader inside of the "new Material(shader)" as such, but I am not sure what the best way to do this is....Anyone got any ideas?
For material I'm doing this myself: new Material(Shader.Find("Sprites/Default"));
Is the .Find okay to use in a component? it's not slowing it down or something?
Component or System? You mentioned specifically ComponentSystem
yep, it's literally called Unity.Entities.ComponentSystem
Is this old or something and I should be using something else?
Oh, I only said component at first, my bad
Pretty new to DOTS, it's quite overwhelming because of the constant changes ^^;
Yeah ComponentSystem is super old, are you on 0.50? If so use SystemBase instead. But basically I have a Material field in my SpriteEntityRenderingSystem, so nothing is actually attached to the IComponentData itself, except a rectangle that represents the sprite on a sprite sheet (since I'm rendering sprites)
So in my case I simply retrieve the correct sprite shader & material once in OnCreate()
This sounds very similar to the thing I saw from Code Monkey on his tutorial.
I basically mashed together his "how to render a sprite" and his "sprite sheet rendering system"
But that clear some things up, I am indeed on the 0.50 version
It didn't say deprecated or anything on the component system inside the code, so I just continued to use it
Probably cause it's still heavily in development so they just forgot the deprecated attribute. I haven't actually seen the video you mentioned but I assume it's very similar since it's a very simple and straight forward way to do it.
yeah, shaders are a magic box of wonders though, need to try and figure out what is wrong with this...
It seems like JobsUtility.MaxJobThreadCount is hardcoded to 128, and NativeSetThreadIndex indeed use the full range, that seems a bit weird?
For context I'm trying to allocate a large disposable container for each thread (let's say a float array of 4096 elements) so each thread in theory should only take up 4096 * 4 = 16 KB of memory
But because of that fact I have no choice but to allocate 128 * 4096 * 4 = 2 MB of memory, no matter the amount of actual concurrent threads.
I originally was planning to have the container to be much bigger, but because of this I have no choice but to limit it to 4096 to have a reasonable memory usage, despite most of that 2 MB is completely unused.
This is probably purposeful because the idea is to limit the number of threads down to the number of threads on the CPU. One Job thread per CPU. That is why the limit is set at 128 since no computers have more than 128 CPUs right now.
Jobs are not really threads. You can work on containers from multiple threads without problems.
Unless I'm misunderstanding your point, that's not the issue at hand
I may not understand your question either.
If I have a 4 core mobile device, in theory I only need 4 * 16 KB, but I have no choice but to allocate 128 * 16 KB.
Why do you need to allocate these per thread though. I guess I don't understand.
c# Threading and Jobs are very different although they do similar things.
Thread or jobs running in parallel, whatever the correct terminology is.
I use parallel jobs for running my custom script system, and each job should have its own chunk of disposable memory to use
It doesn't matter what the state of the memory is, all it needs is that each job can operate on its own without conflicting with other jobs.
I imagine it's much cheaper to just allocate once and reuse, instead of allocate every time a job runs and disposes at the end.
Okay so you can create a container
and then have each job operate on part of it. You don't have to worry about creating an allocator per job.
You will have to add [DisableNativeRestrictions]
So when you schedule a job, you can have an index.
Yes that's NativeSetThreadIndex
Except it uses the full range of JobsUtility.MaxJobThreadCount which is hardcoded to 128.
Even if the device is only a 4 core, you still have to allocate 128 times the amount you want for each job.
why do you have to do that?
How would you ensure two parallel jobs running at the same time are not writing into the same chunk of containers, if not using NativeSetThreadIndex?
I guess what are you trying to do instead? Cause you aren't creating the native containers to do nothing with them?
Making sure you only write in a certain range when you execute each job?
are you looking to read and write in each container?
How do you know which ranges are available when jobs are running in parallel?
So for example, you can index on a NativeArray
NativeArray<int2> ranges
So then ranges[0] = 0,3
Okay I think that's what we are missing
ranges[1] = 3,3
ranges[2] = 6,10
And then each job you want to index on that ranges
x -> the starting index and y -> the length
Let's say I have 20k jobs I want to run, each job needs a 16 KB chunck of memory it can manipulate (but it doesn't care about what values they have, they just have to be conflict free with other jobs)
So then when doing each job, you read that NativeArray and just make sure you don't write outside of those ranges or you will get race conditions
You solution would be to allocate 16 KB chunk for every single job, which will be GBs of memory.
Is 20k jobs the same type of job (doing the same stuff) or is 20k different jobs?
I'm not getting you, why would that matter?
Each job just needs a 16 KB memory that it owns and conflict free with other jobs, it doesn't care what other jobs are doing.
Cause executing the same job 20k times versus executing 20k different jobs is a very different thing.
It doesn't matter, let's say they are all the same job.
Do you then just allocate 16 KB * 20k jobs = ~300 MB of memory?
I don't know where you are getting 16kb from
is this referring to ECS or straight jobs
16 KB is my own requirement
I want each job to have 16 KB of memory that it can operate on.
16KB X20k jobs yeah, 300 MB then you are good
Why, you need 16KBs for each job. You said that yourself.
16 KB dispoable memory that each job doesn't care the initial values or the ending values.
In reality, I know for example the device I'm running on only has 4 cores, so there can ever only be 4 jobs running in parallel at the same time
I could instead just allocate 16 KB * 4 and give them to each job, not 16 KB * 20k.
Jobs != Threads. You can run 1 job that operates on 4 CPUs or the same job can run on 8 CPUs
It doesn't matter, if I know there can ever be 10 jobs running in parallel, then I only need 16 KB * 10, not 16 KB * 20k.
So you are very familiar with threading right?
I wouldn't say so, but go on.
I don't know anything about threading and I think that was helpful. Because Jobs and Threads are very different in how they are implemented.
Like talking about allocating memory isn't really what is needed. You want to figure out what data you want to act upon and write a job around that. You will only need to allocate the amount of memory to do your work. The only thing that is annoying about jobs is that you need to know how much your output is going to be so you can allocate the correct exit amount of info at the end.
I think you are still missing the point.
Okay, have a nice day.
The requirement is that each job needs its own 16 KB chunk of memory that's used only during its execution, and what intial values or the final values of that chunk of memory does not matter
You need to review how jobs work, you aren't using them as intended. It isn't C# threading.
Now imagine I have to run 20k jobs on a single core machine, I just need to allocate 16 KB, let the first job have it and let the first job do its thing.
Because this is a single core machine, only ever one job can be run at a time, so first job must finish becore the second job can start, hence I don't need to allocate another 16 KB for the second job, and I can just let the second job reuse the same 16 KB that was used by the first job.
Asking about your attempted solution rather than your actual problem
This means that despite I need to run 20k jobs, I do not need to allocate 16 KB * 20k of memory, I only need 16 KB * 1 memory because it's single core.
Well I'm not having XY problem, my exact requirement is just that:
each job needs its own 16 KB chunk of memory that's used only during its execution, and what intial values or the final values of that chunk of memory does not matter.
You can allocate 16 KB * 20k but that's horrible inefficient like I pointed out.
@lusty otter I had the same exact problem and till now I have not gotten a clear answer to this problem. From experts like tertle and DreamingImLatios it's clear to use the JobsUtility max worker count (128) and from Unity samples too. I also wish it was different because it screws up laying out memory in advance
the bottom has a multi threaded counter sample https://docs.unity3d.com/Packages/com.unity.jobs@0.1/manual/custom_job_types.html
Yes the minimum amount of memory required is (the size you actually need + JobsUtility.CacheLineSize) * JobsUtility.MaxJobThreadCount
Which is a huge waste because JobsUtility.MaxJobThreadCount is hardcoded to 128 no matter the actual device.
maybe you have more luck with the JobWorkerCount
That's not possible either unless we have a way to obtain which worker we are executing in.
Because NativeSetThreadIndex uses the full 128 range.
Personally I only witnessed 0-6 from NativeSetThreadIndex. But anyway, this is not working out then so you'd have to implement something yourself
That's an undocumented behavior even if it's true and can't be relied upon.
From this post the result shows they got up to 29 https://forum.unity.com/threads/counting-job-iterations.836017/#post-5542054
Either way I'm not exactly sure how to make something custom either, assuming we obtain the max amount of workers and allocate based on that, we still need to let each job communicate that they are taking/returning one of the allocated chunks without conflicting with other parallel jobs running atm, and I think that must be locked during the taking/returning part of each job to ensure no race condition.
Well, this is all assuming allocating once and reusing it over and over, is cheaper than every job doing 16 KB of Allocator.Temporary and dispose at the end.
I assume it is.
I think I have two packages: GUID [2c8fd13e93ac9424599cbebab2f01cc2] for asset 'Packages/com.unity.entities/Editor Default Resources/icons/dark/Convert/Convert.png' conflicts with:
'Packages/com.unity.dots.editor/Editor Default Resources/icons/dark/Convert/Convert.png' (current owner)
I'm upgrading to .50 from .17
delete com.unity.dots.editor
ty
this has been merged into the entities package
ty ty
Library\PackageCache\com.unity.entities@0.50.0-preview.24\Unity.Entities.Editor\Unity.InternalAPIEditorBridge.002\ProfilerModules\StructuralChangesProfilerModuleBridge.cs(4,23): error CS0234: The type or namespace name 'Editor' does not exist in the namespace 'Unity.Profiling' (are you missing an assembly reference?)
Remove profiler?
In : https://docs.unity3d.com/Packages/com.unity.entities@0.50/manual/upgrade-guide.html#partial How do I find DOTS->DOTS COMPILER
Goodnight I'm stuck. Cya tomorrow.
Have a good one guys. The finish line always seems so close.
Blizzard themselves shouted me out, proof: https://www.crystalfighter.com/achieve/starcraft/achieve.html
www.starfightergeneral.com
#1 SENNA MASTERY NA
Banned on Twitch for saying terrorism, drug cartels and execution of Hong Kong peaceful protestors are evil. Three strikes, no appeals won. Amazons says that if you report human rights abuse...
what version of unity are you using? this looks like an error you see on 2021/2022
2020.3.25f1
It is an older version, let me update
I was stuck on it because the newer ones weren't running, maybe that's when .5 started being a thing. Good catch.
you have to use 2020.3.30+
Astute finding, thanks tertle bro
Not everything converted fine as I had to comment out scripts like collision... But I got to .5. I should be okay now.
Goodnight
long day
is it possible to customize the inspector drawer for entity components?
I have ~120k entities, all of which have a component that a system checks. Said system takes a while to check all of them. It has an early return clause (if one of the variable in the component is -1, it returns, which is true for 99.9% of components), what's a more efficient way of handling this ?
the answer to this for anyone who stumbles upon this in the future is yes, you just have to defined a class that inherits from Inspector<The IComponentData you want to modify>
public abstract class ConversionInspector<T, U> : Inspector<T>
{
private PropertyElement elem;
public override VisualElement Build()
{
var inspectorObj = ToInspectorType(Target);
elem = new PropertyElement();
elem.SetTarget(inspectorObj);
elem.OnChanged += (elem, path) =>
{
Target = FromInspectorType(elem.GetTarget<U>());
};
return elem;
}
public override void Update()
{
if (elem != null)
{
var inspectorObj = ToInspectorType(Target);
elem.SetTarget(inspectorObj);
}
}
public abstract U ToInspectorType(T obj);
public abstract T FromInspectorType(U obj);
}```
if anyone else finds this useful for Components that have a packed format
Also fwiw you can use arbitrary structs that are the same size as Float4s and pass them into shaders
Via the instancing mechanism
Nothing complains and the bytes come through unharmed
what are you using this for out of curiosity..
Rendering a bunch of instanced scaled blocks
And giving them the information they need to calculate their textures
So I can tile textures across them seamlessly
They can all be colored individually
And the textures map across blocks and slopes
Nice, that's interesting, i've never tried anything like that tbh
Do you pass the structs into shaders inside jobs or outwith?
Before I ported this to ECS I was dumping them in a structured buffer attached to the material
But hybrid renderer let's you pass property overrides per entity
So I am just doing that
Is there a performance difference with this approach, compared to your old method
I'm guessing it provides a more optimized way of uploading data to the gpu
I think it's actually slower
I am guessing they are using the same method internally
More of a native->gpu buffers rather than managed->gpu
Of a structured buffer
Yes it is
I don't actually know it it's slower
But I was already dumping from a native array
Ah right
Trying to learn ECS by mass producing animated sprites, but I was curious if anyone know how I should properly call Graphics.DrawMesh()
inside a job or Entities.ForEach method?
Or any other method I can go about this ofc.
For JobsUtility.CacheLineSize, how do I utilize it properly?
Let's say I have an NativeArray<byte> of 128 elements, if I get arr[63], does it fetch [0] to [63], or [63] to [126]?
'ICollisionEventJobExtensions.Schedule is obsolete: 'Schedule() has been deprecated. Use the new method that doesn't take PhysicsWorld.
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
An alternative question would be: How do I do SystemBase Collision and Triggers?
Maybe they should make an integrated script on this.
Hello, can anyone confirm if this link : https://forum.unity.com/threads/outdated-thread-easy-to-use-trigger-collision-events-system.878203/ IS a good way to do collisions/triggers?
uh you meant the thread that says OUTDATED in the title?
@remote crater I believe you want to do something like this?
SimulationCallbacks.Callback callback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) =>
{
inDeps.Complete(); //<todo Needed to initialize our modifier
return new DisablePairsJob
{
Bodies = m_PhysicsWorld.PhysicsWorld.Bodies,
Motions = m_PhysicsWorld.PhysicsWorld.MotionVelocities
}.Schedule(simulation, ref world, Dependency);
};
m_StepPhysicsWorld.EnqueueCallback(SimulationCallbacks.Phase.PostCreateDispatchPairs, callback);```
Thank you. Let me ascertain what is going on here.
I think you want to schedule the collision job in a similar way using a SimulationCallback
Is this the latest and greatest way of doing collisions?
I think I used an older way, but I could not find another way.
I want to use the modern accepted way if I am spending days upgrading to .5
Ok man, it has to be then. That code snippet had many errors, I'll click the .cs file
Maybe the whole file makes more sense. Much appreciated!
Look, I only have one question about this...
What is iSimulation?
Oh I can't because it is a html file.
Is iSimulation how .5 does things now?
Or is it specific to that program?
I strongly suggest downloading the repo and opening the physics samples in unity and visual studio
You got me curious enough to download the .zip
they have a decent amount of usecases covered in there
Thank you very much derekt.
heard someone say hybrid renderer is required for ECS 0.5, is that correct?
If you want to render entities it is
Gotcha, so if I want to do a 2D game, start up the 2D and just import com.unity.rendering.hybrid, ye?
Yes,
side note I donโt think sprites have a native dots equivalent yet
I know, have been using some sketchy entities with graphics.drawmesh and shaders to create animations, but I really need to find a way to do it the "right way", so if someone has that info, do share. since my project broke after the 0.5 upgrade ^^;
There have been some good threads in the forum on custom sprite rendering solutions using direct Graphics calls. Their solutions might be superficially obsolete at this point, but they're still fundamentally workable, I believe.
yeah, I was using one from a youtuber, but that one was like 2 years old at this point and now obsolete.
better check the forum
This is a good one that was at least updated to 0.17: https://github.com/fabriziospadaro/SpriteSheetRenderer
I think I need to give it a go myself since I need to handle sprite animation speed too...
The fundamentals are the same across these solutions: incrementally update compute buffers rendered using Graphics.DrawMeshInstancedIndirect, or something like that
Is animation even on the 1.0 roadmap, or will it be "later"?
Like everything else...
later
Thank you, mindstyler! And sorry for pinging you, thelebaron. I know I could have looked it up myself. I was just hoping to commiserate over all of these many roadmap "later"s ๐ฅฒ
theres actually an update about it
totally cool with pings ๐
i am disappointed(as always ๐ฅฒ ) there wasnt some sort of intermediary releases but relieved to have some real update on the matter, and not "were reevaluating" like the original roadmap phrased
Cool! I had thought it was weird how they punted on a package that seems pretty well developed, but I guess they're taking a longer view on it
yeah, now if only we could get an update to audio ๐
actually I wish all dots packages had roadmaps/updates that frank
Yeah, audio is still the big question mark for me
that's interesting.. seems animation will be a fairly substantial update when it finally gets here
i do hope, re that first reply, that they create a new ground up alternative to Animator.. as a generalist i've done a lot of character stuff over the years in various software and i can honestly say that even to this day, trying to build a robust and predictable character setup with Animators state machine is just layer upon layer of pain
Tbh I don't see how you can even release DOTS as 1.0 without animation
Well as they said, as an hybrid with GOs. So with mecanim in mind.
I thought it was interesting a card about navigation was added in context of animation, or maybe more weird?
gd point actually
Hello, what's the default size of an ArchetypeChunk?
any specific reason?
in UE for instance chunks are 128 bytes per line x 1024 lines
which makes up for the size of modern caches
what do you mean by in UE?
I didn't think they had an ECS framework
oh they do, it's called Mass
and I found super odd that the chunk size is 128 x 1024 there, because no current cache size uses 128 bytes per line
well GPU caches are 128bytes
as do M1 cpus
probably influenced by the whole unified memory thing with the GPU
or probably a distant look to the future
not sure, this system is brand new might be the case
so i assume in unity chunks go contiguous in memory and they do have this sort of struct of arrays kind of hierarchy by what I read
so effectively multiple chunks fit in cache
yes a chunk is header data + arrays of each component
as for the size, is there any comment made by the devs that you know of?
any reasonale by these default values?
one can only guess
I think they commented once long ago about making it configurable
but that hasn't happened
Okay! Thank you so much derekt, a pleasure :)
I've tried smaller chunk sizes recently (atm I've settled on 4kb chunk sizes instead of 16kb, I haven't found any recommendations either)
I tried making a 1kb chunk and got an error so I didn't bother testing 2kb chunk sizes ๐
Pretty sure they locked it to 16kb for some reason
Yea - probably for scale, not sure what I'm missing with shrinking the chunk size to 4kb, but my chunk utilization with 16kb isn't that good since my game isn't that large.
chunk size has nothing to do with cpu cache lines according to Joachim
AFAIK they just picked a reasonable number
not too big, not too small
cool good to know
hopefully we can change chunk size individually based on archetypes in 1.0 ๐
Does someone have any tips on how to deal with asmdefs and DOTS? Every asmdef I make I have to add like 10 references everytime
Haha yeah, I have an asmdef builder
i love fixing performance hotspots and achieving 0.2ms improvements in a job that takes 6.8ms /s
Seems like caching the pointer value for a BlobAssetReference out of a NHM is pretty much worthless even when it's 250k times the same key that is looked up
UE Mass info source?
a reliable performance profiler would be great. The VS2022 performance profiler seems nice but the timings are really off somehow
not sure why
What do you use the VS2022 profiler for? Can it do things Unity's profiler cannot?
yes, it shows cpu ticks for each line of code. something a REAL profiler is capable of ๐
but the timings are really off somehow
except it's not actually that capable of doing it
hehe, well it's not working that well for unity and burst. I've to attach the performance profiler to the unity instance itself
but for my .net core server it's wonderful ๐
i currently have 15 markers in my job and unity is choking hard lol
Uh what
What are you trying to profile like that
You're introducing so much overhead via the profiler you're probably not profiling anything worthwhile
if i need to actually optimize something i mostly just write performance tests
Yea if you want to optimize something
Run it 10k times in a tight loop
And measure that timing
Trying to profile pieces of a job is going to be wierd at best
the job has 600 locs and relies on components and blob data. the performance characteristics are pretty much lost on me at this point
Break it apart into static functions
That you can measure separately
Use the unit testing framework
To setup the timing runs
yeah, maybe. it's like, how do I know at this point if it's better to have blobdata or a big struct, you know? there are so many unknowns currently how to proceed
The only way to know is to benchmark both options
guess I have to because the profiler is garbage ๐
No the profiler is great for giving you a high level overview of performance and where you're spending time
It's not really meant for precision optimization of chunks of code
yeah, with like 2-3 markers
Also code running in debug/profile markers can have such dramatically different runtime characteristics
From release code
And you want fast release code
Not code that's faster in the profiler
๐ฎ
How about CPU cache misses?
vs can't do that, but Intel VTune which is a total beast
Ya that info is very nice
Have you tried WPA?
I've used it successfully before but not with unity
I think it should be able to work on Unity tho
it can show you stuff you never thought of. like ram utilization and stuff that totally goes over my head like sse misses/utilization etc..
stats for how good you're multithreading. pretty great overall, thing is it wasn't that helpful in my case and pretty much had an output very similar to VS. I'd like to know where my cpu time goes to but if it's just a little everywhere and the sum of its parts profiling gets really useless. There's no real "problem" the problem is more global and this is one I don't know how to solve in a better way
in my particular case, casters cast a spell and the spell data is in a blob. the blob is pretty huge and lots of checks are necessary which slow everything down.
of course every read in the blob is a total cache miss so it's not good to begin with
and the relation from caster -> spell -> target is problematic in itself. I've not found a way to run this all enclosed and local to its data.
probably should just start from scratch ๐คฃ
but on a more serious note, that's actually why i use performance tests. so i can keep my original implementation and rewrite large chunks of it and see how it compares
I honestly don't have a problem with starting from scratch but I don't have any solution for the problem ๐
only one idea is floating in my head and that has to do with source generators. basically translate spell data into code
and have a polymorphic solution for most of the code
The way I do it know seems like a dead end and if I'm stuck that much a bigger form of rethinking is to be in order. And the biggest contender for that is to rethink the data layout of spells itself and if it even makes sense
what's a reasonable way to get a local struct copy of a BlobAssetReference value? just new a struct and memcpy?
eh, I'm not allowed to anyway with the MayOnlyLiveInBlobStorageViolation error :/
I'm not sure why that's a thing. Unity is usually pretty happy with giving you back struct copies.
pretty sure this is top making a copy of blobarray
with has a pointer into the blob
modifying it and breaking your subscene
understandable with BlobAssetReference<T> but not with T itself
this is one actual case where I want to get a copy for localities sake and I can't. I don't know how the check is implemented, seems to me that any struct that has BlobPtr or BlobArray is affected
I've been a bit curious about what's the "proper" way to handle timers in ECS -- take for example a Buff system in a RPG.
My buff would be something like a DOT (Damage over Time). So, deal 10 damage every second, for 10 seconds. What's a standard way to handle this sort of timing?
Assume I have a lot of entities, so iterating over every single buff is expensive.
is it though?
~120k entities that can have buffs, most have 1 or more
use ticks, start tick and end tick. that way you only have to compare against the tick itself and not have to calculate any time or deal with offsets
That's what I've been doing so far. DateTime.UtcNow to Tick and just store longs.
But I feel like it won't scale well if I'm checking every buff
why are you using datetime instead of the game time?
what if you wanted to slow/speed time or pause the game in future
I won't have that need
do you not want to save your game?
just checking the currentTick against endtick is really not a problem and pretty much the fastest thing you can do
It's just a server, not a client. I have a database system plugged into it to save, which is why I want to save in "real" time. If my user has a buff that lasts 3 days, it has to be real time
uint for ticks is more than enough. don't use a long
if you take server down to patch it
save all the buffs
then start the server back up again
all your buffs will instantly expire
Yes. That's desirable
๐คทโโ๏ธ i can not think of a single reason to use datetime but ok go with it
All my needs are figured out. I'm basically recreating an existing server into unity ECS
it's okay, there are worse things to do ๐
very true, I noticed ticks are 0.1 microseconds which is probably within margin of error
depends on the simulation framerate how long your tick actually is
I'm hesitating between two different "philosophies" for buffs:
The classic "my unit entity has a list of buff" and the more ECS "my buff is an entity"
but if you use dateTime that doesn't matter really
Having used the first option as a fast test, the second ECS option seems more appropriate now
For the record, DateTime.UtcNow accuracy is ~16ms
i prefer my buff is an entity. depends on how complex the buffs are. if it's just a flag with maybe 1-2 values you could also use a DynamicBuffer on the unit entity
on windows systems
It will end up being a dozen values, so Entity it is
problem with buff as an entity is it's hard to write results in parallel
personally i have a polymorphic buffer on the entity for this
i tested it about a million buffs on 100k entities and it did ok
I'm interested in more on that if you're willing to share
are you using a DynamicBuffer and is this buffer limited in its size?
yes and no
can't really live in chunk space, right?
the system is designed to have 100+ buffs at once per entity
so i dont care that much if it lives in the chunk
trying to find the video that inspired me
so then the buffer lives randomly in heap?
which begs the question, what is better about it than having entities for buffs?
because i can do it all in parallel
if i have 2 entities doing damage to a single entity it gets quite messy
but this system isn't just damage
it's everything
it's unlocks
it's character stats
so, the parallel problem comes up when buff on entity A does damage and lives in chunk1 and another buff on entity A does damage and lives in chunk2?
of course
well, just do Interlocked ๐
I didn't have much luck with performance and dynamicBuffers
i know i've seen your many complaints
personally i have no issue with them
my performance testing benchmarks have them at good enough to exactly the same performance as nativearrays
wrote a huge bunch of testing after i saw your issues
and could not find an issue
that's odd, I have even tried this with optimising struct size data in DBs. There's absurd overhead, not the actual writing but the rest
if you do AsArray on them
and you seem to use very large data even in heap so that's extra odd if that comes close to NativeArray performance
they are literally the same as a Persistent allocated native array
persistent allocated are slower in itself so that's not a good benchmark
have you compared reading back a temp/tempjob/persistent array?
they are really only slowing on allocating
sorry i got ot run to a gym class, i cant find this video i'll look again when i'm home
was on youtube, was this really popular game did a talk about their attribute/stat/effect data driven architecture
I have not done it explicitly. Just did the DB tests and compared against other solutions. Maybe I need to redo them ๐
was really obscure but was a fantastic video
see you later then. I'm interested in the video
that said, this is a great solution if all you care about is direct changes like this
brb
Do you think we will ever get to completely switch over to an ECS workflow?
As in be able to select to use ECS at project creation and be completely rid of the GameObject workflow for that project?
probably not for a long time if ever
The gameobject authoring workflow is really nice
having a different representation for edit time vs runtime can be very useful
Yep, that's the thing. They seem to want to do it that way instead
Obviously so that people don't have to re-learn Unity
I use almost pure ECS for now
Only one game object to boot up my server, and I could probably make that into a system
pure ECS is great when you don't need animations ๐
I don't need a client at all which helps
In this 2017 GDC talk, Ubisoft's Aurelie Le Chevalier dives into For Honor's modifiers system, a data-driven system that allows designers to dynamically create gameplay effects, that can handle anything from simply buffing/debuffing character stats (damage, speed, etc.), AI decision-making, areas of effects, and attack properties.
Register for ...
I found it finally
Thought this was quite an interesting talk
From memory not the most engaging talk to start with, but I found the concepts very interesting
ah thanks, I know that talk ๐ your mentioning of obscure game threw me off haha
but yeah, that's a really good talk. very indepth and technical
tertle, how are you planning to handling triggers? for example, you have a buff and every time you get damaged you explode, dealing AoE damage to others. You don't seem to have an intermediate stage to handle this if I got you right.
Any of the attributes can have code attached to it to execute
That bit isn't hard, though I'm not certain on the performance yet I haven't benched it
I haven't touched this system in 2 months since I proof concept it
That sounds a whole lot like what I need for my purposes
So I'm not certain I'll stick with this for everything
I think a mix depending on the type
From memory I had 5 different type of attribute
Like stats, buff, I can't remember rest
I'm not certain all categories make sense to be this system
Atm they exist in 5 seperate buffers because each type can be optimised differently
I have an Effect system with ~150 different effect types, all requiring specific code. What's a good way to do that, in your opinion ?
Said system has ~20 effects with a lot of data, and ~130 that just take in 4 integers as parameters
Tram just arrived at gym, back in like 2 hours
What I'm talking about though requires a lot of low level code
damn, when a small condition chain takes 0.42ms. they break performance and are so hard to avoid ๐ฆ
i need to improve this ๐
Just spent the whole gym session thinking up a new way to do my attributes
Or I should say, breaking it in 2
Mostly thinking about how I want to easily incorporate it with my save system
Ah yes logic, performances enemy
From a quick look I think you could probably do it branch less and probably simd
But I'm not sure it'd actually be faster
I feel like this would be one of those cases I spend the time doing this and the code looks gross but the assembly looks amazing, then I throw it in a performance test head to head
And it's just slower
haha, I shaved 0.17 ms off with reducing the condition levels and turning the code to switch with 1 conditional operator.
simple enough, should work as the other code
Yeah that's much better
still, I'm always perplexed how much some if/else take
yeah right I always forget that this is a thing now with burst
Like I assume hostile would be more likely than friendly for most games
correct, maybe it helps if I just move the Hostile check to the top
say, in your project where you use buffs, etc... where is this data stored?
do you have some form of database?
That buffs attribute stuff is an experimental library not actually in my project atm
As for where I store the data, I can't actually remember
I'll check when I get home
ah ok, thanks! ๐
For my Ai which isn't too dissimilar I created a custom allocator and stored all per node data in a single giant chunk of memory
That's setup during 'conversion'
very interesting, I wanted to convert many of my data to "big chunks of memory"
I was hoping to do away with it and switch to unitys new allocators
But they haven't added enough support just yet to everything I need
the blob data isn't too great for my spells. There are lots of attributes that are optional, so I have to use a BlobPtr and a conditional check if it exists in the code
So cbf doing their work for them
Would you be better off defining them as seperate spells? During your authoring you can have conditions that generate a different conditions spell for runtime work
Can't be fucked
lol that's a first I've read this ๐
I'm turning 38 soon so not long and I'm a boomer
Well then, you're just a touch older than me boomer
great, then I have the perfect excuse to not understand your abbreviations
Not too bad of an idea actually but how would I hold this all together?
No idea how your system actually works
So can't really say
yeah, my bad ๐ I need to think about how to handle the complex stage of "is this spell allowed" without conditions. any ideas?
About to get home then let you show you my Ai and how I'm going to base my skill system on it
seems impossible to me. my brain is so used to if/else
I'm not going too claim it'll be as fast though
It's more about flexibly
And having design being able to build completely new things from data and a graph
It is fast though
mine is also about flexibility and then I went down the rabbit hole of performance
It can model any FFXIV/WoW spell already, very conveniently, so that's pretty great in itself
You know the ability system from ue?
Now it's more about, yeah, performance of course and staying also flexible in the code base. I think on that front yours is a lot better
Think that
yeah I know it, not in depth but enough to know it's pretty cool! ๐
Oh I don't know it in depth either having never used it
so yours is VERY modular then?
Completely you can reorder graphs at runtime
To change how the logic connects
It's all 1 job
Just a giant graph
mine is very tailored to what people are used to from MMO like spells
oh wow that's a cool feature
remember im talking about my AI, im just going to base my ability system off the exact same thing
since i have the tech stack for it already
finally at a pc let me show you it quickly
to show you what i mean
that's a very powerful tech stack if you can do such vastly different stuff with it
at the end of the day all it is is a graph
most of the work is
a) in the memory and linking it
b) in the UI
you are putting it mildly hehe
i was mostly shocked that it performed well
lots of simd usage?
because its downside because for the most part it loses the ability to simd and have a good cache
well, if it still performs great, it hardly matters
what it gains is 100% thread utilization and no job or system overhead
yeah so it's done exceptionally well in any test i've thrown it at
my concern is i haven't used it in production code yet
ive put a lot of effort into this so it's going to suck when it finally goes into production
and just fails on something
find out in a few months i guess
interesting concept to say the least. I wonder how much actual coding will be relevant in a few years. I mean, if you look at the evolution of shaders. There will always be a place for manually coded shaders but so much power lies in graph based approaches
it's absurd how powerful they can be
i shouldn't say it doesn't use simd at all
the actual graph playback doesn't but i have a system running beforehand that normalizes data etc that most AI systems would need
i'm afk for a few minutes
thats a shame about to post some stuff ๐
this is what my graph looks like for example
you can link multiple graphs together
each entity just has a single buffer on them
public struct AI : IBufferElementData
{
/// <summary> Gets the key to the graph. </summary>
public int Key;
/// <summary> Gets the number of frames between updates. </summary>
public int UpdateEveryXFrames;
/// <summary> Gets a value indicating whether the AI is enabled. </summary>
public bool Enabled;
/// <summary>
/// How many frames before the AI should update again.
/// To avoid updating all AI on the same frame, if you are instantiating AI from code this should be set to a random value.
/// e.g. Random.Range(0, ai.UpdateEveryXFrames) + 1
/// AI in a subscene are given a random value during conversion.
/// </summary>
public int FramesBeforeNextUpdate;
}```
which has a key which points to a graph in a hashmap
(as you can see it also has a convenient benefit of easily allows timeslicing certain AI routines but that's not really relevant to this)
then the entire AI job pretty much comes down to this (excluding slicing)
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (result && graph.IsCreated)
#endif
{
graph.Value.Select(in entityContext, ref this.Context);
}```
i'm back. that's really cool!
to make changes at runtime, you change the graph however you want
then just hit a button that reassigns the entityContext.Graphs
so the next frame they'd be reading different chunk of memory and new graphs
i made the whole thing generic as well
which was a huge pain
but this means you can extend it in any project
here is what a node looks like for example
{
private bool not;
private float score;
/// <inheritdoc/>
public float Score(in EntityContext<AIContext> entityContext, ref AIContext context)
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
if (!context.Workers.Exists)
{
Debug.LogError($"Entity({entityContext.Entity.Index},{entityContext.Entity.Version}) is not a worker but using {nameof(CanCarryMoreResources)}");
return 0f;
}
#endif
var worker = context.Workers[entityContext.EntityIndexInChunk];
if (worker.CurrentCarriedResources < worker.MaxCarriableResources)
{
return this.not ? 0f : this.score;
}
return this.not ? this.score : 0f;
}
/// <summary> Factory for <see cref="HasResourceTarget"/>. </summary>
[Preserve]
public class Factory : Scorer<AIContext>.Factory<CanCarryMoreResources>
{
/// <inheritdoc/>
public override short ScorerType => (short)ScorerTypes.CanCarryMoreResources;
/// <inheritdoc/>
public override string DefaultName => "Can Carry More Resources";
public bool Not { get; set; }
/// <summary> Gets or sets the selector the action is linked to. Null is valid. </summary>
public float Score { get; set; } = 1f;
/// <inheritdoc/>
protected override void Init(ref CanCarryMoreResources scorer, MemoryAllocator allocator)
{
scorer.not = this.Not;
scorer.score = this.Score;
}
}
}```
Factory is for creation/UI
and this is how it's called from a completely separate library
{
/// <inheritdoc/>
float IContext<AIContext>.CustomScorers(short scorerType, Scorers<AIContext> scorer, in EntityContext<AIContext> entityContext, ref AIContext context)
{
return scorerType switch
{
(short)ScorerTypes.Hastarget => scorer.Score<HasEntityInMemory>(entityContext, ref context),
(short)ScorerTypes.HasResourceTarget => scorer.Score<HasResourceTarget>(entityContext, ref context),
_ => 0,
};
}
}```
holy shit, the stuff you are making! ๐ I hope this finds success as an asset
im hiding a lot of unsafe code here from end user
yeah ive been meaning to release it as an asset for over a year
i'm just too lazy to write documentation
get on it! it'll be worth it in the end
you dont realize how lazy i am
i probably have like half a dozen assets i could release for dots
that are really polished
OH there is something else really cool about this AI library
it records the state and path that every AI asset took every frame
so you can play back exactly what the AI was doing over the last X frames
to see why it did something
you are not lazy ๐ releasing something paid to the public with proper documentation is just something else.
I know the process when I released my camera in 2015 or smth. Writing the documentation for it sucked and I always got the feel of this is too complicated, endless amounts of support questions and other stuff that just ticked me off
i cant even bebothered showing it off on the forum in all those how to do ai threads
btw
i found at least 6 major burst bugs writing this AI
if you've ever seen some obscure bug fix in the burst patch notes with my name on it
it came from this AI system
all these weird pointer casting issues with generics
probably a lot harder when you have a job you like ๐ but having another good income stream for your talent is always a plus
yeah, saw your name couple of times. guess you are one of the few who does this crazy stuff with burst
I'm not even scratching the surface of burst :/
i just enjoy trying some weird obscure things
to see what's possible
favourite piece of code I ever wrote was something I have called
K
private struct BurstTest : IJob
{
public NativeReference<uint> Result;
public void Execute()
{
this.Result.Value = K<KTests>.NameToKey("test4");
}
}```
this is K
K lets you assign keys, layers, etc in setting files
and then read them anywhere you want, burst included
think
classical unity
LayerMask.NameToLayer()
oh sounds useful, especially for burst
where does K store stuff?
in KMap ๐คฃ
I should have figured that out myself!
{
private static readonly SharedStatic<KMap> Map = SharedStatic<KMap>.GetOrCreate<KMap, T>();```
kmap is just a fixedlist hashmap
{
internal const int MaxCapacity = 255;
private FixedList4096Bytes<MiniString> keys;
private FixedList512Bytes<byte> values;
private FixedList512Bytes<byte> next;
private FixedList512Bytes<byte> buckets;
where ministring is just my version of a FixedString16 (without null termination)
since fixedstring32 limited to 128 layers
and i wanted more
reminds me to look more into burst features. SharedStatic is something I'd already have needed a bunch of times
but yeah, this is only a small feature
but i was super happy when i got it to work
because i thought conceptually it was impossible
great idea and module for this burst feature. wouldn't be possible without SharedStatic, right?
sharedstatic is the magic for this
i was just sick of passing layers and states etc into jobs
just wanted to be able to directly read from some setting file
I have the same problem in a bunch of places
i'm considering releasing my entire core library at some point soon~
i think there are a lot of useful things people would find in it
and my core library is completely non-invasive
it will not change anything about a project
no systems, no bootstrap anything
so you can literally add it to any project without harm
I have a dumb setting for "show damage numbers" - I was so unhappy with the implementation that it's now a compiler condition. I can redo this now with SharedStatic
i probably wont release my game library anytime soon as that is quite destructive
but yeah i would like to release this core library
so many cool optimization tools in there
That would be really cool.
I'm just waiting for someone to release a proper package for linking gameobjects and entities. If not soon, I'll do it myself. Never planned to but with the way how 1.0 looks it will be needed anyway
ah yeah
im still putting off using anything but a capsule
soon capsule characters will be a game feature
who needs animations
Like, even if you have a great working ECS asset. Someone wants to take it for his MB project and then, what to do? Expect to write all the damn code?
It's not much but to get everything working it still needs a bit of understanding, design and code
Such a shame with animations taking this long ๐ฆ
right, it's really what's holding Unity back so you can go pure ECS
pure might be pushing it with audio etc but that is much less problematic to manage yourself i think
you could be very close to pure anyway
yeah, some goes for UI. I also think this is much more manageable
hm, the great thing about your node approach is that you don't have conditional checks on node graphs that don't require certain nodes to begin with. That's such a big flaw in my code right now.
part of the requirement check
I need a way to skip this condition altogether ๐ค
I could introduce a new flag array in my spell data that has the information of what checks the spell actually needs. that way I could skip a lot of checking that are not necesarry. How does that sound?
First I thought about a bitmask but that leaves me again with lots of ifs that need to be checked
do your spells ever change?
got my old sample to work 200,000 entities with a basic AI job that looks like
if it updates every frame, takes about 3ms to process this graph
if check every 4 frames looks like this
so slicing works pretty well, considering it's individually checking 200k entities every frame
there's not that much logic in this graph, but i'm decently happy with this performance
i'm done with it. shaved off like 0.7ms - spells don't change, at least not mechanically, just numerically - but there are buffs that can enable new mechanics
if (ai.FramesBeforeNextUpdate <= 0)
{```
should probably turn this into a single frame check
had hopes I could improve it more than the 0.7ms but it's a start and I think there are more places that can be improved like this. I've never done something like this, seems like a cool way to do this
maybe some more temp values to reduce overhead
was just a thought because it seems like you're doing the check every frame
when in theory it only needs to be done once
the big checks are just on user input
(or maybe its not being done every frame and only on application?)
ah ok yep that makes sense
with no input it's not even a blip in the profiler
do you know if burst compiles switches to a jump table in the editor?
i'm bad at reading assembly ๐
well, I can see a jmp - good enough for me lol
have you ever found the need of conditional acquiring of write handles in jobs? I've a really dumb way of doing that. Don't want to auto increase the versioning number just by acquiring a write handle but the job has to run to actually know if writing back to the chunk is really necessary
Another question, is there a faster way to read BlobArray?
might be worthwhile to cast to a nativeArray
There it is again: error MayOnlyLiveInBlobStorageViolation: You may only access .SpellRequirementFlagsBasic by (non-readonly) ref, as it may only live in blob storage.
Damn, that is starting to annoy me
well, got it working but interestingly enough, casting to a NativeArray seems to make it worse
enough for today, improved my timings from 6.8ms to 6.0ms. I have several other places to apply my little trick now. Hopefully I can get it down some more tomorrow. sleep well everyone o/
there might be an interesting way you can kind of do this now
ComponentTypeHandle now has an Update() method on it which gets the latest safety handle and you could create the handle from EM instead of the system
though im not certain this would help (just kind of thinking allowed)
personally not really though
anything that uses change filtering for me must use ComponentFromEntity or ECB
side note for anyone reading WithChangeFilter is kind of broken in 0.50 and you really need to do any change filtering in a IJobEntityBatch
Hello guys, I'm very new to DOTS and I really only want to use certain parts of it to improve my performance in game.
I want to use JOBS to multithread my foreach loop which does a bunch of raycasts.
I'm getting this error
InvalidOperationException: CL_SquadController+Data used in NativeArray<CL_SquadController+Data> must be unmanaged (contain no managed types) and cannot itself be a native container type.
// We check each unit in squad if they can attack it
var soldierRaycastDataArray = new NativeArray<CL_SquadController.Data>(allSoldiers.Count, Allocator.TempJob);
for(int s = 0; s < allSoldiers.Count; s++)
{
soldierRaycastDataArray[s] = newCL_SquadController.Data(ignoreLayers, allSoldiers[s].gpuiCrowdInstance.transform, target, allSoldiers[s].unitController);
}
var job = new SquadRaycastUpdateJob()
{
SoldierRaycastDataArray = soldierRaycastDataArray
};
var jobHandle = job.Schedule(rangeCheckCollider, 1);
jobHandle.Complete();
soldierRaycastDataArray.Dispose();
The error is where I create my NativeArray.
My Data struct looks like this
and my actual job like this
uff
I had a few questions about unity, yes, they are rather stupid to a greater extent, but still, I read blogs, the unity roadmap and do not fully understand.
-
When can we expect the arrival of weta digital tools? This or next year?
-
When can we expect a full-fledged dots with its functions? I was told that it will be in unity 2022, is it next year?
-
Should we expect the appearance of analogues of nanite and lumen in the future? Maybe the developers gave some comments?
-
What do we expect from animators in the future? What tools will be made for animators in the future?
- I wouldn't expect it till 2022 lts so ~1 year
- They haven't officially said anything but I'm pretty sure they're working on something, though their tech might be quite different
- They posted a big update on this just recently https://forum.unity.com/threads/animation-status-update-q2-2022.1266089/
Tertle what time zone are you in
As for 1. Weta, last I heard from a friend of a friend who works for them, they were still going through the acquisition process in late Feb with no dates set
Ah that makes sense
Hello fellow Aussie
i assigned the rendering components with rendermeshutility
but it is invisible
what went wrong?
going by those world render bounds it looks pretty small?
yes they are suppose to
im on 0.50 btw
thing was working in 0.17
are you using that AddRenderComponents thing?
yes
one thing peculiar
those that are showing are not children of other entity
the layer mask is 0, I dunno if that should be "everything" instead
so the default value 4294967295?
ah, if some are rendering then that's probable not it
hmmm
im gonna send the components of the rendering object
note its on a different layer
but referencing this it should be fine
Just a side show. Here's my latest DOTS related article: https://coffeebraingames.wordpress.com/2022/04/16/dots-snippets-listening-for-new-and-destroyed-entities/.
I don't suppose anyone knows if there's an easy way of changing an entities color?
There's a very easy way using the hybrid renderer
You just have to build a shader graph to support it
Actually there's a bunch built in
For standard mats
that's way to hard ๐ฉ
You probably want the Base color override
Just add that component to an entity and you should be done
Assuming your material supports it
I have only used this with a custom shader but I assume it'll work just fine with the out of the box ones if they say it will
I guess I'll look into it thanks
I know its probably not best practice but is it possible to access entity child's component (set its data) from gameobject method?
(I have entity reference and I need to change its child's rotation when some event is triggered on gameobject)
@blissful sage yeah, World.DefaultGameObjectInjectionWorld.EntityManager.SetComponentData(childEntity, data)
thx but I know how to set component data - what I dont know is how I get childEntity from entity to do so
children are stored in the Child buffer on an entity https://docs.unity3d.com/Packages/com.unity.entities@0.50/api/Unity.Transforms.Child.html
I had tryed entityManager.GetBuffer<Child>(entity) I had found somewhere but it resulted in ArgumentException: A component with type:Unity.Transforms.Child [Buffer] has not been added to the entity. exception ... Im calling it right after entityManager.Instantiate ... do I have to wait for something? ... also Im not sure how to get Entity from Child
you sure your entity has a child buffer?
Child.Value is an entity(shows on the docs page if you click value)
eventually it should I suppose (Im not sure about execution order / how fast is created automaticaly during entityManager.Instantiate function ... its instantiated from prefab (GameObjectConversionUtility.ConvertGameObjectHierarchy) which has child and it looks right in DOTS Hierarchy
it might be delayed a frame then, ive not actually attempted to query a child in the same frame as creating a parent that has one
Hmm you are probably right ... I had moved it to coroutine with yield return new WaitForEndOfFrame(); at start and it seems to be working ... thanks so much ... hopefully I will be able to work with it from here ๐
Hi, in the ECS Samples there's a Entities.ForEach that takes a MonoBehaviour as first argument, how exactly does this work? I can't seem to find the relevant docs for this feature.
The job in question is: SmoothlyTrackCameraTargetsJob in PhysicsSamples/Assets/Common/Scripts/CameraSmoothTrack.cs
This is so weird. A trick to reduce the amount of condition checks is an improvement in one part of the code but then adds an absurd amount of time in another part of the code.
@dense crypt its using .Run() on the mainthread, UnityEngine.Components can be added as managed components to entities.
@dense crypt additionaly to what thelebaron said, the ConvertToEntity script, set to Convert and Inject Game Object is the key here. And the WithoutBurst tag
I see, so the Convert script would in this case create a managed component that has the same name as the MonoBehaviour? And then the job works cause said managed component actually exists in ecs land.
It doesn't really exist in ecs land. It's still a managed component. That's why WithoutBurst and Run is necessary.
hmmm ISystemStateComponentData is not getting added when inside a subscene, anyone encountered this?
in play mode or editor?
I'm not 100% sure if this is correct - BlobArrays in blobs are not local to the memory address of the blobs itself -.-
I thought a blob array was stored inline
Hmm I'm still not sure I follow 100% then. Take a Camera with Convert and Inject. When playing there is a Camera component attached (see image). So do you mean that this is not really a component, or is this actually a component that acts kinda like a proxy, simply containing the pointer to the Camera (in this case)
correct, it's a proxy
I am aware how we can't use managed memory in jobs, but I am not fully confident in the whole managed component hybrid land
Ah okay, so from a code perspective whenever I pass the UnityEngine.Camera Component in to a ForEach, it's actually doing some magic where it's automatically grabbing it from the managed component? Because in my head I kinda expected myself to have to pass the proxy component and manually grab the reference through the .Value field
Entities.ForEach has some trickery underneath when it comes to that
Yeah I see, now it makes a lot more sense
you can open the generated code and see how that works. previously it was in the dots compiler. now it's in some library folder I don't remember
yeah that's true actually, not sure why I didnt think of checking the generated source
Anyone know if there are any sprite animation libraries suited for ECS 0.5 out yet?
you're in luck: https://github.com/fabriziospadaro/SpriteSheetRenderer
is there a way to query only a certain component? Like I want the entity/entities that only have a translation and nothing else?
Not easily afaik, you could make a IJobEntityBatch and check the ArchetypeChunk.Archetype.TypesCount and see if it's only 1. If it's not just early out
You're in a situation where you can not add a tag component to identify the entities you want?
I just remembered to use the double component strategy for this (destroy entity with ComponentA1 and SystemStateComponentA1 and then just do a query for without ComponentA1 to get the system state components for cleanup)
I did waste some time trying to get every component that exists to add to as an exclude component in the query and got this error Requested: 11928 Size: 72 Capacity: 1024 totally reasonable there are limits, just didnt even think about it prior
Oh dear, I've done something exceptionally stupid. I'm using extensions in bursted jobs and the extensions are not bursted. I must say, I was not aware of this but from my small test job the difference is with 500k calls 0.4ms to 0.00 can't be measured in profiler.
well, that wasn't it either. guess the test just wanted to screw with me.
so now I'm left with losing 0.9ms with 2 lines of code:
does that make any sense? no, I'm baffled to what's going on.
I'm picking apart every block in the job. 600 loc overall. This happens near the end and up to this point I have ~2.11ms. with these 2 lines it's going up to ~3.0ms
what is spellCasterSpell and inputSpell?
after those 2 lines I use 2 extension methods that didn't have a BurstCompile tag so I thought, after the test this must be it ๐ฆ