#archived-dots
1 messages ยท Page 195 of 1
burst compiled everything(systems)
id assume so
ugh like 90% of my systems refer to the collisionworld from physics so i cant switch everything over to ISystemBase ๐
hmm how would you get another ISystemBase from a struct system ๐ค
Thatโs what I want to know too
Was Script saying those methods are internal?
Super painful to rewrite all lambdas as ijcโs.. not what I was hoping for ๐
yeah there is a utility thing thats all internal atm
from my perspective it doesnt matter because all the current systems id be doing that for arent the struct types ๐
Awwww yeah upgrade from 0.14 to 0.17 without any issues. Hell yeah
Not that its useful, but it was fun to try ๐
Yea upgrade was fine - only wanting to use isystembase where Iโm running into a wall of issues
@stiff skiff hows perf for you? i feel like my project is 5-10% slower but im way too lazy to do any thorough testing
Yeah Im interested in those, but I saw no docs on the unmanaged systems
โdocsโ? What are those?
Sadly we don't have our performance tests in place, so I wouldn't know
Docs are those things I hate writing, but am required too xD
Especially if I need to write them in readme.io's garbage of an editor
I say upgrade was fine but currently my perf is absolutely crippled by jobs that shouldnโt be running ๐ง
It feels slower than 0.16 but maybe I'm just imagining, haven't actually tested it.
Talking about docs.. how come they are able to release the new package.. without automatically publishing the new documentation on the site?
yeah anecdotally the transform group in my default test scene was at around 0.4-5ms and is now 0,6ms
Transform system was supposed to have โmodest gainsโ
Half of the important stuff to me is still missing, unmanaged EntityCommandBufferSystems, unmanaged ghost prediction information, unmanaged physics world
etc
Not to mention .enabled
And I guess they didn't want to add lambda support since they are working on code gen right now
Enabled is a thing for ISystemBase it's one the SystemState ref
But it generally feels a lot less finished then previous iterations idk
Thatโs just system enabled thatโs always been there no? I mean re ICDs
Ah yea, no I bet that's months away
LIke they push out this huge thing => unmanaged systems but half of the functionality is just missing
What is unmanaged ghost prediction?
Itโs actually closer to 95% (missing) though
Yeah never use any new features in a release, it's just not worth it
wait 1 or 2
though sadly this means 3 to 6 months now ๐
i did notice an interesting physics component named CollisionWorldProxy, allows dataflowgraph nodes to access the collision world, not sure how long thats been there
Iโm going to have to spend the time butchering my code cuz I want to see what perf difference there might be ๐
didn't 0.17 basically release 2 months ago internally (going by the date on the changelog), guessing that's when it got feature locked and shipped for qa(?)/getting other packages like physics up to date
but other updates got released basically as is including the issue of not having everything updated at same time
i thought we were qa ๐
True lol
so maybe internally they could be further ahead than we think (wishful thinking)
Won't believe that until I get my roadmap
yea i doubt they have qa for entities atm as well but does it really take 2 months to update other packages 
I would love any kind of roadmap, or communication, in an official capacity
This was the first time all dots packages were tested together... not at all surprised a bunch of issues turned up.
Pace overall though really does feel staggeringly slow
just some official communication would go a long way of soothing the slow development
I'm just worried there are some really big changes on the roadmap that I'd like to see coming
Just posted this as itโs the top level info I would have liked to have known re .17. Please add/make corrections: https://forum.unity.com/threads/entities-0-17-changelog.1020202/page-2#post-6754924
You might want to provide an example of the mentioned cryptic error. They will certainly ask for it
Also that error IS weird..
because System.IntPtr is a struct...
I see netcode 0.6.0 prev7 on my side
january 22
Dynamic buffers serialization over the network โค๏ธ
How can i load a subscene into a custom world?
@amber flicker I chuckled at my little hack to reference struct based systems
Edit: You don't need the unsafe declaration, I was testing something earlier
Nice! May steal ๐
Yeah I put it into an assembly definition reference so I can access stuff
Also one last thing, since SystemRef is a ref struct, you can't store it as a member to your systems - so you pretty much do World.GetOrCreateISystemBase<T>() in OnUpdate
Would it make sense to have a system that calculates the distance in between all "characters" entities and save it in a lookup rather than calculating distance in multiple systems using sphere casts and transforms? If yes, how do I loop over every permutations of characters and in what data structure do I store the distance so I can reference it with two entities to get their distance?
This would be for an aggro system and an ability range system
I imagine having it sorted so I can get the closest character would be useful too
I'd do it in a separate system, and just store the float distance on the entity
Yeah that makes sense. How can I loop over every entity twice since we can't nest Entities.ForEach tho?
do you mean because your checking entities against one another?
Yeah exactly
use an entityquery for the distance component and whatever other component that's on the entity for the job
Ding ding, never used Entity queries before but that sounds like the answer
thank you i'll look into it
no prob
Say I want to get both the entities and the components from my query should I do something like this?
var characters = characterQuery.ToEntityArray(Allocator.TempJob);
var translations = characterQuery.ToComponentDataArray<Translation>(Allocator.TempJob);```
Or am I better to do GetComponent<Translation>(characters[i]) in my foreach?
Would the order of characters and translations be guaranteed? And does doing query.To...() twice executes the query twice?
GetComponent is basically random memory access and so slower and not optimal
both of the those ToEntity and ToComponent are basically there own separate jobs
you should only really need the ToComponent
if you iterate through the entitys that you want with the job
distanceMap.Clear();
var characterQuery = GetEntityQuery(typeof(Character), typeof(Translation));
var characters = characterQuery.ToEntityArray(Allocator.TempJob);
var translations = characterQuery.ToComponentDataArray<Translation>(Allocator.TempJob);
for (int i = 0; i < characters.Length; i++)
{
for(int j = i + 1; j < characters.Length; j++)
{
distanceMap.Add(new EntityCouple() { e1 = characters[i], e2 = characters[j] }, math.distance(translations[i].Value, translations[j].Value));
}
}
characters.Dispose();
translations.Dispose();
I need both the entity and the translation to calculate their distance and insert the entity as key in the map
There's no guarantee those arrays will align. Make sure you pass the exact same query to both arrays
Err, the same archetype to both queries rather
Then they are guaranteed to align
you could just have a single query actually
Oh yeah I guess so
Don't I have 1 query?
yeah it is
Yes don't mind me I'm dumb
Haha no worries, so there's no faster way to do this?
You could do some kind of fancy spatial partitioning. This is nice because it's simple though
You should put the actual "work" into a Job.WithCode though
I mean I would do an entities foreach(Entity entity, float distance) =>
instead of the two for loops
you would only have one for loop then
Yeah basically the foreach would take the place of your outer loop
just iterate through all entities against that one
Correct me if I'm wrong but wouldn't that create 2 queries?
1 would be my entity query, and 1 my foreach?
With my double for loop I only have 1 query?
Well you should be creating the query in OnCreate and caching it in the system
well if you use a different query for the foreach
anyone else getting this error in 0.17 - InvalidProgramException: Passing an argument of size '10720'.
Unity.Entities.SystemBase.Update () (at Library/PackageCache/com.unity.entities@0.17.0-preview.41/Unity.Entities/SystemBase.cs:412)
Ooh I can use the query in the foreach? Sorry I haven't worked with those before
And if you're using the same archetype I wouldn't be surprised if Unity was usiing the same query behihd the scenes
But then I lose the index i that allows me to only get the combinations instead of the permutations
you can't really do that though can you, you get a error conflict if you use the same query in the foreach and an Entityquery
If can pass int entityInQueryIndex as the first parameter in the Foreach
i am getting a null World.DefaultGameObjectInjectionWorld in the new update, anyone experiencing the same?
restart unity
tried.
do we need to manually create the world now? there isn't a world on start after update
huh, weird, I had the same error and it went away with a restart. No, I wouldn't have heard anything about it. Something that fundamental would get a notice in the upgrade guide
seems from the test changes, we have to put a partial now before every class that inherits SystemBase. doesn't throw any errors if you don't
how should i do stuff like on-hit effects in ecs? Where the character has a buff that adds secondary damage to each of their attack/spell hits
oh wait
nevermind im overthinking things arent i
Currently having an issue wherein entities I instantiate during the ConvertGameObjectToEntity thing don't seem to save with Subscenes when closing them. If I run the game with the subscene open, it's fine, but on closing it loses them.
Outside of subscenes, they seem to be instantiatied fine and have their entity references updated according to their new parent just fine with just a LinkedEntityGroup thing.
For the subscene, I've tried manually adding a SceneSection to the entities, but am unsure how to programatically get the scene guid of the creating object. Any ideas?
op looks like there's a dedicated CreateAdditionalEntity method, that'll probably resolve the issues
Edit: it did
how do i make a system where like... i can do stuff like +x% damage with spells or +x% accuracy to ranged attacks.... Conditional stat bonuses and stuff like that...
nvm i think i know
does WithChangeFilter work for dynamicbuffers?
yes, adding and removing elements at least. Any time write access is gotten
How do we use ISystemBase? I cant figure out how to Entities.Foreach
You can't use a foreach. You have to manually write the job and schedule it yourself. It seems like a lot of jobs might be broken when trying to schedule in a bursted OnUpdate though and cause weird errors - IJobChunk works at least
why would jobs be broken in the burst onupdate?
Apparently IJobChunk is the only job type you can schedule from bursted onupdate right now. I assume it's a bug
#archived-dots message this is a dumb way if you want to grab system structs
that doesn't look like it saves any typing?
thats the entire meat of it? why wouldn't you just do World. ^
SystemRef and world.Unmanaged.GetOrCreate are internal
yeah I was too lazy to do that haha
its not like they update this package every week or something where you would be annoyed about doing it all the time :^)
true lol
oh man, my framerate has halved with 2021.1b3, Entities 0.17 and NetCode 0.6 against 2021.1b2, Entities 0.16 and NetCode 0.5. Tomorrow it's time to figure out which part slows everything down. My bet is on hybrid renderer - aaand I'm not able to reproduce it anymore. best performance problems are the once that go away without doing anything ๐
@zenith wyvern Sweet thanks, will probably stay with class SystemBase for now then
@zenith wyvern ive used entitybatch without any(noticeable) problems
Tertle on the forums said it wasn't working for him, weird
Hi, I'm using ECS and I'm generating trees at runtime. There is a lot of leafs then (~300/tree). I thought about merging the leafs of a tree into a single combine mesh. Has there is several trees, I tought it was a perfect candidate for Jobification, but I can't figure out how to do that. I always end up with a Job which contains a non value reference. Is what I try to achieve possible ? Or should I go another way to increase performance (dynamic batching + GPU instancing - I haven't checked if this is already done. I guess dynamic batching I guess so as the leafs all comes from the same prefab. GPU instancing not sure)
Any help or advice there would be welcome. Thanks !
does anyone here create blobassets at runtime?
hmm do you just create blobs using a new BlobBuilder -> blobBuilder.CreateBlobAssetReference?
ref var resourceRoot = ref builder.ConstructRoot<BlobArray<TResource>>( );
Already throws errors for me
it would be nice if there were a BlobAssetStore associated with a world at runtime as it'd be convenient to usethe AddUniqueBlobAsset... wondering if I can just create an instance
TResource is constrained to unmanaged
This is the error I get error ConstructBlobWithRefTypeViolation: You may not build a type BlobArray`1 with Construct as BlobArray`1[] is a reference or pointer. Only non-reference types are allowed in Blobs.
Means we cannot use blob arrays as the root anymore?
didn't know that was possible before.. I don't get compile errors from a normal ICD in the root
Did anyone notice the new DOTS packages section the 0.17 manual? Seems handy for when searching what is available already https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/index.html
oh yeaaaah no more google or bookmarks :D, thanks
dots timeline sure is interesting
it already links to the @latest link, so just one bookmark from now on :p
has anyone worked out if it's possible to grab an ISystemBase within a SystemBase?
I assume it's not?
I didnt look yet. Shot in the dark, we can't GetOrCreateSystem from the EM ?
sadly doesn't look like it
That would be too easy right ? ^^
I currently have some NativeHashMaps stored in a system that both ISBs & SBs would now need to access and I'm wondering where to put this data now. Would welcome people's thoughts. Roughly 50% of my entities (which can be many) store some mutable value in the hashmap. Options I'm thinking so far:- 1)Blobs - have to be created at runtime, recreated occasionally and shared references managed, 2) Shared statics? Is this a good option for NHM? 3) Singleton with e.g. unsafe hash map? 4) same as existing but duplicated - one system for managed, one for unmanaged, 5) something else? Storing on entity is an option but requires additional ICDs & entity reference I'd rather avoid I think.
I would go for 5 and profile before trying unsafe stuff, but you have more experience than me ๐
Have you looked at the mesh low level api's? You can use meshdataarray and nativearrays to create vertex and index buffers via job system and apply this data to a mesh.
Wanted to avoid for complexity rather than perf reasons but yea.. didn't expect this issue
Yeah it adds steps but still it stays in the pattern ? So I think in my head I hope for performance in the future. But sure your own native containers are more straightforward usually and you can make sure they are performant ๐ค
I don't have the answer I'll let the pros speak ๐
am I the only one who doesn't find any ISystemBase docs in the 0.17 manual?
no you're right, the docs aren't online yet
how do i do uh.. secondary stats in ecs? Stats that are dependent on other stats and will automatically update when the other stat changes?
does anyone know
I would stack stat-modifiers ComponentDatas, and have a system that compute them all in the end
Making it all relative would make it like hell
yeah... that's what i usually stick to. Idk how to do an elegant system where like.. i have attributes that increase secondary stats. Can't wrap my head around it...
and then statmodifier passives that increase one stat based on another stat.. automatically
dunno how
Hey guys, is there no way to write into a system's fields from a job?
If it is an unmanaged/blittlable field you can use NativeReference<T> in your System or a pointer
Here's an example:
public unsafe class SomeSystem : SystemBase {
NativeReference<int> intRef;
int* intPtr;
protected override void OnCreate() {
// Dispose these in OnDestroy()
intRef = new NativeReference<int>(Allocator.Persistent, ...);
intPtr = (int*)UnsafeUtlity.Malloc(4, 4, Allocator.Persistent);
}
protected override void OnUpdate() {
var localIntRef = intRef; // Need to have a local copy
int* localIntPtr = intPtr;
Job.WithCode(() => {
localIntRef.Value = 20;
*intPtr = 1;
}).WithNativeDisableUnsafePtrRestriction(localIntPtr).Schedule(...);
}
}
Native Collections aren't bittable are they? :/
they're structs
that contains pointers, but with collection checks, they contain a dispose sentinel which aren't blittable
there are also the Unsafe variants if you need them
I'm trying to have a system that populates a map field that can be used by other systems
like a nativehashmap?
Yeah exatcly
Yeah i dont see why that wouldn't work
So like NativeReference<NativeHashMap<int,int>> ?
No you can just do NativeHashMap<int, int>
not exactly, remember that native containers store pointers
so you have a copy of the container, but the pointer points to the same content
oooohh
So even if I assign it into a local variable, the field points to the same collection
Cool thanks!
@warped coral start with that, you can either put the stats in a comp or buffer. what do you prefer?
a comp has all the stats, that's a downside, buffer is an array though and not as fast
you could also split the stats in smaller comps. produces lots of code though and I don't think it's really necessary
Just keep in mind that if you use a native container for this you're going to have to manually managed dependencies between systems yourself, unless you use an unsafe container attached to an entity, which comes with it's own issues as well
If you can get away with representing your map as a dynamic buffer on an entity it will make your life a lot easier
if i'd like to maybe add more stats later on... and keep the game versions compatible.. i should use a buffer?
currently i have a DynamicBuffer<Stat>
Yeah I think I'm in over my head with all of this. Where exactly in ECS are you supposed to implement helper methods? I was trying to recreate something like how PhysicsWorld has usable methods PhysicsWorld.CastRay(...), etc. Am I over thinking this? Should I use struct methods?
Only use a method on your component if it deals specifically with that component's data and nothing else
My use case for anyone interested: I want to compute the distance between all my "player entities" and be able to easily query for the distance between two players from any other system
Otherwise make a static function on a helper class
But what if my method needs background data?
You pass it into the function with anything else it ineeds
It's the only way to keep everything job/burst safe
But where in the first place do I store the distance between all entities?
wouldnt you use a system for that
You could have a native container or a dynamic buffer that gets passed around if needed
Hard to say without knowing the exact use case
A singleton with a map component... I think I got too hooked up in weird stuff that I forgot the simple solutions lmao
Just to be clear tho, system methods cannot be burst?
That's pretty much how I represent my map in my game - a singleton entity with dynamic buffers that hold data for different aspects of the map
oh yeah singleton entities
I'd say no because the system themselves are managed
If they're member functions no they can't be bursted unless it's the new ISystemState struct which should probably be avoided if you're just starting out
It has to be a standlone static function to be burst safe
Got you. Thanks a lot
@warped coral updating is not a relevant question if you're using comps or buffers. you can make both work either way
the question is, do you want to give up speed for convenience in coding that thing.
because buffers need a lot less code, it's usually just a for loop with some conditions. with comps (i use them) there are massive walls of code ๐
And I use multiple comps for the same stats. BaseStats, BuffedStats, FinalStats. Basically for every stage I have a different comp
i could possible make them generic but i don't really know how in ecs. not worth my time yet
and generics possible give up speed again. hard to test with no implemented solution then and no base metric for performance
Okay well now I'm stumped. If I can't have NativeHashMaps on components, where am I supposed to store them?
You would have to store it in a system and pass it around, or use unsafe containers which can be stored on a component
Or use a managed component
I would use dynamic buffers but not being able to lookup with custom keys makes things difficult
Yeah it's definitely not suitable for all cases unfortunately. An UnsafeHashmap should work for you, you just have to make sure you manually dispose it before the entity is destroyed or else it will leak memory
I'll look into it. Thanks
@viral sonnet hmm.. so.. i should have multiple buffers and systems? one for primary, then one to auto-update secondary based on primary?
I would just make it work and then iterate as you go because otherwise you will spend forever trying to come up with the perfect design on paper
simple but limited is better than non-existent. if its too slow optimize.. otherwise its fine
ISystemBase is the harbinger of the return to Struct based Jobs. We're going full circle now. From Classes to Structs to Lambdas and back to Structs.
I havent used hybrid renderer in so long though. Cant even get a cube to show up
For v1 you need to disable SRP batcher in the URP configuration assets
And jobs have always been struct based haven't they? Everything else is just a wrapper to save typing. Which is very good and valuable
My main struct job was the old IJobForEachEntity_XXXXXXXX which were deprecated a long time ago. Replaced by lambdas. Now it's looking like it's going to be resurrected from the dead.
Not that I know of. Even back then I think those were just compiled into IJobChunks
still wish they never removed IJFE
Which has always been the core of ECS jobs
There is a replacement coming isn't there?
Some middle ground between IJobChunk and IJFE
Forget what it's called
Yea, I need to figure out how to use IJobChunks. It's the only job type working with bursted isystembase
yeah theyre still working on it i think
IJobEntity I think thats what they called it. Saw it for a second on the forums a while back.
Yeah that's the one
I can see why people liked IJobForEach but their reasoning for getting rid of it is good. The generic overloads are just hilariously bad
@spark glade
so saw this linked in the entities docs, com.unity.compositor for use with animation. might be able to bypass the nightmare of connecting nodes in code soon? or now?
Huh, ECS version of the ancient Unity animator I guess?
yeah, i guess theres no conversion of existing animators(dunno if there ever will be?) tho.
Looks like the manual has been updated too, more stuff on conversion and livelink
Finally some docs on hybrid components https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/hybrid_component.html
Does Hybrid Renderer and URP not work together with lighting? None of my objects are picking up any lighting I put in the scene.
v2 supports most lighting
My default background skybox changes with lighting changes but not the quad I stuck into the scene.
Same plain old lit shader.
Without lighting, the plane should be black. Yet the color doesnt change.
Looks like you're using a subscene but it's still open, does it work if you close the subscene?
Did you verify the lighting works if you turn it back into a normal gameobject?
Subscenes open or closed shouldnt matter. And ah figured it out. Forgot to turn on lighting.
Ah, URP only directional lights supported. Welp. Okay.
@zenith wyvern joachim just said in that 0.17 notes thread We don't yet recommend using ISystemBase. It doesn't have all functionality yet. We are still working on getting full coverage.
Ahh, makes sense
Do they expect us to listen? We're here suffering through DOTS in the first place.
Of course we'll suffer through the broken and barely functioning ISystemBase as well.
well they dont recommend it for production either, i think they know we wont listen
when is it ok to have methods inside a component?
would it be bad to make stats entities themselves so i can add statmodifier components to them individually
I wouldn't. Then you can't query for them alongside whatever they're being applied to
idk im confused. do dynamic buffers still get processed even when empty?
i think i want different kinds of statmodifiers. The standard permanent, the temporary kind, the conditional kind, and the gradual decay/growth kind. With the gradual and temporary kinds, i'd like a system to not process them when they dont exist
If you have a job that includes a dynamic buffer in the query then yes it will run whether or not it's empty. You can use change filters so it will only run when the buffer changes (on a per chunk level)
To make a system like that that's extendable and works well would require pretty deep knowledge of Unity's ECS I think. May want to start simpler until you're more familiar
hmm.. i know i need the gradual/temporary kinds to constantly tick down their time and then remove them when they're done. but dunno if i wanna use a dynamic buffer. If i use a component, then the systems that process them will automatically turn off... If i put the statmodifiers on the character, i'd have to have a string on them for their name to know which stat it affects i think. if i make an entity for each stat and also put a stat component on each stat entity, and then stat modifiers for each stat entity, i could just process each one and not need to look up to make sure each stat modifier affects the right stat i think
You can use multiple systems.
One to handle the time reduction and another or multiple to handle adding and processing of the time dependent statuses themselves.
The time reduction system is simple:
private override void OnUpdate()
{
var elapsedTime = Time.DeltaTime;
Entities
.WithReadOnly(elapsedTime) // Not sure if necessary but good to have.
.ForEach((ref DynamicBuffer<TimeStatus> statuses) =>
{
for (var i = 0; i < statuses.Length; i++)
statuses[i] -= elapsedTime
}.ScheduleParallel();
}```
Then with another system, read and process whatever happens with that time.
Always good to compartmentalize your code. If you need to time change to happen before or after the read/process status step, use [UpdateBefore/UpdateAfter]
yeah... i'm more concerned with how to structure the stuff though. Like uh... where to put my stat modifier components so its easy to tell what affects what stat, and easy to loop through for calculating the stuff for the stats
Depending on how you create those stats. Hardcoded? Simple. Use an enum and a giant switch statement with hardcoded effects.
From files? That'll be a lot more difficult.
im thinking of making stats have their own entities in addition to having their own components... dunno if that's a bad idea. I'm not hardcoding the stats. So i have to use dynamic buffer or components with strings i think
i dont really wanna make a component and system for each stat either
I've been using a sort of "centralized" status entity.
One entity with all the various modifiers and effects that status has. Then pass around the entity variable itself like a referance.
So something like a status on a player entity would have a struct like:
public struct TimeStatus : IBufferElement
{
public Entity StatusType; // "Reference" to the centralized entity.
public float TimeRemaining;
}```
Then use GetComponentDataFromEntity<>(true); to get the exact data that the status effect has on the entity
This really only helps if you have a lot of entities with that TimeStatus. Using the GetComponentData is not that efficient. It's a balance between a cache miss vs memory usage.
hmm i do like how flexible that is.. although it seems like it creates a lot of entities to manage although i'm not sure if that's bad for performance or whatever
Really depends on how complex your status is. If it's just a simple health reduction over time, then just bake in the effect using an enum stating that the health will be reduced and a float value.
If it's really complex with further dynamic values or one you would like to change globally instantly, then use a separate entity and pass around its reference.
hmm ok i'll try that and see how it goes
if each stat is an entity, whats a good way to retrieve values for specific stats on a character?
Use GetComponentDataFromEntity<>(true) then use the Entity variable as the index to the ComponentDataFromEntity array.
like how should i store the entity variable?
It's a variable like int or float. Just stick it in a struct.
oh... so like.. dynamic buffer of some struct where the struct has stat name and stat entity?
Ehhhh, you cant use strings in dynamic buffers. Well, you can with NativeString but try to avoid it.
what about FixedString32
Yea, but what's the benefit of wasting memory space for string values? Nothing in unity currently can display strings directly from an entity. It has to be converted to managed value first.
If you need it to represent something, use an Enum or just a plain int value. Far less memory usage.
I have a lot of entities that have localized names. I just use an int to represent it in another string[] that is then used by the UI.
what if i want to add more stats later on and keep game versions compatible with older versions and stuff
Well okay. Your code.
actually i guess i could just make an enum for most stuff. for elements or damage types i could just add everything under the sun and it should be foolproof
Oh yesssss finally, I spent the afternoon reading blogs about the conversion workflow ๐
Oooohhh!
I've been trying to get animations to work with the DOTS Animation Graph thing. I've confirmed I can deform the model by changing the values the SkinMatrix buffer directly, but I can't seem to get anything to play, it's always the bind pose. What I've tried is creating a Base Graph Asset Model and in it adding an Animation Clip node (and accompanying clip) and linking it to the Output, then assigning the graph to an AnimationGraph component on the game object. Is there something else that needs to be done?
Hey all
Any ideas how I could work around this issue:
'The EntityArchetype was not created by this EntityManager'
Basically during conversion (subscene) im building a list of networked components (translation and rotation) and then building a Archetype, and then during play I create a 'shadow' entity using the Archetype i've created during conversion
Maybe I could store the component types in a buffer?
Turned out storing component types worked perfectly ๐
Wow I just enabled hybrid renderer V2 and its spewing TONS of 'A Native Collection has not been disposed, resulting in a memory leak. Allocated from:...'
For anyone else getting them, if your using many worlds make sure only 1 has the hybrid renderer on
It is typical to have something like a component that represents something being processed, and a component that represents when this process is completed?
Yea i often have tag compoents for that
so i can have a ForEach.WithNone<TAG> which will loop everything that needs to be processed
and within that i often use a command buffer to add that tag component
anyone know any rigorous benchmarking done on dots physics vs PhysX?
Hello all. I've been interested in using Unity to do simulations and discovered DOTS. Just getting up to speed and excited to find a group to learn with. Does anyone have any recommendations on learning materials they found helpful? Or if there are any good established patterns for composition oriented game programming I'd appreciate hints that direction as well. Meanwhile I'm googling my little heart out.
I did have a question right off the bat. If I have a chunk of entities that should be evaluated by a Movement system, is it better to have a Movement component on those entities at all times and just tweak a value inside the component to represent the vector, setting to 0 if it is not moving? Or is it better to add a Movement component only to those units that will be moving in the next frame? I know adding and removing tags causes a structural change and a sync point, so for the purposes of reducing those I assumed you'd want to just leave a Movement component on the entity and have the system check to see if it is 0 and ignore it. I know this will make the system iterate over all of the entities, instead of being able to create a separate chunk of moving entities and iterating over that smaller subset. Can someone provide some guidance on what the best practice might be in this situation?
Hybrid renderer is garbage. Stick with plain Entities and bootstrap to Mono manually.
You should avoid per-frame structural changes as much as possible. Even iterating thousands of entities takes almost no time (assuming the work the system is doing is relatively cheap) compared to the cost of a structural change. And if you really want to you can use change filtering to avoid doing work unless a component is accessed as read-write by another system
You should profile of course but if all your system is doing is adding to a float3 and you run it bursted with ScheduleParallel you'll most likely find it takes literally a fraction of a millisecond, even for thousands of entities
@zenith wyvern thank you for your insight. As I was reading about EntityCommandBuffers I got the impression that there would always be at least one sync point per frame. Is that a faulty assumption?
If you're using the command buffer to perform a structural change then yes it will cause a sync point whenever the command buffer runs
I guess the root of my question is whether or not I can expect at least one sync point every frame already. If so then entity command buffers seems like the way to go to make sure there will only ever be one per frame. But if you're implying that there isn't necessarily a requirement to have 1+ sync points per frame, but instead multiple frames can cycle without a sync point occurring, then I'll just go the first route and try to optimize for as few component modifications as possible.
As far as I know there's no reason you would absolutely require at least one sync point every frame. Practically speaking most non-turn-based games are probably going to have one or more, but it's not a 100% thing. But it's not like just because you have one structural change that you can add a dozen more and it won't slow you down. Rearranging the memory of the chunks from the structural changes is expensive even aside from the fact that it's forcing all jobs to complete before it happens.
You can use batch operations on entity queries to try and reduce that a bit but really you should just try to avoid it if you can. Sometimes you can't. The scenario you described did not sound like it required a structural change, at least
Thanks again. Honestly I was hung up on the timing of sync points more than the computational cost. It seems optimizing for the minimum number of changes is probably the best option all the time.
For performance critical code yes. Don't get too hung up on it in every case - sometimes you just need a new component so you can have a new system act on it. That's an unbelievably useful tool that you shouldn't discount either
The point to stress is to avoid doing it every single frame if possible.
i have crash with log and i cant understand what can be wrong
looks like in this sytem
Thanks haven't tried that. I'll go check if I can make something work with this !
Q: Can I force the physics world to fully rebuild? I have a bug with static colliders that I need a workaround for.
World.GetExistingSystem<BuildPhysicsWorld>().PhysicsWorld.CollisionWorld.Reset(10000, 10000);
That does not do the trick. ๐ถ
My problem is (still) that some static colliders don't work; if I add a PhysicsBody, that works only if it's not static (so dynamic or kinematic are fine).
This occurs of the entities are moved into another chunk in late conversion.
(in this case by adding a sharedcomponentdata)
An unreliable workaround is creating or destroying another static body.
I have a bug report repro project where that works, but it doesn't work for every constellation of bodies and components.
Forum topic with screenshots and 60kb sample project for the morbidly curious.
I think I will just workaround with kinematic bodies for now even though that's a couple hundred colliders.
Scheduling Question: If I want some code to run exactly and only when ever a certain Jobhandle has been completed... how would I do that?
Basically to do somethign with the job's results without actively calling complete() right after schedule.
Can someone please point me to a tutorial on what dots data flow is
Data flow?
Depends, does it have to be on the main thread? You can just make another IJob and schedule it with the previous JobHandle.
does changefilter become dirty if i do a foreach with read&write even if i dont write into the component but just read to check if i should modify it
Yes. ReadWrite automatically places a change tag on the component type.
so.. if i wanna use change filter i gotta do a separate read first to check before i write?
Yes
that seems weird... so i store a local bool.. do an entities.foreach "in" to just read... then if the bool is dirty i do entities.foreach "ref" to read & write... ok
Ultimately, everything is compiled into an IJobChunk. Read through this and you might understand. https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/chunk_iteration_job.html
That's the section referring to change filter specifically.
ok
Needs to distribute data to some game objects.
Mainthread.
does the order stay the same if i do a entities foreach scheduleparallel and then another scheduleparallel in the same onupdate?
will the first always be done before the second
Yep, order is fixed the moment you create call the schedule parallel.
cool
Then consider using this:
// Inside the OnUpdate
if (AlreadyRun && JobHandle.IsCompleted)
PassInformationToMono()
else if (!AlreadyRun)
AlreadyRun = true;```
Ok something like that it is then. ๐ Thank you.
Then again, I've never seen a job last longer than 1 frame. Just use JobHandle.Complete() and pass info to main thread.
Well currently it's not working at all and I need to find out why ๐ But that's more because my native arrays are screwed up.
Ah ok it's not that, I'm just missing a dependency on the physics system.
How do I make a JobComponentSystem depend on the output of EndFramePhysicsSystem (actually just StepPhysicsWorld)?
If you move the "RemoveComponent" to an ECB, you can work around the crash
Does the crash always happen? And does the crash happen if you comment out the Buffer clear?
I'm guessing it's some combination of the 2
AFAIK every physics system has a GetOutputDependency method. You combine that jobhandle with your system's Dependency before it runs whatever job you want to run after physics
You can also use AddInputDependency to make it run before physics systems
After over a year with DOTS, I still don't understand this part.
protected override JobHandle OnUpdate(JobHandle input_dependencies)
{
//Space. The final frontier
if (!_spaceQuery.IsEmpty)
{
input_dependencies = JobHandle.CombineDependencies(_stepPhysicsWorldSystem.GetOutputDependency(), input_dependencies);
//...
//Schedule job... ???
var job = ScheduleBatchRayCast(_cw, rc_inputs, rc_hits);
///... ?!
Like this? How does that even work.
Yeah
What goes in the question marks? The job doesn't depend on anything.
(or is there an implicit dependency?)
Oh I don't know, I've never used physics before
I assume it schedules a job in some physics system somewhere
Well this is more about JobComponentSystem than Physics.
It could be any job really.
I don't understand how JobComponentSystem actually does something with inputdependency.
Ah..
If it has no dependency then I assume you shouldn't need to run it before or after any other system
Yes afik it uses that jobhandle to communicate dependencies with the rest of the framework
So the /// ?! is return input_dependency
Not for this, at least that's the official example from the docs.
and I wouldn't know how to schedule this job from a SystemBase.
The same way you do in JobComponentSystem, you just have the Dependency property instead inputDependencies
Ok.
protected override void OnUpdate()
{
//Space. The final frontier
if (!_space.IsEmpty)
{
Dependency = JobHandle.CombineDependencies(_stepPhysicsWorldSystem.GetOutputDependency(), Dependency);
I guess.
Exactly
@light mason you refering to data orientated design or dataflowgraph?
btw that's the one case, the one singular case, where a += operator overload would be awesome ๐
(well unless you want to combine multiple deps ofc.)
It's been suggested, according to Joachim using an operator overload would cause unnecessary extra work that doesn't happen otherwise. No idea why
Yeah Dependencies are like Friendship.
Pure magic.
This DataFlowGraph graph thing , never seen it before
its primarily used for animation atm(but imo it could be used for stuff like ai), theres a guided tour in code samples on the package manager
its essentially this but in code. this screenshot is from the compositor package, and it visualizes the animation package's nodes(which is built upon dataflowgraph) as a visual graph
For a second I thought I understood, but no, I don't understand -.-
tldr its a node graph
this is what I do, square brackets are things I tried in OnUpdate()
{
1. combine dependencies with outputdependency of EndFramePhysicsSystem
2. schedule job
3. combine dependencies again (of scheduled job)
4. [complete() job]
5. [complete() Dependency]
6. set input dependency [toComplete] on BuildPhysicsworld system
}
But I get:
InvalidOperationException: The Unity.Collections.NativeArray`1[Unity.Physics.RigidBody] RaycastJob.world.m_Bodies has been deallocated. All containers must be valid when scheduling a job.
@safe lintel interesting , under the hood is it ESC ish api ? Why does it fall under the dots umbrella?
Is it because itโs bursted and jobs?
well its burst and job friendly with hooks to use it with ecs
Doesnโt nodes feel like anti dod
var cw = _buildPhysicsWorld.PhysicsWorld.CollisionWorld;
//Schedule job.
var job = ScheduleBatchRayCast(cw, rc_inputs, rc_hits);
This was the (a) problem, I got the Collisionworld in OnCreate and I guess that was too early.
yeah that would generally be before any systems run
if i store an Entity ref struct, like Entity Entity field. And then i change the entity itself, not actually writing to the entity ref, it won't be set dirty for change filter right?
like struct EntityRef has an Entity field. I modify the entity somewhere else
@warped coral no the component storing the entity field wont trigger changes
only Entities.ForEach(ref ComponentType c) triggers changes
nodes are still DOD, the package is built around the idea of walking graphs, node or otherwise
because tree structures are much more easy to construct in this kind of setup. I think they also ended up pretty performant as well.
remember when it comes down to it, the first parts of dod are, observe your data directly, restructure it to something better to machine process. then write logic that modifies and looks around said data structure as needed.
objects self modify and hide their own data behind virtual pointers. thats indirect access to your data and not full control
nodes are just a concept for bit of data that has a relationship(s) with other bits of data
oh ok
I have two consecutive systems, the first which adds a component to an entity using the entity command buffer, and the second with a for each lambda requiring that component. Will the second system pick up the entity with the added component on the same frame? If not, how can I add a component and use it in another system on the same frame?
An easy way would be to [UpdateInGroup(typeof(InitializationSystemGroup] the first system which runs the command buffer in EndInitializationCommandBufferSystem. Then any system past InitializationSystemGroup would pick up the new entity/component
For some reason I thought initialization system group was only the first frames at launch ๐คฆโโ๏ธ
Nope. It works well for exactly the scenario you're describing
Thanks, exactly what I needed!
Is the "hyrbid" approach that they talked about when ecs first came out still the best approach when you want entities that still have some monobehavior logic?
It used to be you could set up a way to bind a gameobject to an entity but its looking like now you can just convert an existing prefab to work in the pure ecs. Thats nice and all but what if I need to be able to bind a game object to a particular entity?
hybrid components are for legacy components that are just data, not logic (mesh renderers, mesh filters, old colliders, box colliders, line renderers)
What about navmesh agents?
it allows you to keep a entities centric processing and lifetime
There's no support for navigation in DOTS rn
so it just cant be done at all? no work around?
navigation you write yourself, or use the legacy navmesh
there is always a work around
Ok so what is a valid work around if your entity needs to reference a monobehavior?
just know you have to switch to a main thread system using .run and usually .withoutburst
there is 2 or more nav approach on forum
which both are tradeoffs
can I just do SharedComponentData<GameObject> ?
you can directly attach them to the entity with .AddComponentObject on the entity manager
oh awesome
which is what HybridComponents do internally, but there is more to them
I'd suggest you get a feel for the whole framework before you start hyper focusing on managed stuff
because the hybrid stuff is the real pain in the ass stuff
For navigation, I try to just avoid it until they support it in pure ECS
plain ol entities and dynamic buffers + schedule and lambdas work very well
As of the latest version there's actually docs on hybrid components https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/hybrid_component.html
yeah, just know that they are for simple components
not your monobehaviours that do work
but you can attach your mono's
which can be useful for slowly converting logic
So just to be clear I can write a monoscript, attach it to an entity with AddComponentObject then call methods within it from inside an entity system as long as I do so within the main thread?
and I appreciate all the info guys thanks for the link too
You can do anything you want on the main thread ๐
But you lose all the advantages of burst
But yeah afaik
yep you can do that
its just kinda meh
but were just programmers not cops
you can do whatever you want
I agree but I am not about to roll my own navigation system as an alternative to it.
Nah no way lmao
I think June is right, it's better to only attach data stuff. You can even attach sprites. Then you can just treat them like normal entities and ignore the monobehaviours
That's the ideal setup
Imo
personally what I like to do with systems like that is rewrite them to be hidden in a way
Yeah but he wouldnt be able to use navmesh logic
create a system that queries up a bunch of NavigationQuery components, with the minimal amount of data needed for a query, then write out the results to all of the components (like a async function call)
Isn't there a jobified version of navmesh somewhere?
There's a forum post but nothing official afaik
there is yeah, I dont have it bookmarked as I dont do navmesh stuff
in said system you can create a linear list of the entities and slam the nav api and write out all the results in a final lambda
then you get to pretend it was done within the ecs systems, even though its a single bubble on the main thread somewhere
yeah thats it
Anyone know what package this is in? I never found it
You shouldn't need to mess with ECS to use that if you don't want to
built in iirc
Let me see
yeah I think thats a internal unity package / module
Cause I tried to read the doc but it wasn't clear how to use it
Yeah if it's in "UnityEngine" that means it's not a package I think
But is that usable in pure ECS?
I mean with burst
(IJob, IJobParallelFor),
I haven't used it but just glancing it it yeah it looks like it's burst compatible
if you haven't written a unity job before (one of the two above) I'd start with some of the simple examples
people need to make more use of the 'regular' jobs
instead of lambdas
It would be pretty sad if it wasn't, jobs are pretty slow without burst
Ok so if there is built in navmesh functionality then I can just use this in my populatespawnjob
Thanks guys!
I like the lambdas ๐ฅด
So has anyone messed with the animation package for dots yet?
Is it even at a slightly usable state?
My game is pretty advanced in terms of functionality and I've managed so far with only Entities.ForEach
And I'm comfortable with that xD
there a lot of more complex things you might need to do, that are much much easier if you run some regular jobs or a for with them
and the job hashmap visitor
Good question
gotta have them macros
I do use your visual studio snippets thing @low tangle, thanks for those
If any of y'all cook up a working example of the experimental navmesh, please share ๐
Ill drop you a link when I figure it out
I'm still a bit hungover today, not energetic enough to write any yet
ty dude, i'd rather work on my other systems atm
Looks pretty straightforward tho
it is, its similar api to the physics queries that came much earlier
does it cause a sync point if i use entitymanager to read stuff? Like.. i only want to recalculate a stat value when i get from its value property and the stat is dirty. At that point, i need to use the entitymanager to read some values... is that ok or will that cause a sync point?
It forces any jobs that write to that component to finish immediately (if they aren't already), but that's about it
ok
GetComponent() HasComponent()
'yes' is a good way to think of it. dont stress the sync points too much, just make sure when you do properly start making schedule lambdas, you use the built in EntityCommandSystems that are sprinkled thoughout the default system order
try not to add any new ones
job structs for not dots physics (physx) queries
they can be chained into results before a lambda if you feed in the jobhandle
I feel like most people on this discord have deep understanding of the framework on a low level and I'm just out here enjoying ECS's architectural simplicity without really knowing what's going on (:
allowing async queries of old physics
I'm slowly getting there tho
nothing wrong with that at all. thats why I enjoy the ecs setup so much
the framework behind it, nativearrays, hashmaps, are all super clean and easy to grok
I thought I'd be a OOP guy for my whole life, but this... this has changed me lmao
I don't understand why games are made in OOP in the first place anymore
inertia
Every problem I have I can find a way to solve it with systems, as with monobehaviours I'd have to work and rework shit for hours
The modularity of them is just mindblowing
word
it's fine to scheduleparallel without ecbs if the foreach stuff doesnt cause a sync point?
OOP is great if you want something simple and straightforward. It just doesn't scale well unless you're a genius
And sadly I am not a genius
you mean you dont like making manager.cs thats 3k lines long?
https://media.discordapp.net/attachments/613124043494916097/802303342524366858/gdsi45gbbxc61.png?width=436&height=600
So DOTS works well for me
I'm not much of a planner guy, I like to implement stuff as I go, ECS is perfect for that
For OOP you have to have your entire game's class diagram completed before coding
For minimal efforts
thats a nice cat
big boi
This takes 20 systems but at least I know I can extend on it so easily, also shout out to NetCode
Is it any good? I been hesitant to check it out since the last four(?) networking apis unity released has been deprecated.
Well I've been waiting since 2018 for a networking api, then I find out the only thing available is using a weird data oriented format
It's rough on the edges, but I really hope they don't deprecate it cause I find it underrated and pretty solid
I'm not too knowledgeable on profiling, but it runs fairly well
Netcode is completely integrated with ECS, there shouldn't be any garbage afaik
Yeah, that!
Ok cool.
Unet allocated so much on its own and the raknet api was even worse when it was still around
However it's still incredibly early
If you're going to use it don't go in with high expectations
Ill prolly stick with ENet for now then haha
Tbh I don't see much I couldn't do
I say if you wanna take the lunge of faith and believe this is the next big net framework, go for it
I mean all you really need to write a multiplayer game is a good way to serialize data and a socket to send it so I'd hope its not lacking those two functionalities at least
You can have synchronized components, RPCs, input buffers, owner prediction
It's designed around server authority tho
But it's seemless with the owner predictions ๐ muah muah muah ๐
Owner predictions? You mean like lag compensation?
Yeah it's very specifically designed for FPS/twitch action style games
According to Unity they will eventually develop stuff more suitable for things like RTS or Fighting games
Yeah, basically your client processes the input and checks it against the server on the same tick
I don't see why you couldn't do an RTS with NetCode
afaik RTS should be server authoritative
Maybe performance?
I thnk it's designed around a low amount of ghosts (synchronized entities)
As I understand it for an RTS you would want something 100% deterministic, which dots is not yet
Ah okay
You definitely don't want to sync your 1000s of units every frame accross the network
If everything is deterministic you only need inputs
That's how things like AOE were made back in the day
Damn
why only send input though lol
How would it compensate input loss?
Sending only inputs with a few rpcs and synchronized component is the way to go
Why? You can send the output of the input and then verify that its a valid value on the server
and save the server processing time by making each client process their own input
There's lots of articles about it https://www.informit.com/articles/article.aspx?p=2461064&seqNum=3#:~:text=Age of Empires uses a,by each of the peers.
Although there are notable exceptions, the concept of networked multiplayer games didnโt really catch on with mainstream gamers until the 1990s. This chapter from Multiplayer Game Programming: Architecting Networked Games first gives a brief history of how multiplayer games evolved from the early networked games of the 1970s to the massive indus...
This was like 20 years ago, and these games supported thousands of units
And if you're only processing inputs (and they are reliable) it makes things like replays really easy
In a server authoritative context, you want all the computing to be on the server
At least, most
In my click to move system, I process the raycast on the client, but I send its end point and whether or not the client has right clicked to move or not
The only thing I calculate on the server in my game is stuff that cannot be verified without having to recalculate it. Like gunshots
I haven't worked with it enough to argue
But in owner prediction, having the server simulate the movement for example is mandatory for the synchronization
Sending the input allows you control things on the server, but it depends what kind of game you're making
The way I have always done it is calculate all movement on client, send the positions to the server and perform a distance check, if its too far then I just lerp the client back towards the last known position.
Does it jitter at all?
But yeah there's no right way to do it, it's an architectural decision.
Yeah, when its live on a server and not local host it will jitter a little
but I don't see that as an issue personally
Server authoritative gives you the more robust solution, at the cost of more calculations
I'm interested to see how I'm gonna implement some more complex systems as I go.
So far I only have auto-attacking and movement
My setup is similar to this, however I am not using ecs at all for it just I/O threads
https://forum.unity.com/threads/showcase-enet-unity-ecs-5000-real-time-player-simulation.605656/
I think the only reason you'd really want to send input only is to protect from cheating
Looking back at Fall Guys launch which had client deterministic movement, yikes
It's a solid and safe way to do it.
Ofc you can do it with client simulation
It's just less straightforward
It really just depends on the type of game you're making
and also make sure you're still checking the input is valid on the server
There's nothing inherently wrong with also running simulation on the client, but crucially the results of the client's simulation are not used to determine what happens for other players. Where the simulations diverge due to non-determinism, network delays, etc, you correct the player's local sim to match the authoritative description from the server. So a client that sends only input can still coexist with client-side simulation.
There's still the question of how to make it secure and non-exploitable. Doing that with raw input is easy - validate that the input is in the range you accept
So I guess it greatly simplifies the security
Yeah, it is simpler and if you're not targeting a large number of connections per server it wont be an issue.
The basic idea is to send commands rather than game state. If you have a function F(X) = Y and you need everyone's Y to be the same, you can send X instead of Y. The reason why this happens in the first place is because sometimes commands are more efficient than game states bandwidth-wise. In an RTS game, there can be 200+ units at one time so sending a command is better than replicating 50 positions, rotations, healths, etc.. There are several other benefits like 100% game state cheat proof and small replay sizes.
I guess that guy nailed it
Yeah that is a good example on when to do it.
is it possible to get a dynamic buffer on the same entity from inside a componentdata struct
Not without the entity manager
You're probably looking at a system that queries both your buffer and your component
To quote sark
oh hmm
so... how do i avoid recalculating a stat's value every frame? I only want it to be calculated when i retrieve it and it's dirty. It needs to be able to get a dynamic buffer to recalculate
Is your stat a component or an entity?
I read somewhere you can have a system update only on components that had their value changed but I'm not sure how
i have a dedicated entity for each stat. The entity also has a stat component that holds the value property that I want to access and recalculate if dirty. The entity also has dynamic buffers on it for stat modifiers
So I'd have a component tag called Dirty
In your recalculate system, call WithAll<Dirty>()
but... then.. whats the process to retrieve a stat. Like if a character uses an ability
Why would that affect that?
usually it would just be accessing the property
On your stat entity, you can add a Dirty component when its value is changed
now it has to do what... uh... add the dirty tag and somehow wait for the system that processes dirty stuff to finish?
You stat should only need to be recalculated once per frame
yeah thats what i dont want...
Why not?
only when i access it like i can do with monobehaviours.. otherwise i loop through all the stat modifiers and recalculate the value every frame while i'm not using it
You can't have properties on a struct
uhh why
Oooo RTS MP discussion
That's not true
But you shouldn't have logic in your components
To throw into that, you can have massive units synced without dertimistic
https://www.forrestthewoods.com/blog/tech_of_planetary_annihilation_chrono_cam/
Technical deeptime into the unique networking architecture of Planetary Annihilation.
You can use properties in a struct if you need to
LocalToWorld contains get properties for convenient Position, Rotation values
then how do i do what i need in ecs? like... i only need stats to recalculate when i access it and it's dirty. I could easily do that with monobehaviours but im not sure how to do something similar in ecs
Unless?
In ECS, your logic is a string of systems
THe way I see your problems:
SYSTEM_THAT_EDITS_STAT ---> SYSTEM_THAT_RECACULATES_STAT ---> SYSTEM_THAT_USES_STAT
ahhhh that makes things a lot more clear... so when i use an ability, i queue it, and then switch a bool for that stat so the recalculator system knows it's about to be used.. then it gets used.. or something like that... wait.. but then... when i use an ability.. it has to have multiple systems... one for parsing the command.. and another for the actual logic then... so they can update at different moments... i think it's much clearer now
Using an ability will most likely have multiple system
yeah my way of thinking about it was flawed
ABILITY_IN_RANGE_SYSTEM
ABILITY_DAMAGE_SYSTEM
ABILITY_COOLDOWN_SYSTEM
It may be even more specific then that
Oh yeah
ABILITY_FIREBALL_IN_RANGE_SYSTEM
It'd try to abstract it as much as possible
Say you have a Fireball ability entity
With a range component, damage component and cooldown component
You can have 1 system for each component
Instead of 1 system per ability
yup
my rts was grouped with ranged attacks and melee attacks
cooldown was shared between them
Then I have this monstrosity
but the actual 'attack' was different
Yeah I want to abstract attack to be an ability
So I can use the same logic
I basically just have an AttackingSystem that recast Attack everytime it's off cooldown
Like an auto attack
how do your systems uh... communicate so like... if the range check fails then the whole ability doesn't go?
When I right click on an enemy to attack it, I add the Cast component to the ability, with an Entity target
You have 2 options as to how to handle the string of systems
One is to have more tag component say "InRange"
If your ability doesn't have "InRange" you character moves towards the target
Or you can fail the cast by remove the Cast component from the ability
And do some logic on top
that... seems confusing
Basically it's important to order your systems appropriately, then they communicate with eachother through tags
It's definitely complicated, but once you've got it down
Any ability will work through your system
See it as like a conveyor belt idk
In an assembling machine
uh.. what would the process be for a fireball ability?
what systems happen first and then next and then whatever
Let's say a simple ability that has only a range, and damage
ok
When the player input indicates he wants to cast Fireball
(And keep in mind this is how I do things but not the ultimate solution)
I would add a Cast component to the Fireball ability with the target entity (the entity we want to throw the fireball at)
First system would be RangeCheckSystem
With a foreach (Ability, Range, Cast)
That checks the range against the caster and target locations
if the caster is within range do nothing
if not, add a CancelCast to the ability entity with a reason "Out of range"
next a damage system
With a foreach (Ability, Damage, Cast) .WithNone<CancelCast>
That removes hp from the target
Then a cleanup system
Foreach (Ability, Cast) that removes the tags that were added like CancelCast
oh.. i think i know how this is going... like.. every system acts as a gate... and it has to satisfy each system
Basically!
Instead of a CancelCast component, you could just remove the Cast component
And create a CastError entity
That displays a message to the user "Out of range"
There's many ways to go about this :p
ECS is weird at first, but once you have the "click" to stop thinking in OOP, it's really magical xD
And the cool thing is that later on you can seemlessly add functionality to this. Imagine instead of targeting an entity your ability is an AOE. Well you'd have two components, one called ENtityTargetting and the other called CoordinateTargetting for example, and have two systems that process these targettings methods differently
Without compromising the damage, cooldown and any other functionality of the ability
I hope I'm not spamming, sorry ^^
More than stop thinking OOP, yo uhave to explicitely think DO. System ordering is of course a thing, but even more is data layout, to stick as much as possible to hardware computing
Only because you're used to it
for human brain yes
Care to elaborate?
What's good and bad data layout?
In short (then i'm going to bed)
data input and output
and archetypes and how chunks will lay in memory
for maximised parallel query and processing
Selecting good data candidates and how to describe them is a good part
And the designing of your components can affect that?
My knowledge of DOTS is really high level so idk
Yes, and how often they will mutate, and so on
Like you said earlier, many ways to simulate a problem
For performance-intensive areas you want to minimize structural changes as much as possible, give ScheduleParallel a chance to do it's job easier on nice uniform chunks of data. We have lots of tools to do that thankfully
If I read well you're doing netcode ? that already gives you some kind of pattern with the commands sync, serialising, client prediction, and so on IMO
anyway going to bed, gnight all
nn
So... have I been doing things wrong if I've been using Schedule instead of ScheduleParallel? ๐ฌ
And I just tried using ScheduleParallel and I've got a bunch of container errors :/
Schedule is fine
depends on scale really
if you dont need the work to be split on extra threads, then schedule is fine
ScheduleParallel will support greater numbers
most of my work is done using schedule/run
Okay so I'll make the switch when/if I get there lmao
im working on some networking stuff and doing everything i can to use ScheduleParallel as i dont want too much networking overhead
ANy guidelines on what "work" should be done in parallel
but much of my gameplay stuff has all been schedule
And yeah if you're using a native container then scheduleparallel won't work unless it's read only or you use a parallel safe version of the container, which may not even work for some use cases
@zenith wyvern Is NativeStream safe for ScheduleParallel?
I believe so
Wow so the native collections aren't even suitable for parallel work?
usually there's an associated parallelreader/parallelwriter with native containers ๐
so you can do something like NativeHashMap.ParallelWriter
Basically any performance intensive work that has the possibility to cross chunks
NativeArray "just works" in parallel jobs - assuming you don't do anything crazy with your indexing. And yeah, other containers will generally have AsParallelWriter
Alright I appreciate the help!
So when i was messing with NativeStreams yesterday, I had to use those WithDisable...... methods
Any ideas if thats going to be a issue?
AFAIK you shouldn't need to disable safety checks, it's only an issue if you're trying to access the same index from separate threads. In the collections test folder you should check the NativeStreamTests, it shows how to use it properly in parallel jobs
I didnt know about the nativestream tests, will check those out. Been super hard to figure out its use
Is it bad practice to add and remove components often? You mentioned minimal structural changes but I find that to solve a problem, I often have to resort to systems talking to themselves via components
I think most of my systems have entity commad buffers adding and removing components
I often add and remove stuff, but been trying to keep it to tag components
If it's working for your game, don't worry too much about it. Profile first then you can decide how to proceed.
I'm not sure if it was implement yet or still coming but Unity was talking about doing optmizations around tags so adding and removing them would have low/no cost
My general rule is to avoid per frame structural changes if possible
Beyond that I do it whenever it's convenient
use tag components, they are a great tool. yes they do trigger structural changes, but for most of the time getting started it will not matter. you can go back in and refactor things very easily due to the separation of logic (systems) and data (components)
Yeah I'll take the approach "Optmize later" while I learn about DOTS
yup thats what I do ๐
please do, its super easy to refactor systems
Exactly :p
even unoptmized DOTS is wayyyy faster then monobehaviour
I don't plan to do a RTS so I don't know if it'll ever even get to that point
focus on making the game or learning dots then
does an entities.WithChangeFilter<thing>().ForEach(ref thing) make itself dirty
No. It would make it dirty for the next system that uses changefilter for <thing>
If you mean on the next frame, no
If you're manually updating your systems, no idea. Probably
ok i guess that's good. so only when another system modifies it then it'll count as dirty for it
Yeah
Well
When another system queries for it as ref
Or writes to a ComponentDataFromEntity/BufferFromEntity for that type
If you include it as ref in a query, whether or not it actually writes to it isn't relevant
oh ok
@zenith wyvern Is there a better way to optmize the change filter?
maybe a manual job (Chunk job?)
Not sure what you mean by optimize the filter
like if i have a foreach ref component
if something... wirte to component
it will trigger the change filter for every entity with that component, even if i didnt actually write
Yeah, if you want to avoid that you need to have conditional logic on the first job that writes to the component, so the job only runs on certain conditions. In my roguelike I have jobs based on user input that set off a whole chain of change filter jobs behind the first one.
If that won't work you need to remove your component from the query and pass in a componentdatafromentity instead. The component won't be "changed" unless you write to the componentdatafromentity inside the job
Just keep in mind ComponentDataFromEntity is really really slow
Is it ok to reference an Entity on a component attached to a diff entity?
@gusty comet Yup, storing entity references is ok
But if the entity stored gets destroyed and you try to access it you will get a error
You can use EntitiyManager.Exists to check to see if its still around
Alright thanks @ocean tundra
I have one other question, is having a nativearray on a component acceptable?
You can only have an unsafe array on a component, and that comes with complications. Dynamic buffers are generally the way to associate a resizable list with an entity
Awesome thank you sark
If I use AddComponentObject to attach a gameobject to an entity, does that mean the gameobject is destroyed when I destroy the entity
No. conversionSystem.AddHybridComponent will create a hidden gameobject associated with the entity, and attach your component(s) to it. That game object has it's position automatically synced with the entity and will be destroyed with the entity
I don't know, I don't use subscenes
How do you use things like prefabs then? just built them all via code?
No, I just use ConvertToEntity on everything
It works the same as subscenes but you don't need to bother with ConvertVersion nonsense
oh yea, i thought they marked that obsolete?
Not that I know of
i swear i just read something about that the other day...
oh no "We still support more granular approaches like the ConvertToEntity MonoBehaviour and some function calls in GameObjectConversionUtility, but those should be avoided and are only kept around for dependencies we will remove in the near future."
Ahh well, I've had nothing but horrible experiences with subscenes. So I'm not using them until I have to. Or maybe I'll just abandon unity at that point if they don't make them any more user friendly
i got to go sorry, but good luck
my experence with them in latest has been good
but wait and see
Any costs to use ecb.AddComponent on an entity that already has the component? Should I check with HasComponent first or is it not necessary?
it won't add it if it exists
So I was looking at the docs for hybrid components and wont this code just keep adding the component over and over again ever single frame?
[ConverterVersion("unity", 1)]
public class DoohickeyConversionSystem : GameObjectConversionSystem
{
protected override void OnUpdate()
{
Entities.ForEach((Doohickey doohickey) =>
{
AddHybridComponent(doohickey);
});
}
}
@gusty comet The key point there is GameObjectConversionSystem
That system will only run 1ce as part of conversion
Thank you roy.
All good man
I really like how clean code can be with dots. Can't wait for more of the engine to be exposed
yea me too
Feels really nice adding bits
but i still run into the issue where large complex bits can be really complicated
๐
but i think thats mainly cause DOTS is missing bits, so i end up building those bits my way and integrate too closely with whatever im trying to make
so is there a way to get all components of a certain type in the scene as a nativearray
There is but why?
So you need to make a entity query, and then it has a toarray (or to nativearray) method on it
but ive never needed to do that
I am getting spawn point locations, each entity is a potential spawn point. In my spawn system I want to get each potential spawn point, decide if its actually valid. If not destroy the entity, after all invalid spawns are filtered out I want to convert them to a nataivearray so I can use array.sort on them to sort the spawn points based on distance to the observer
the steps up to destroying the entity would work well as a Entities foreach
but i dont know about sorting
sorting would be a seprate step
the entities foreach can use run
and you can use WithStoreEntityQuery to save the query
You're not guaranteed of order they've been queued in
then use that query to ToNativeArray
Because I want to sort the potential spawn points of my ai to areas only near my character
if I spawn 10 ai i want them to spawn at the 10 closest spawn points to my player
and array.sort and a custom comparer works fine to do that
public struct DistanceComparer : IComparer<float3>
{
float3 value;
public DistanceComparer(float3 distanceToTarget)
{
value = distanceToTarget;
}
public int Compare(float3 a, float3 b)
{
var targetPosition = value;
return Vector3.Distance(a, targetPosition).CompareTo(Vector3.Distance(b, targetPosition));
}
}
why not use 2 systems for this.
1st system would Entities.ForEach all spawn points and then store the nearest points in a DynamicBuffer.
then...
2nd system would go through the DynamicBuffer and spawn them
sounds like a lot of work, what would be the benefit of this?
I think the 2 systems would actually be less work
how?
sounds like more as 2 > 1 ๐ but you would have 2 tidy small systems
NativeArray<float3> arr = _query.ToComponentDataArray<SpawnPoint>(Allocator.Temp).Reinterpret<float3>()
and get to use all the standard ways of doing stuff
But yeah I'd probably do it via a foreach as well myself. Pass in the player position to a ForEach over your spawn points
wouldn't I have to do like 3 recursive loops?
Eeehh yeah I guess if you're getting the top 3 a sort may be best
Foreach would be fine if you were just getting closest one
There's an async version of the function I posted above as well, you can use that instead if you don't want to block any jobs on the main thread
Alright is that an expensive function to call?
Not really. It's creating a copy so if you have like 3 million of these spawn points you might want to think twice
Otherwise it's fine
Just remember to dispose it if you allocate it non-temp
Also keep in mind you're not getting references or pointers to actual components. Just copies. So changes won't have any effect to the actual components until you write them back
Alright thanks for the info, don't think ill have any issues though just reading data for now.
Also you shouldn't use Vector3 math if you don't have to. The new math library will generally perform better in burst with float3s
math.length == Vector3.Distance
How do you manually create a system these days?
doing World.CreateSystem seems to work but it doesnt show or run
You're creating it manually but you want it to auto update?
Did you DisableAutoCreation on it?
Yup disabled auto create
You can do DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups
Seems like an odd thing to be doing though if you went out of your way to not create it in the first place
Cause i have to setup a few confusing bits first
NativeContainers and network streams
I would suggest using a singleton component or something with RequireForUpdate
Bit easier to understand when looking at just that system
but you cant have native containers in a component?
your right it would make more sense as entities
You could with a managed component, but I more mean for the purposes of preventing the system from updating until you're ready. You only create the component it's depending on once you want it to go
With RequireForUpdate it won't run until then
hmmm
makes sense
but i also need 1 of the same system per player
again i could move that to entities..
Oh, yeah, that sounds like manual creation might be the way to go then. I haven't messed with networking so you probably know better than me what makes more sense
also a managed component wont do, i want to use burst
๐ no idea if this is the right way
feels rightish ๐
Anyone know if EntityGuid is safe to use as a unique id?
Unique? I'd say yes. Stable? No idea
@ocean tundra Unique in its World for the duration of this session. So I wouldn't store it in a database I guess but I didn't have to inspect its values yet so don't know really.
Hello, calling for help here again. Has anyone ever used RemoveComponentForEntityQuery?
well I just realised that it is super new
So ideally I need to be able to use build my game for WebGL buuuut I've already done a decent chunk of work on it in DOTs
I hear that Tiny supports WebGL builds but I am having some teething troubles transferring acrosss, does anyone know a good way for doing this, or adding Tiny to my project?
For references I am basically pure DOTS about from camera and some text UI
Does DOTS normally not support WebGL?
it wasn't working for me and I thought I read somewhere it doesn't
but perhaps there was some other reason it wasn't working for me ๐
but I think it's quite easy to find out of date information about DOTS so maybe that isn't true
Burst might be problematic?
okay
well that's nice to hear
now I just need to work out why it didn't work fine for me xD
however that doesn't mean that it is always bugs free
i.e. today I found problems with IL2CPP
hmm let me try if my currrent demo runs just to be sure I am not getting confused
man it would be great if we at least 1 dots dev would come in here so he can hear our complaints...
when is our enable/disable components!
-> forums