#archived-dots
1 messages ยท Page 196 of 1
{
ECB.RemoveComponent<UpdateUECSEntityAfterSubmission>(id);
}).WithStoreEntityQueryInField( ref _entityQuery).ScheduleParallel();```
or any variance of this
I have a question is it normal for something to be inordinately quicker singlethreaded than multithreaded or could I be doing something wrong?
I have a job calculated on 1million entity's takes roughly 315ms across all 14 cores or takes 230ms on 1 the main core
There's a slight overhead of schedulling in multithread. So yeah if it's a single job or on a few entities it might be faster to .Run() right away
yeah I know there a slight overhead but my job is way over a small overhead
yeah I see that haha
yep webgl works and frankly it's amazing that it does
how can you be sure a job is using Burst does it show in the profiler, isn't burst automatic now?
ok cool, thanks, that's what I'v been doing, using withoutburst to get things working, then schedule(), and run() and scheduleparralell() for the end result
is there a way to know if entities with a specific component exist?
this is last today question I think ๐
๐ญ
I think you can use an Entityquery or HasSingelton if there is only one
_entityQuery.IsEmpty apparently not super straightforward operation
I mean that's kind of the whole thing of entityquerys and jobs no need to check if there isn't an entity because they won't do something unless there is
RequireForUpdate if it's to prevent a system from executing if comp is not found
Someone using 2D Entities? I'm getting erros when importing
Have you actually gotten past the point of just rendering in webgl with dots? I was able to render stuff but it started breaking in weird ways as my project developed
Stuff just started silently failing and I would get indecipherable exceptions constantly
@zenith wyvern that is this demo: https://twitter.com/sebify/status/1353689203184459778
Moved to entity command buffer plus new hybrid renderer increased performance noticeably especially on entity creation. I had to record with phone because the gpu couldn't cope with it. https://t.co/VvwFcILnsn
ofc what you see in that tweet is not webgl, wasm is not so powerful
but it's the same with a crappy frame rate
Good to know, I'll have to revisit it then, thats exciting
does the entitycommandbuffer actually work well to create entity's now?
however IL2CPP is bugged! at least on this demo it breaks
I just finished to profile it, while it works, it's still slower than I thought
Oh so you had to disable il2cpp on the build configuration? Maybe that was my problem
no I mean, some parts break
when I tested before it was about the same with just a raw for loop to create as it was to use an ecb job
I can't spawn more than the first batch of balls
but it breaks also on windows, it's a bug with IL2CPP I Should report it
is it better to query empty dynamic buffers, or delete them when empty and readd when using again
To me it sounds a lot more complex to add/remove the buffers than iterating over the empty ones
ok
currently whats the proper way to convert scenes to entities? Like if I'm making a mud and I wanna make some room scenes
am i able to make some kinda prefab that i can spawn at runtime?
You'll probably want to look at subscene conversion
So guys I thought my way to handle abilities was pretty solid but now I'm seeing a problem.
Say I have a string of systems as I like to call it that goes like this:
SystemA WithNone<Cancelled>
SystemB WithNone<Cancelled>
SystemC WithNone<Cancelled>
SystemD WithNone<Cancelled>
SystemE WithNone<Cancelled>
SystemF WithNone<Cancelled>
Any of these systems can add the component cancelled to the entity to "break" the chain. But now since this requires structural changes of adding the component cancelled, I need to use the entity command buffer and that means the component isn't added before the end of the frame. Is my understanding wrong or is there any way to make this scenario work?
If I "break" at System C on an entity, I don't want system D, E and F to act on that entity.
i think you'd have to have sync points immediately
instead of adding/removing component, maybe you could use a bool? the adding/removing components.. i think that's good only if there are common sync points between them
like if the systems occur in order on the same frame then uh... yeah idk.... if you wanna add/remove then i guess a sync point between each of the systems needs to be there but idk if you want that
Probably gonna have to use a bool but I feel like it's dirty, to have access to query filters like WithNone but instead use if(component.bool == true) return;
yeah i know.. i also dont like how we can't skip processing empty dynamic buffers. And uh... i really wanna be able to use a change filter but with dynamic buffers for stat modifiers and stuff and i can't figure it out cuz like.. the stat modifiers always need to be ticking down their durations, and then ideally it would stop processing when they're empty and then i would recalculate the stats but change filter on dynamic buffer that's always recalculating would always be dirty, unless i keep deleting/readding the dynamicbuffer, but then on delete the stats can't just do a changefilter<DynamicBuffer<StatModifier>> cuz it aint there so idk
Haha yeah I get you
Instead of having the stats modifiers ticking down, why don,t you have buff / debuff entities that have a duration and that are in charge of adding and removing the modifiers from the stats?
i cant figure out how to do stats that only recalculate when dirty in an elegant manner. I'd have to manually mark each stat dirty in a system before i use every stat and that's just so complicated. with monobehaviours it was a simple property that just recalculated if dirty and then returned the value
oh.. like status effect components in the old monobehaviour
The way I see it buffs and debuffs should definitely have their own entities since they'll have names, icons, a list of modifiers, etc
so.. every character would have a list of entity fields that reference each buff/debuff entity... and then uhh..
You have event that on apply add the modifiers to the target of the debuff
And another for when it ends, to remove the modifiers
so... on character would just have a DynamicBuffer<StatusEffectRef> or something... and then uh... the statuseffect would be a component that also references the character entity... ok i think i get it
what if i want stat modifiers that grow or decay over a duration?
You could have different types of duration components, one like StandardDuration, other one DecayingDuration and they are treated by different systems
so.. instead of adding the stat modifier... idk.. somehow when i retrieve a stat, it needs to calculate the correct value from the growth/decay statmodifiers applied to it
unless i always calculate it every frame but that seems like a terrible idea... and yeah idk i'm always stuck on how to make an elegant system that recalculates only when needed
i can't just use events with systems cuz they have a definite order to them and stuff... so.. idk
idk how to do it argh i've been stuck on this and idk
I'm also trying to figure out events and order atm with the problem I mentioned above
Maybe someone has more insight :/
I need to use the entity command buffer and that means the component isn't added before the end of the frame. Is my understanding wrong
Not at the end of the frame. When the ECB you targeted will execute
each systemGroup provides one, and you can add yours
actaully 2, at beginning and end
Right, but we agree it wouldn't make sense to execute the entity command buffer every system?
Well technically could I execute it only when I chose to add the cancel component?
Nah. Is it okay if you read all modifiers inputs and compute them on a final value. Then check the Cancelled component only when trying to cast your ability ?
I guess I could do that. Just feels dumb to calculate if the target is in range if say, the ability is on cooldown, or vice-versa
something like that, depends on what yo have now of course
But that might actually make more sense
So I would do all the checks, then add "ReadyToCast" or something, and then in another group, actually cast it
can't you Query abilities WithNone<OnCooldown> ?
Only if it has ReadyToCast, otherwise dump it
Yeah but it was just an example as there will be multiple conditions
yeah readyToCast sounds good
Thanks for making me think outside the box hehe, I appreciate it
๐ happy coding
Does any component system group I create come with an entity command buffer or do I have to manually configure it? Also, do I always access it with World.GetExistingSystem<EntityCommandBufferSystem>() or is there a different way to get the buffer from within system groups?
just found about this https://twitter.com/_kzr/status/1341302567884623872
From Burst 1.5, you can directly call Burst-compiled functions without manually handling function pointers. It's quite handy when using heavy math functions. https://t.co/XiF22xEcPc
@dull copper been there for a while, its a great thing
function pointers has been there for a while but it's a whole lot more complicated to author them
this is just static class and function inside it
I'm still wondering why they need that static class for it
it's still adding a bit of boilerplate if you only need a single static function to get burst compiled
but I can totally live with that
for utility things like in that, it's really nice
do note that Burst 1.5 isn't even released yet, it's still in preview
the only way to assign into a dynamic buffer is to do a for loop right? foreach and enumerators dont allow assignment?
and if i wanna remove stuff, i gotta do for(int i = buffer.Length-1; i >= 0; i--) right?
you cant use foreach
but you dont have to use loops with dynamic buffers
i do buffer.Add and dont need a for loop
i cant make different dynamic buffers that use the same struct on the same entity?
like... if i want to categorize different stats and have a buffer for each one, although they all use the same Stat struct?
so a Primary stat buffer, Secondary stat buffer, etc. all using the same Stat struct isn't possible?
No you cant
have to have different types
if you try it it will replace the existing buffer
or you can use different entities
dang... that's kinda painful.. and generics with structs isn't useful either i guess.. so i can't use generics methods to do stuff
eg you have a player entity and a player primary stats, secondary stats... ect all linked
just dont use generics
untill unity confirms they work its not worth it
soooo painful
ok
thats why i use code gen
idk what code gen is
can easily make 100s of stats and their buffers ect
all the systems are basicly the same, just with different types
how do i name the entities in the entity debugger through code? or is that not possible?
There's a set name emthod on the entity manager I believe
oh ok thanks
@warped coral make sure to wrap each use of it with #IF UNITY_EDITOR
it only exists/works in the editor
oh.. it's an editor only method? ok thanks for the heads up
That's annoying haha
you can also just use asmdefs and put editor only stuff in separate assembly
Maybe make a extention method and use that instead, then the extention method can have the #IF Editor
or use Editor -folder that's treated special for that
altho I have no idea how this all works with DOTS
na that method dosnt work like that
editor folder stuff dosnt really help with dots
is it a terrible idea to put a fixedstring32 on every stat so i can change around the stats in future game versions? or should i hardcode stats to an index within an enum and never change them?
use a enum
as that is actually a int under the hood
and you can set the enum to any number
but also if you r going to add a new stat, you would likly release a update containing code
I just want to double check with everyone how they get their Entity Command buffer, is it always through the CreateCommandBuffer() from the EntityCOmmandBuffer system?
@fluid kiln that sounds right, im away from my DOTS code atm. i think i use the EndSimulationBufferSystem
yeah i mean idk... if i have 8 stats and access the buffer by the enum index... or... if i just put a name on all of them and then find them by name... i know using a name is slower and takes more memory. just dunno... if i wanna be able to modify stats and stuff in the future
and you also need to add the dependancy
usually, new stats = new game features
that would require a full game update to be released
a enum/number is a good choice as you can keep adding untill you max out the int
then previous saves become incompatible usually? cuz idk.. hardcoding it seems like.. its gotta be set in stone then
Stats should be linked to types or a serializable index
Not a string
Therefore your saves are always compatible
not really, you just need to be carfull
follow good update rules
in API develppment when something is release just NEVER remove the old stuff
The name of the stat would be a field that has no purpose other than to be displayed to the user
so you can Add and Change stats
so i can never just remove and replace older enum indexes
but deleting them you dont, instead you might disable, but the code/types/ids are still reserved and used by the old stats
Well you could as long as you save load takes that into account
unless maybe i have a system for that? that manually does swaps or something if my enum structure changes?
yea and eventually you could do a big patch that breaks saves
or more likly your controlling the save/load process so you can fix/remove/cleaup that dead data on loads
my player creation looks like this. is there any way to turn it into ecs in an elegant way? ```
async Task<Entity> NewPlayer(Session session, string characterName) {
session.Name = characterName;
string password = string.Empty;
session.WriteLine("Do you want to create a password?");
if (await session.ConfirmResponse()) {
session.WriteLine("Password?");
password = await session.ParseResponse();
}
Entity entity = EntityManager.CreateEntity();
EntityManager.AddComponent<Disabled>(entity);
EntityManager.AddComponentData(entity, new Player(characterName, password));
players.Add(characterName, new PlayerInfo(entity, password));
EntityManager.AddBuffer<CommandText>(entity);
EntityManager.AddBuffer<LogText>(entity);
CreateStats(entity);
AssignDefaultStats(entity);
session.WriteLine(string.Format("{0} created.", characterName));
return entity;
}
im using the entitymanager a lot and that feels bad
Why isn't your player a prefab?
im still new to ecs and have no idea how the conversion works
basicly you just build/create with normal gameobjects and prefabs
while in editor
and then during build, boom converted
it converts it into entities that are fully compatible with the serializeutility so i can save/load just fine?
yea
it convertes into subscenes
which you then load/unload like normal scenes
i havnt messed with serializeutility in ages, but it was a major pain before
basicly it would save all your pure dots easy as, but if you had a mesh or any old gameobject stuff, it would just give you a gameobject with everything attached, which you then need to manually figure out how to save
i've made a serialization system for uh.. just monobehaviours before.. to save and load gameobjects automatically... but i guess using ecs.. i wanna just never use any object references... i dont wanna deal with that stuff again
hmm yeah... i'm currently making a mud so i dont need all that stuff.. but i do plan on adding graphics otherwise nobody will play it... and also without graphics using unity would be a waste so... yeah anyway at that time i'll probably use my serialization thingy to do it somehow
why do you want to create one?
unless maybe i make all the graphics not need saving... like just keep stuff in a resources folder and load them by keeping a name on every entity that needs it
๐
thats nasty but works
i managed to get addressables to work, but it was akward
is the conversion workflow hard to learn or use?
like if i just wanna make rooms and turn them into entities
last time i couldnt even use subscenes
Actually the doc doesn't answer my question
tried just this week was super easy
and i still dunno how i wanna place the new player into the newbie start room
like i assume i'll make a bunch of room prefabs.. convert them when user makes a world.. but idk how i'll like.. find a specific room?
to place new players in?
idk i guess ill figure it out
with monobehaviours it was easy.. cuz everything has coordinates. with rooms in a mud i have no clue
hmm..
so.. rooms will be entities... uhh.. i'd need something to contain all the room references? so i can loop through to find a room by its coordinates?
What is the point in .Schedule if it just blocks on the main thread till its completed?
what if i wanna create or destroy rooms at runtime.. and make sure it's still able to save and load ... idk. i think in old school muds every room was in an array, and every exit was in an array... i guess i gotta use a dynamicbuffer of entityref for rooms too or something idk i gotta figure it all out but im confused atm
@warped coral look at conversion more, you build your whole map in a normal scene, with gameobjects and components, you can setup spawn/start points, all your rooms and connections and then you get nice entities to work with
ok
@gusty comet schedule will only block in places without threads i think
eg webassembly
What about jobhandle.complete then?
yea that will force a block untill the jobs are done
doesn't that block thee main thread till the jobs finished if itsnot a parrallel job?
you shouldnt .complete stuff
Don't you have to in some cases?
maybe really weaird cases...
i do everything i can to NEVER complete
just not worth the block
Is there a way to get an entity from a component?
yeah
system groups are just a fancy name for your usual systems, but nested. And to create your ECB you just inherit EntityCommandBufferSystem and choose a name for your subclass :p then yes you retrieve it like usual
How?
entitymanager
Whats the method name? There is no GetEntity method
oh wait... maybe it was from system
oh i was thinking of singletons
oh right i asked that same question before
and found that you couldn't
my memory is bad
if the compiler doesn't throw an error then it's all good right
I am creating some entities in a job then later back on the main thread I am attaching a gameobject to the entities with AddComponentObject
EntityQuery m_Group = GetEntityQuery(typeof(SpawnPoint), typeof(Ped));
var array = m_Group.ToComponentDataArray<SpawnPoint>(Allocator.Temp).Reinterpret<float3>();
array.Sort(new DistanceComparer(position));
m_Group.CopyFromComponentDataArray(array.Reinterpret<SpawnPoint>());
var entities = m_Group.ToEntityArray(Allocator.Temp);
for (int i = 0; i < entities.Length; i++)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
EntityManager.AddComponentObject(entities[i], go);
and even if it is safe, this bit of code is probably going to be slow af.
EntityQuery m_Group = GetEntityQuery(typeof(SpawnPoint), typeof(Ped));
var array = m_Group.ToComponentDataArray<SpawnPoint>(Allocator.Temp).Reinterpret<float3>();
array.Sort(new DistanceComparer(position));
m_Group.CopyFromComponentDataArray(array.Reinterpret<SpawnPoint>());
what are you trying to do
I have a bunch of potential spawn point entities spawned I generate them every frame in a job based on cameras current position.
I am trying to order them by distance
so when I loop through them the closest spawn points will be used first
why do the spawn points need to be entities? you cant just use uh... vectors?
There is way more data than just the point on them
oh ok
I originally tried to
make all the data in a single struct then store them in a nativelist
but I was getting errors about accessing that array in a parralel job
did u copy the array to an array in localscope for you to use or were you trying to access it as a field on the system?
@fluid kiln Dont create new ecbs, instead use the built in ones
each ecb nees a sync point to playback
He wanted more than the default ones ๐คทโโ๏ธ
oh
@warped coral Yeah actually iirc the error was related to using the array on the main thread
the only way I could get it to run was to use a non parallel job and call complete first
so I decided to make them entities instead.
@gusty comet why don't you just query entities with the SpawnPoint tag with a simple Foreach ?
@karmic basin Because I want to loop through them in order from closest entity to furthest
so you tried to have let's say a native list in the system's scope and sort spawns by distance ? Didn't work ?
It did but when I got back to the main thread and tried to loop through the nativearray it caused errors
The only way I could get that to work was to schedule the job as non parralel and call complete on it (at this point I wasn't using a system just jobs)
why did you go back to the main thread? you should do it all within the job
var spawnpoints = .....
entities.foreach(something here){
var sorted = spawnpoints.sort
do stuff....
}
Because I needed to call api code that isn't available in jobs yet rofl
EntityQuery m_Group = GetEntityQuery(typeof(SpawnPoint), typeof(Ped));
var array = m_Group.ToComponentDataArray<SpawnPoint>(Allocator.Temp).Reinterpret<float3>();
array.Sort(new DistanceComparer(position));
m_Group.CopyFromComponentDataArray(array.Reinterpret<SpawnPoint>());
var entities = m_Group.ToEntityArray(Allocator.Temp);
for (int i = 0; i < entities.Length; i++)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
EntityManager.AddComponentObject(entities[i], go);
can't do that in a job
remove the Gameobject.Create and have a prefab entity?
then you can do ecb.Instante(prefab)
Yes but according to the docs the gameobject mirrors the entity and I need it to do the opposite
Why ? Because the DistanceComparer ? with dots mathematics it's an easy method call and you can Instantiate your prefab instead of a primitive cube
It's not meant to
yea mixing GO's and Entities is not great, Entities need to be the 'source of truth'
The link is supposed to be one-way
Unless I'm missing something I don't understand how 2-3 sync points is enough. Like I can imagine some big system chains. Let's say
- Input that creates an event to cast an ability
- Ability checks if the player meets conditions to cast
- Ability is cast applying modifiers to the player
- Something else that requires structural changes...
That means there'll always be a certain amount of frame delays...
number 1 dosnt need to create a entity, you could just set a value on a player entity component
The gameobject I am creating will eventually be moved on a navmesh through navmesh agent and if the entity is constantly mirroring itself onto the gameobject , the gameobject will never move
@fluid kiln again 2 can set a value that it can cast
hum I think that's exactly what you say that's gonna happen, your GO will constantly b set back to the ENtity's position...
3 would then create the entity, using a ecb
Yeah but then instead of having ForEach that are meaningful, they'll be filled with ifs... Isn't that anti-pattern? idk
So I guess I have to use navmeshquery instead
but you have no choice, at least that's how Companion GameObjects work
was really hoping to just be able to hack my way around it
@gusty comet i belive there are job save pathfinding now, but still confusing to use
its very primitive
you basically have to build the path node by node yourself in a system
yea
you could break it apart more, GO (not companion) that does ONLY nav mesh => read into your entity => your entity to its companion
thats what I am trying to do now
that inital GO/pathfinding bits, can all be seprate systems and components
@gusty comet it should be clearly stated in this page that the conversion link is one-way https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/conversion.html
Yes from Entity>GameObject
so I tried to get around this by making some hacky code that "works" but what I am wondering is
is this safe
EntityQuery m_Group = GetEntityQuery(typeof(SpawnPoint), typeof(Ped));
var array = m_Group.ToComponentDataArray<SpawnPoint>(Allocator.Temp).Reinterpret<float3>();
array.Sort(new DistanceComparer(position));
m_Group.CopyFromComponentDataArray(array.Reinterpret<SpawnPoint>());
var entities = m_Group.ToEntityArray(Allocator.Temp);
for (int i = 0; i < entities.Length; i++)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
EntityManager.AddComponentObject(entities[i], go);
so you have a PathfindingRequest component you add, that triggers your system to either link/create a pathfinding GO, use a SystemState Component to store that link, another system that loops on thatSystemSate component to read (there is some sort of job save read Transform API somewhere)
oh so you're already trying an alternative, I see. Then you've think about it more than me
basicly try to have your main entity as pure ecs as you can, then for inividual old gameobjects you build a system to create/grab them from a pool, use them untill done, and release back to the pool, never directly attaching them to your 'pure' entity
do authoring monobehaviours also need to be in their own file
yes
@warped coral Normal monobehaviour rules so i guess yes
oh ok
@warped coral Also you know about [GenerateAuthoringComponent]?
no... im reading the conversion stuff in the manual and im confused
authoring component... and then.. a conversion system.. and uhhh.. something about setting up the thingies so they create entities.. before i actually convert over the data or something
@warped coral maybe focus on making your ability system work before adding more confusion ๐
Yea not gonna lie the entire gameobject conversion process could be documented better
Or maybe that will ventilate your mind :p
idk i wanna figure out the conversion stuff so i can make rooms and then figure out how to create new players in a specific room
why not just give every player their own world?
i wanna be able to make predefined rooms... I could go with procedural but i'd like to be able to manually make stuff first
I find it more clear now. Had to read blogs and check how Unity does it for Transform to figure it out. But yeah I'm sure I'm still not 100% on some parts ^^
I also wish it would let us define if the gameobject or entity is in charge when using companions xd
Then the next day they publish the rlease with docs :p
IConvertGameObjectToEntity is getting uhh deprecated right.. so i skip over that part in the manual?
@warped coral whoa what? it is?
Nope
it allows you to plug more during the conversion
And that's where yo ucan add for example Hybrid COmponents that don't exist yet in ECS
I mean in dots
like Particle System
oh i probably mistook it for something else
I wish we could add value types to entities
Probs the ConvertTotEntity Mono component. Now yo should use subscenes instead
I have so many components that just have float3 and int in them
@gusty comet but then how would you tell 2 ints apart?
Nothing wrong here
you can code a (implicit??) converter to reduce your code a bit
so you could do stuff like em.AddComponentData<type>(entity, new float3(x,y,z))
Yeah like 1 authoring GO that converts to many components ๐
its a little bit better
yea or for the authoring flow, you can have 1 monobehaviour that adds many components
is it usually better to use authoring game objects instead of generating authoring components from ecs components? it's better cuz gameobjects get broken down into ecs right?
yeah that's what I mean, MB, not GO ๐ ๐ ๐
my bad
@warped coral start with components and the [GenerateAuthoringComponent] directive
Even if it adds way more MBs
Don't overthink too much at the beginning ๐
ok
Otherwise you get stuck in your head and everything is confused
should i store the coordinates on each room.. or just keep some kinda massive hashmap with the coordinates as the key and the room entities as the values?
(off topic: the getting started doc of Project Tiny is 94 pages long... help....)
I want to reiterate because what I'm realizing right now is kind of shaking my whole understanding of ECS and I'm kind of stumped.
So far I had figured out how to implement functionality using ECS. I would actually do a LOT of structural changes because in my head that allowed me to optimize my ForEach loops and control what entities they are called on.
I would also use a lot of event type components to do some work.
For example: When input of type "destination" (point to move) was detected, I would create an entity with a component "Destination Request" that contains the destination and an enum "Request Priority" that would be an enum with some values like [Input, Crow Control, Cinematic, Forced]. This request would then be picked up by a DestinationSystem that would override the value of the destination component only if the priority was higher. (Crowd control > Input). Now what I'm understanding, is because I create this destination request entity, there is a delay of 1 frame between the input and the actual movement.
This type of structural changes are everywhere in my code and I know it's caused by my flawed understanding of the framework. But I still can't wrap my head around doing otherwise. Without the DestinationSystem, EVERYWHERE in my code where I want to change the player's destination, whether it is from input or crowd control, I would have to REWRITE the code snippet: if (priority higher) set destination.
Using a lot of systems with a lot of triggers seemed very fluid to me on the conceptual level. This is more a rant than anything else so I don't expect much from you guys but maybe someone can help me "click" on how to design systems.
Does anyone know how to manually set the update order of ISystemBase? UpdateBefore/UpdateAfter only work with standard SystemBase.
That's a whole design question. you could use coords, a grid system, load scenes on the fly, ....
At least Tiny has documentation and a getting started. Entities just chucks the user into the deep end with autogenerated documentation.
if i use a hashmap.. that's not good for looping is it?
Haha, true that ๐
You cannnnn but what it does is converts the hashmap into an array using memcopy then uses the array's IEnumerable to iterate.
Maybe try [UpdateInGroup((...), OrderLast = true/OrderFirst = true)]
I've only used ISystemBase once w/ UpdateInGroup
Yea but I need to chain systems one after the other. UpdateInGroup thankfully works. I'm running the main chunk of simulation inside FixedStep since I'm not using it for physics.
@fluid kiln yea i have that issue too, some ways ive seen to address it is tag components (unity said ages ago they will optmize these to have less cost on structural changes), unity also said component enabling is comming (when??? so you can have your destinationRequest compoent disabled untill you need it), sub enities, so you have smaller entities in a linked group as its smaller a structural change is less costly
and finally the enabled bool
There's still some primitive ordering with OrderFirst/OrderLast though it would still be subjected to how unity determines the order based on its read/write dependencies
Enabling or disabling components would be greaaaatt
no clue on what the satus of that feature is, i last heard about it like 6 months ago
Your Destination Request component is okay. Again many ways to implement based on your game. And again, NOT next frame, if your input reading is before an ECB, you can then have a system acting on it after the ECB but on the same frame
@fluid kiln
you could use streams as events to produce and consume same frame without sync points https://forum.unity.com/threads/event-system.779711/
I never liked using the ECB. Every time I tried, I get better performance just running a job with entityManager on the main thread.
i also code in expected frame delays for things, 1 or 2 frames at 60 or 120 isnt really noticable
in my head it also spreads some processing across frames
but not sure if its actually worth it ๐
but again i do networked stuff, so there is a network delay i often need to hide anyway
of like 200ms at worst
How many sync points is too much? Because right now I'd like to create 2-3 of my own like "InputEntityCommandBufferSystem" and etc...
yes, most of the time 1 frame delay does not matter
unity by default already has ~2 frames delay due to how the engine rendering works so if you don't notice now you prob won't notice +1 frame
Nobody can tell exactly -> Profiler is your friend
the generated authoring component for my room component doesn't have string fields for the name or description
@warped coral strings prob arnt converted
Alright thanks guys I'll persevere ^^
Looks interesting I'll give it a read!
so.. i gotta manually make a gameobject conversion thingies to do it?
If that works dont overthink it @fluid kiln You'll come back later to refactor eventually, when you get a good grasp on the pattern
Strings are special in DOTS. You'll either need to use a byte array to represent your string or use one of the FixedString32 variants. I dont believe autogeneration supports either though.
The way I understand it is that strings aren't usually data you actually want on your entities
so... i gotta manually do what... uh.. start from gameobject and somehow convert to entity?
You could have a resource file that stores your strings and then an index on the entity that points to that string
what if i have lots of rooms with unique uh... descriptions
Yep. A component containing either an int for an index to a managed string[] array or a ComponentData containing a FixedString32 variant.
Yeah I agree. For some reason I thought that a few frame delays was unacceptable as I was noticing it on screen, but maybe it's due to something else
oh
@fluid kiln's approach still works, you pretty much access the unique description via ID
this is how my card flavor text works
in my own game
so every room then needs a unique id.. hmm
could i use the room's coordinates as its id instead? a float3 or something as the key
Not necessarily. Every room would have a DescriptionId that point to a file with this id
you should use a blob asset instead for description
That works. Is there no way you can just use a int id? If you want to fall down the rabbit hole of over optimization, you can encode a unique ID into individual bits and use the resulting int to access a hashmap. But it's better to just assign each room a unique and sequential int index and use that.
its not like description data would change
and a blob asset can exist within a component
is saving and loading blob assets with serializeutility complicated?
The blob asset exists as a reference pointer. You're basically storing a UnsafeArray<byte> that's readonly.
@warped coral i think it would give you a list of blob assets, that you need to save and reconstruct on loading
And making a blob asset is so painful. The only benefit of using blob assets is that multidimensional arrays are accessed linearly in the memory instead of arrays of references that a UnsafeArray<UnsafeArray<>> would result in.
oh
I found blob assets pretty easy to create, just a bit wordy tho ๐
Yea, real shame the generic extension methods I had to make them got shafted with the new blob asset verification.
so... is a hashmap with coords to room ok or is it subpar compared to using an array
and what about having the coords turned into an array where like.. the x y z get converted to indexes
Honestly, it's okay. Comparing the performance hit between a hashmap (Dictionary since you cant store strings inside a NativeHashMap) and array is negligable.
Getting a werid exception.
ArgumentException: A component with type:GameObject has not been added to the entity.
Happens for this line
var agent = EntityManager.GetComponentObject<GameObject>(entity);
But i am already adding it with this code
EntityManager.AddComponentObject(entity, go);
Anyone know what causes this?
@gusty comet I imagine you cant use Gameobjects, instead needing to use components
but im not sure
Ill try
Is go of type GameObject that you manually made and implements IComponentData?
It cant be Unity's GameObject.
Then whats different between this and AddComponent?
One is for IComponent, one is for Monobehaviours
Still getting the same error with NavMeshAgent which is a monobehavior
ArgumentException: A component with type:NavMeshAgent has not been added to the entity.
It sounds like you're calling GetComponent before it's been added.
Let me double check
does this look alright ```
//Room entity components.
[GenerateAuthoringComponent]
public struct Room : IComponentData
{
//public FixedString32 Name;
//public FixedString512 Description;
public int3 Coordinates;
}
//Exit entity components.
public struct Exit : IBufferElementData {
//public EDirection EDirection;
//public Entity Destination;
public int3 Destination;
public Entity Door;
}
//Door entity components.
public struct Door : IComponentData {
public bool isClosed;
}
public struct Lock : IBufferElementData {
public bool isLocked;
public float LockStrength;
public int Key;
}
GenerateAuthoringComponent only creates an entity with one component. You'll need a separate authoring system or monobehavior to connect the rest to that entity.
But yea, seems about right.
oh yeah i haven't split the stuff into their own files yet
@zenith wyvern Nah its only being called after its been added
//in onupdate
Entities.WithAll<Coord, Ped>().ForEach((Entity entity, int entityInQueryIndex, ref Coord point) =>
{
if (spawnedPeds == null)
spawnedPeds = new List<GameObject>();
if (spawnedPeds.Count < 300)
{
var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = point.position;
var test = go.AddComponent<NavMeshAgent>();
spawnedPeds.Add(go);
EntityManager.AddComponentObject(entity, test);
}
}).WithoutBurst().WithStructuralChanges().Run();
barrier.AddJobHandleForProducer(Dependency);
Entities.WithAll<Ped, Coord>().ForEach((Entity entity, int entityInQueryIndex, ref Ped ped, ref Coord pos) =>
{
if (math.distance(pos.position, Camera.main.transform.position) >= 125)
{
var agent = EntityManager.GetComponentObject<NavMeshAgent>(entity);
spawnedPeds.Remove(agent.gameObject);
GameObject.Destroy(agent.gameObject);
EntityManager.DestroyEntity(entity);
}
}).WithoutBurst().WithStructuralChanges().Run();
barrier.AddJobHandleForProducer(Dependency);
@gusty comet Cant have Coord in WithAll and as a parameter in the Foreach ref...
just remove it from WithAll
@ocean tundra in which foreach? both?
yea
You dont really need the WithAll on the second Entities.ForEach. The lambda parameters already contain the references.
in the 2nd you have with all ped and cord, and you also ref those
so take the withall out?
i cant generate authoring components for buffers?
if i store exits in a buffer how do i add them to rooms during authoring
if generateauthoingcompoent dosnt work you can write one yourself
but i did read that it works
it doesn't show up in the component list for adding components. this is what my exit bufferelement looks like ```
//Exit entity components.
[GenerateAuthoringComponent]
public struct Exit : IBufferElementData {
//public EDirection EDirection;
//public Entity Destination;
public int3 Destination;
public Entity Door;
}
I dont believe buffer components are supported by authoring.
maybe there only supported with a single field?
ok so... i gotta somehow uhh.. do the things to convert gameobject over?
does return break out of a parrallel entities.foreach like it break would in a foreach loop?
or does it just return one iteration?
is there a way to break out of the foreach?
not that i know of
dont worry about it too much atm
when you need extra performance you can look at writing manual chunk jobs, and you would be able to break out of the chunk loop easy then
can i use some kinda hashmap or dictionary inside component data?
like is there some kinda fixedhashmap or something
or can i make a fixedlist<mystruct> and cap the capacity to 12 for each direction?
dynamic buffer is all you can use
i wish too that other collections can be inside components
I think you could use a class component and stuff a native collection inside it
but then no burst or threads
eww class components
You can use unsafe collections on components but they do not have leak detection and some of them behave differently from their native counter part
unsafe collections sound so ... unsafe ๐
im conflicted.. should i use a dynamic buffer for room exits...or just keep a fixedlist on the room component and populate for all directions even if it doesn't have an exit for that direction
cuz the generate authoring thingy is telling me that when i do the thing on an IBufferElementData, it expects only 1 field... and if i use a struct, the entity field doesn't get converted to a gameobject so... idk.... anyway idk how i should structure the rooms on the entity side
hmm.. i probably wanna index by direction so it's easy to move around
implement IConvertGameObjectToEntity
and use that instead of autogenerateauthoring
ok
[NativeDisableUnsafePtrRestriction]
private NavMeshWorld world;
protected override void OnCreate()
{
world = NavMeshWorld.GetDefaultWorld();
}
protected override void OnUpdate()
{
var w = world;
Entities.WithNone<SpawnPoint>().ForEach((Entity entity, int entityInQueryIndex, ref Coord pos, ref Ped ped) =>
{
var q = new NavMeshQuery(w, Allocator.Temp);
}).ScheduleParallel();
InvalidOperationException: OnUpdate_LambdaJob0.JobData.w.world uses unsafe Pointers which is not allowed. Unsafe Pointers can lead to crashes and no safety against race conditions can be provided.
If you really need to use unsafe pointers, you can disable this check using [NativeDisableUnsafePtrRestriction].
Why am I getting this error even though I have used to correct attribute?
probably needs to be on the type NavMeshWorld
You need to use .WithNativeDiableUnsafePtrRestriction in the entities ForEach and pass the navmesn world that function I think
@zenith wyvern I think you're right but can't figure out how to use it do you have an example by any chance?
@ocean tundra it is or am I missing something?
something like Entities.WithNativeDiableUnsafePtrRestriction(NavMeshWorld.GetDefaultWorld())
@safe lintel
.WithNativeDisableUnsafePtrRestriction(NavMeshWorld.GetDefaultWorld).ScheduleParallel();
Assets\code\PedestrianAndTrafficSystem\Peds\PedMoveSystem.cs(43,12): error CS0411: The type arguments for method 'LambdaJobDescriptionConstructionMethods.WithNativeDisableUnsafePtrRestriction<TDescription, TCapturedVariableType>(TDescription, TCapturedVariableType*)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Adding the type like it says with <NavMeshWorld> results in this error
Assets\code\PedestrianAndTrafficSystem\Peds\PedMoveSystem.cs(43,12): error CS1061: 'ForEachLambdaJobDescription' does not contain a definition for 'WithNativeDisableUnsafePtrRestriction' and no accessible extension method 'WithNativeDisableUnsafePtrRestriction' accepting a first argument of type 'ForEachLambdaJobDescription' could be found (are you missing a using directive or an assembly reference?)
do i gotta mark structs with system.serializable for serializeutility to work on them
ive not actually used any of the navmesh world stuff but thats how you use WithNativeDisableUnsafePtrRestriction in the foreach lambda.
So does that mean navmeshquery isn't compatible with parralel jobs in component systems?
why do i get this error on my roomauthoring component and what does it mean? ArgumentException: RoomAuthoring and RoomAuthoring have a conflict in the stable type hash. Use the [TypeVersion(...)] attribute to force a different stable type hash for one of them.
@gusty comet in https://github.com/zulfajuniadi/unity-ecs-navmesh/blob/bb4fe6ed2f847d6f2acd3547c3d3207214ec7a2c/Assets/NavJob/Systems/NavAgentAvoidanceSystem.cs hes getting that stuff in oncreate() and using a persistent query and just passing that into the job rather than getting it inside the job(note the api is older here)
oh crap wait.. its cuz i have a RoomAuthoring class and a Room with [GenerateAuthoringComponent] on it i think
@warped coral do you even think a minute when you're stuck before calling for help ? ๐
Calm down, take a breath, let your brain compute the problem and give yourself some time to try things ๐
@safe lintel just gives the same error as before but this time on the query variable instead of the world variable.
yes sensei
your changing your lambdas in the wrong order too
everything up front, then foreach, then run|schedule
Wow its actually not possible to use NavmeshQuery in an entities.foreach even tho its usable in jobs
I've tried everything
you just dont start it from inside a foreach
dont start the jobs from within a foreach, and chain any other jobs with them
I treid creating it in oncreate and using it in foreach
didn't work
I tried creating it in onupdate and using it in foreach
also didn't work
well
let me specify
not possible in parallel job
idk about regular one
Personally i always use https://arongranberg.com/astar/ for pathfinding
but i did have to do the raw movement myself
but it was probably faster that way as i could scheduleparallel
the slowest part is the start, where it has to cacualte a path, then take that path and turn it into a dynamicbuffer of points
pretty sure i had to so some without burst or run or something slow
does a* work with default unity navmesh?
single job query
[AlwaysUpdateSystem]
class NavMeshSystem : SystemBase
{
const int humanoidType = 0;
protected override void OnUpdate()
{
var s = new NavMeshQuery(NavMeshWorld.GetDefaultWorld(), Unity.Collections.Allocator.TempJob, 10);
Job
.WithoutBurst()
.WithDeallocateOnJobCompletion(s)
.WithCode(() =>
{
var start = s.MapLocation(Vector3.zero, Vector3.one, humanoidType);
var end = s.MapLocation(new Vector3(10, 0, 10), Vector3.one, humanoidType);
s.BeginFindPath(start, end);
while (s.UpdateFindPath(1, out int itterationPerformed) == PathQueryStatus.InProgress) { }
var status = s.EndFindPath(out int pathSize);
Debug.LogFormat("status:{0}", status);
}).Schedule(Dependency);
}
}
I've never used this api before so sorry for it not really being 'real' code
@gusty comet
to turn this into a ecs api, you would run a async collect all requested agents into a native array, and access them from a foreach job, that does roughly that ^ for each
i wish unity was further along with whatever the dots navigation package is, im surprised of all things its taking the longest to materialize, I wouldve thought it lend itself to dod much easier than something like animation?
what version of ecs are you using @low tangle? My job.Schedule() doesn't exist for me
neither does WithDeallocateOnJobCompletion
Yeah it works fine in regular jobs but once you scheduleparralel not so much.
@gusty comet no it has its own way of making navmeshs (grids)
or can create its on fancy navmesh
all dynamic at runtime too
is it not good to have fixedstrings inside of structs
not really
DOTS is all about DATA, and strings isnt actually data
strings are usually human representation (readable) data
where would i put them if i want them to save as part of serializeutility?
the room names and descriptions
i wouldnt
instead ill have IDs for them
and save/store that list somewhere
eg a scriptableobject
you can use scriptables
but what if the names and descriptions change at runtime and i wanna save those on the server
then on game start or load take that object and use it to look up the readable values
@warped coral send the name as a byte array when the player joins it
dont "what if' otherwise you can spend forever on things
decide if the will or wont
if they do then yea you can sync the values on start or something
ok.. i mean i want to be able to uh... have everything modifiable and persistent
What is everything?
but regardless what you're trying to do is pretty straighhtforward
i wanna use the room coordinates as the key for accessing the room infos... how do i do that with entities
well if you want everything modifiable then your basicly building a engine not a game
why are you making your rooms entities?
but i get where your coming from, my goal in all games is to allow mods
version that writes out to entites at the end
lets see if I cant convert it to a parallel for now
i want my rooms to be able to have components for different behaviours and stuff
@warped coral so really sit down and thing what a mod can do
eg ive been working on a RTS, so units make a good mod
so i structure the unit with JSON and on game load i take a existing general unit prefab, and make a new prefab from it, with all the new mod values set
@low tangle oh wow thanks bud this is exactly what I was trying to make
thanks for the reference I was sure it was impossible, I wish the errors for ecs were a little more obvious I see what I was doing wrong now at least
yeah no worries, almost done converting it to parrellfor if that navmeshquery supports it (maybe)
Have you tried binding any scripting languages to ecs yet then?
no i havnt, i've considered it but decided it wouldnt be worth just yet
so far just data
might have been how I did it, but the system to query interface was messy (reflection)
still working on better codegen to pull it off
i wouldnt use a scripting language anyway, with things like roslyn its possiable to just compile and run c# code
but theres some burried nuggets in there if you can get lua components as featureful as c# ones
yes, but its also sketchy even with sandboxing
people love to waste time attempting to excape sandboxes
haha yea
not everything is that kind of mod though
I only make multi player games
so cheating/being a dick to others is a thing that happens pretty often
again tho roslyn can really restrict c# code during compile
yea mp + modding = even harder
๐
i would file hash the game directory + mod directorys and make sure they match
which kinda helps
then im all server => client and very strict about not sending info to clients who dont need it
and client isnt a simulation its basicly a 'view' into part of the simulation
cant change anything
I saw they added "support" for modding by letting us load dlls that work with burst? How would I even learn how to do that
so.. i should just leave all the strings out of ecs? And just keep them in some dictionary?
@zenith wyvern Oooo when? where?
I last heard about it as a early idea, use unity to compile some c# code into a burst dll and then load it
but that was AGES ago
@warped coral I would do a dictionary per string type
eg titles, description, ui labels ect
if i access the room name and description together often, should i make one struct for those
doesn't help at all, if its on the client you can't trust it
file tampering is the first thing people spoof
you will have maybe 1 or 2 systems to read that data and send it to UI
@low tangle yea i know its not secure
was more for normal people to make sure they are on same versions (mods + game)
and had some mod packs active
yeah
whats the benefit of multiple dictionaries
more for you
read from one, write to another
easier to tell what something is
would this be ok as a dictionary value public struct RoomInfo { public FixedString32 Name; public FixedString512 Description; }
oh yeah.. and store it within a normal dictionary?
when you update the UI you send the ids of things
and the ui controller thing can just look up the values
thats fine, that kind of non changing data is meant for blobs
you'd really just access it like a scriptable object, check and toss into a UI field
UI and ecs dont mix
i don't understand blobs... is that different than authoring the rooms using subscenes
think of blobs as scriptable objects
there like a blob of components and dynamic buffer like data you can get a handle to and read from even within jobs
docs probably got a page on them
let me find it
what i did is have a UI controller and would get a reference to that somehow in create (it was a monobehaviour)
then in a entities.foreach without burst run i would send it what things it needs (eg selected units)
yeah, thats totally fine
you can also inject the monobehaviour with a entity, and addcomponentobject the mono
and then query it up within the system, keeping no direct references and the ecs pattern intact
you just have to without burst, run only
uhh... soo.. how are blobs made. what makes them different than like... subscenes.... Sooo... a blob can be its own file like a scriptable object?
@warped coral I normally have a method on my scriptable object .ToBlob or something that does that blob builder stuff
intresting, theres a blob cache built into conversion system now
https://docs.unity3d.com/Packages/com.unity.entities@0.17/api/Unity.Entities.BlobAssetStore.html
oh... that sounds neat... i wanted to use scriptable objects for making rooms and stuff but didn't know how to tie it into ecs
@low tangle Did the navmeshquery support parrellfor? About to give it another try now just diidn't see a point wasting time if not
if you want to do it all data friendly your gonna want to convert all your static data like room descriptions, with unique ids for each (name or otherwise)
then hash them all into a hashmap<key, blobassetref>
its meant to, I just havent finished yet. people barged into the office and wanted attention
your gonna want to write one of these, but I'm sure you havent done the syntax yet, so I'll finish it up in a second
so.. if i do that.. i can access blob asset stuff from within ecs?
can they be used with burst and stuff
yes thats exactly what they are for
oh
From burst changelogs
Added support for PlayMode / Desktop Standalone Players to load additional burst compiled libraries for use in Modding.
tyvm
now... to just figure out how
i bet it wont also trigger ecs code gen tho...
but i guess for modding i shouldnt let users make any old System, instead provide hooks....
how do you turn scriptableobjects into blob asset references? do i reference them (the scriptable object) on an authoring component and uhh.. do it when i convert?
How can I include a native collection within a job as readonly so I don't get these exceptions: InvalidOperationException: The previously scheduled job AggroSystem:OnUpdate_LambdaJob0 writes to the Unity.Collections.NativeHashMap`2[Unity.Entities.Entity,Distance] OnUpdate_LambdaJob0.JobData.closestEnemyMap. You are trying to schedule a new job DistanceSystem:OnUpdate_LambdaJob0, which writes to the same Unity.Collections.NativeHashMap`2[Unity.Entities.Entity,Distance] (via OnUpdate_LambdaJob0.closestEnemyMap). To guarantee safety, you must include AggroSystem:OnUpdate_LambdaJob0 as a dependency of the newly scheduled job.
@fluid kiln you need to dependancy track
so you have a job that writes
and another that reads
the read job needs to combide dependancies with the write job
and be ordered after the write
It says aggro system writes to the collection but it doesn't it just reads
then mark it as read only
entities.withreadonly
its cause unity cant tell if your only reading so assumes writing too
either way you should still combine dependancies
even if it works now
evenutally you will add more systems and the scheduler becomes more aggressive and it dosnt know theres a link between the 2 jobs
so will schedule them at the same time
boom explosion
in the write job
make a public method GetDependancy () {returns Dependancy}
and in the read BEFORE you schedule/Entities.foreach
get the write job system, and go Dependancy = CombineDependances(this.Dependnacy, wirteJobSystem.GetDependancy)
ps sorry for no real code ๐
it might be JobHandle.Combine or something
No worries I got it. Thanks!
@gusty comet yeah no dice on the parallel for version, you will have to stick with that part being on one thread
the NavMeshQuery is holding onto a native container inside, and preventing you from writing to it from more than one thread
attempted to create one query struct per each entity, but those cant store into a nativearray due to having a native container inside
if they were marked as unsafe, you could. but theres also some missing api versions, like a dispose(jobhandle)
I'd just stick with a single thread version
i can store blobassetreferences within blobassets right?
to ref other stuff from within? like i can do with scriptable objects?
@low tangle Yeah I figured there wasn't really a way to make it happen. Kinda sucks tbh. but hopefully navmesh will be built into dots by default
Is there something like https://docs.unity3d.com/ScriptReference/Physics.OverlapCapsule.html in dots rn?
huh i just found a weird bug i think
var r = Unity.Mathematics.Random.CreateFromIndex((uint)entityInQueryIndex);
var x = (r.NextInt(0, 1) == 0) ? pos.position.x + r.NextFloat(0, 40) : pos.position.x - r.NextFloat(0, 40);
var z = (r.NextInt(0, 1) == 0) ? pos.position.z + r.NextFloat(0, 40) : pos.position.z - r.NextFloat(0, 40);
x and z are always very similar when i run it for example they will always be between a range of 190 to 260 every iteration.
if i wanna use a nativehashmap... i need to initialize it with a capacity and allocator, and manually dispose it?
Iirc it autoresizes
oh... ok thats good
Its basically what nativelist is to list but for dictionaries
do i need to dispose it manually
i remember using a native thingy sometime ago and i had some memory leak warning
So whats up with gerenating random numbers in ecs
THey always generate to be similar to the last one if done inside of a job
thx
Not sure, I've never even seen that CreateFromIndex method. I think you would have to give it different indices to get different numbers
I am
Oh like within the same loop they are similar?
Yeah
Entities.WithNone<SpawnPoint>().ForEach((Entity entity, int entityInQueryIndex, ref Coord pos, ref Ped ped) =>
{
if (math.distance(ped.destination, pos.position) <= 10 || ped.needsNewDestination == 1)
{
var r = Unity.Mathematics.Random.CreateFromIndex((uint)entityInQueryIndex);
var x = (r.NextInt(0, 1) == 0) ? pos.position.x + r.NextFloat(0, 40) : pos.position.x - r.NextFloat(0, 40);
var z = (r.NextInt(0, 1) == 0) ? pos.position.z + r.NextFloat(0, 40) : pos.position.z - r.NextFloat(0, 40);
var targetPos = new float3(x, pos.position.y, z);
Debug.Log(targetPos.ToString());
var startLocation = s.MapLocation(targetPos, Vector3.one, 1 << 3);
ped.destination = startLocation.position;
ped.needsNewDestination = 0;
}
this makes all the peds converge toward the same area about
Not sure, I don't know enough about RNG to know if that's expected or a bug
/// // Random numbers drawn from loop iteration j will be very different
/// // from every other loop iteration k.
Seems like a bug based on the docs
maybe its cause I am calling Next so often
cause i am not seeing any reason for my code to be producing very similar targetpositions for every entity
Maybe the RandomTests in the mathematics package could give you some insight. I just tried looking and it's a lot of big words I've never seen before so I got scared and ran away
I'm looking to implement the job system in my game. I have my networking stuff (UDP and TCP) running on different threads, but I'd rather not pass it back to the main thread, rather pass it to a job thread instead (so I can use the unity API without sucking the main thread dry)
Anyone have any info on that for me?
Would I just be able to keep a separate job or two open for my entire game?
You can't use any Unity API in a job
So I have UDP and TCP networking in my game
we're only talking about the server for now
each TCP connection runs in a different thread
and UDP runs in it's own separate thread
Is my only solution here to just pass the info back to the main thread?
to use the unity API
what info
messages received by UDP and TCP
I'd like to multithread that part somehow
but it needs to be able to use the unity API
Ok this is pretty easy to do
spin up a new io thread(no reason to use a job for this since you're not going to be using any unity api at all any how
yep already done that
use that thread to serialize data
and
pass it to and from your network thread
in form of a ring buffer
so basically
Serialization Thread > RingBuffer > Net Thread
keep in mind its single producer single consumer only though
so only one thread can write to this
anda only one thread can read
you can't write to it from 5 diff threads
this will give you a way to communicate between threads without locks
I've already got thread communication done with concurrentqueues
instead you can send pointers of data to other thread by using structuretoptr
is this different?
Yes
Concurrent queues just use lock behind the scenees
so its going to be much slower than ringbuffer
but
So then how do I multithread the part where unity's API handles all of the data
like updates positions, etc
why not just do the same you've done with netmessages?
damn that sucks
I don't think you can use TCP without spinning up a new thread for every client
otherwise it kicks the other client off
Yeah I don't really know much about tcp I don't use it
may I ask why you're not using a reliableudp library instead?
I hate using libraries
not sure why, just feels better to use what's built into C#
works fine too
I really don't think that is correct for networking
If you want to be able to multithread your game logic ECS and jobs can do that for you, they even have their own networking library in dots. But at that point you might as well just throw whatever you've already done in the garbage and get ready to screw around for months while you figure everything out
Networking isn't something you should roll your own solution for unless you're knowledgable in networking or are trying to learn. Lots of ways players can exploit your game and cause downtime if you aren't careful
So what exactly is the point of jobs if you can't multithread API code
like why not just use a thread
I use jobs to perform heavy calculations over a large number of entities
Dots has it's own API for game logic integrated with ECS
You can build a game with it but it's still early and not in any way comaptible with most of the existing API
rendering/physics can be done and very sparse amounts of animations and navigation can be done in jobs with ecs
might be missing a few things
Physics is entirely dots, has nothing to do with existing unity physics
How big is the performance increase when using dots properly?
How complicated?
Once you wrap your head around it its pretty simple, but it has a lot of gotchas alaong the way
Up to each individual - for me it took a very long time to wrap my head around everything
And at the end of the day it's still so early you can't expect to actually finish a game with it.
It's possible certainly but yeah
Is unity's regular physics system multithreaded though? I see that on my PC, unity likes to evenly use all 8 threads
Yes, but the real performance boost in dots comes from Burst
It's truly insane how fast it can crunch through complicated math
@gilded bay - This book is extremely useful for understanding the DOTS mentality: https://www.amazon.com/Data-oriented-design-engineering-resources-schedules/dp/1916478700/ref=asc_df_1916478700/?tag=hyprod-20&linkCode=df0&hvadid=266029226349&hvpos=&hvnetw=g&hvrand=11695572038639340120&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=9033320&hvtargid=pla-569068014630&psc=1
And every package integrated with dots uses burst, including physics, so you can expect it to go real fast
I own that book and personally did not find it very helpful. Your milage may very
yeah I learn better by reading online articles
So does the whole ECS thing have it's own physics? Like rigidbodies and shit?
Or would you have to create your own physics
Yeah, physics is coming along pretty well
There's a unity version and havok version
Both with pros and cons, but both will outperform built in by miles and mils
What about standard components, such as wheel colliders and everything like that
You can check it out for yourself https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/UnityPhysicsSamples
you can leave things like vehicles as regular gameobjects still
So say you wanted to do something to an ECS rigidbody. Is it the same as regular unity? rigidbody.velocity
or are there more steps
If you just went to affect velocity, not really. If you want to manually respond to collisions, then it gets pretty complicated compared to built in
yikes
If you want something simple, it's not the way to go. If you want something scalable, then it is
Scalable in terms of performance and the code you're writing. It forces you to think about your data in terms of how your CPU uses it
they do plan to have some apis that are simpler/closer to monobehaviour way down the line but still backed by dots
Yeah they did say that a long time ago. I wouldn't count on it any time soon
I wouldn't expect it until at least next year. This year they're focusing on improving the code gen for systems, which I think will be the foundation for the simplified facade APIs
I think they need to add more general functionality before they worry about a simplified api
@gilded bay the best way for me to wrap around dots properly was to think in sql databases.
recursive linked you the book but the long and short of it is.
entities = index / primary key.
components = coloumns.
systems = sql statements.
Yeah that makes a little more sense
is it just one system per file?
https://forum.unity.com/threads/unity-job-system-is-not-working-as-expected.809706/
Someone said you cant use unity api in jobs but this guy calls transform position?
the transform position he is callling is a member of TransformAccess which is not the same as transform
So basically
they recreated parts of the unity api that can be used
so far they have a rendering api, physics api, very early animation api and a very limited way to deal with navmesh
alright
is it safe to reference a component on another component?
no
Components are Sturcts, if you store a component in another component it will create a copy
same for entities?
thats why foreach uses ref, so when we set a value its to the same instance
umm less of a issue storeing entities
entities = id
so you can safely save that
BUT when using it you need to be sure that entitiy exists
you can use EntityManager.Exists for that
awesome thank you roy
any suggestion how i can make something like this work in ecs then since I can't refrence components though?
public class node
{
public node previous;
public float3 position;
public node next;
}
basically i have an editor script i can use to create "nodes" each node has a previous and next set so Ic an do like node.next.position
and so that the ai doesn't go off the navmesh
so its for a navmesh path?
super high level you can change node to Entity
but if its for a navmesh path theres a better way
can an entity refeerence another entity
its for a waypoint system
not a navmesh path
but its basically the same
yea
ok
so you can remove next and previous
and then change node to a Buffer component
so waypoint path, the 'unit' moved down it then back?
it loops
the unit moves from one point to the next, then back to the first point created when finished
a entity will have a buffer of path points (nodes) and a 'pathingwaypoints' component,
that component store next path INDEX
will the index of the buffer be the same order I add them in?
yes
awesome this sounds like a great idea!
and then in your pathing system you do something like:
entities.foreach(ref pathingWaypoints, in translation position, in dynamicbuffer nodes)
var nextNode = nodes[pathingWaypoints.NextIndex]
do some check to tell if needs to go to next index...
another check to see if at end of path
probs need to store path direction too
I think its so weird you have to use a buffer if you need an array on an entity
sorry that system should have translation as ref, and maybe a speed component/stat too, and you update translation as the unit moves
buffer,, array, all just names they are the same thing under the hood
could probably have called them dynamicarrays and everything will be fine
yes but the fact they attach to the entity
instead of being in a field on a component
is odd to me
oh yea that is odd
but makes sense
when you read more about memory layouts it all clicks and makes sense why they did it this way
for SPEEED!!!!
Yeah you can store an entity reference in a component
How does Graphics.DrawProcedural differ from commandBuffer.DrawProcedural
Is it a case Graphics is immediate while the latter depends on when the buffer is run?
Ran into a funky problem. Hoping someone has some ideas.
if (thingy) {
Entities
.WithoutBurst()
.WithChangeFilter<SomeComponent>()
.ForEach(() => {...}
} else {
Entities
.WithoutBurst()
.ForEach(() => {...}
}```
Copy paste took more effort then expected xD
This is some code I have in a system based on SystemBase
And it seems to not actually be running properly due to them being the same query, but the changefilter being applied based on the condition
if (thingy)
{
myQuery.ResetFilter();
}
else if (!myQuery.HasFilter())
{
myQuery.AddChangedVersionFilter(ComponentType.ReadOnly<SomeComponent>());
}```
If I do this instead, and use an old Entities.With(myQuery) using the ComponentSystem instead. Everything works fine
Basically I want to run my ForEach with an optional change filter. And it's not liking this ๐ฆ
The issue is that internally, it will generate 2 functions to generate the 2 queries
however since they are the same beyond the filter, the 2nd generation attempt will grab the cached first query :/
And then set the filter on "both" due to it
maybe you could alter your second query as a workaround?
like querying for an additional component etc.?
Wasnt there a way to reuse queries and set/remove filters with entities.foreach too?
I can technically leave out the filter, have it store the query and do the filter there manually
But at that point I'm working around additional Unity ECS bugs, and I don't want to
Isnt that essentially what you are doing with ComponentSystem now?
If you need so bad to use ForEach instead of IJobChunk, you can just create 2 systems and make "thingy" be a condition that both knows (so you will have only one of the two system actually executing)
oh, just remembered about the WithStoreEntityQueryInField, you could try use to do the same logic as here and have only one ForEach
not sure if it will work
hey bruno, sorry for calling your attention, but is there a way to cache subscene entities onto an NHM without using a System to do it?
not sure what you mean by that @deft stump
so for context:
I have 6 x 3 panels in a grid.
this grid is a subscene.
now, I want to store these panel entities onto an NHM.
but, when I try to do it in a custom Authoring -> Play -> NHM is empty. (maybe because it's in a subscene that's why it won't store? I dunno why)
so the only jank solution i made is to make a System that checks / adds all the Panel entities onto the NHM.
And enable the critical Systems that needs to do the actual work once I validated it's all in there.
The manual filter? Yes.
Just saying that you could do the same with SystemBase which should be more future proof. But @rancid geode 's idea to use WithStoreEntityQueryInField might be the better solution
Yeah using WithStoreEntityQueryInField was the plan, it's the only way to do this with SystemBase
The reason I wanted to switch to SystemBase was to get rid of the "hack" we already used. I could switch and change the hack to a different hack to work around a bug, or I can keep things the way they are and know that I won't get any new unknowns due to switching to SystemBase
Yeah, Graphics.<something> will have immediate results. Putting commands into a command buffer will make the commands run at a later point when the command buffer is executing. You can run the command buffer immediately by calling Graphics.ExecuteCommandBuffer of course, and can reuse the same built command buffer over multiple frames
Why might I want to defer execution over just running it immediately?
can you elaborate?
asking about .Schedule() vs .Run()?
It's rarely "I want to do this later" and more usually "I want to use other threads/workers/cores" - as soon as you do that, you have to schedule the job (ie not run it immediately on the main thread) - and in the context of Unity, the order and scheduling is related to the safety system and what components you're reading/writing. apologies, looks like I was missing context
Isn't he talking about the graphics command buffer?
@amber flicker srry for ping, but I have a quetion.
I have 6 x 3 panels in a grid.
this grid is in a subscene.
now, I want to store these panel entities onto an NHM.
but, when I try to do it in a custom Authoring -> Play -> NHM is empty. (maybe because it's in a subscene that's why it won't store? I dunno why)
so the only jank solution i made is to make a System that checks / adds all the Panel entities onto the NHM.
And enable the critical Systems that needs to do the actual work once I validated it's all in there.
Whats the alternative?
oh.. haha.. I suppose I should scroll up huh ๐
I would probably store this data in a blob on conversion. It's not actually that tricky and works well with conversion workflows. Otherwise, a runtime system that populates a NHM is fine.
Though if, like me, you later need that NHM accessible via a SB (SystemBase) as well an ISB, that will be painful.. so blob I think? Not sure if you can store a NHM directly in a blob though - not tried. Anyone else know?
hrmmm will ISB replace SB?
in the long term, it'll be preferable.. but not anytime soon in general
As I understand it if you use "DrawNow" functions then Unity can't integrate it with lighting and shadows correctly
helps squeeze out performance where you need to - it makes a system fully bursted
What is isb?
yea, like Peaj says. ISystemBase - it's like SystemBase but a struct, burstable and a tonne of limitations right now. For example you can't use ECBs in them.
Very early days
interesting. how do you keep track of the changes? just reading the source?
the release notes but also follow the forum quite closely and there were a couple of posts about it
What's the best practice to develop with DOTS atm: creating entities at runtime or use "Convert To Entity" components? Isn't the last one a temporary thing?
Conversion workflow is the recommended way atm. Probably best using subscenes
Why is creating entities at runtime not recommended? It makes more sense in my head to create the archetype and manually creating the entity rather than converting... Is there a reason for this?
you can still create entities at runtime, but for certain things like with rendering or physics, there's a lot you may need to set up manually which can be confusing I imagine
@warped fog you can absolutely do that. Its pretty tough for more complicated objects because the consist of a lot of components (a lot more than monobehaviours) and you loose support of nearly all editor tools
Aaaaaah.
Happily, I'm on right way with subscenes. Speaking about conversions, you can convert from "generator component" (it takes object count and their common properties as input) or can just manipulate bunches of GameObjects in editor when at runtime they will be converted with built-in converter (1 object to 1 entity). What's better?
Even just parenting entities in code is quite cumbersome
Thanks @pulsar jay that explains it. Good to know.
Hard to say. I guess both would work but in both cases the GameObjects you create should preferably be prefabs
I suppose ECS would only convert it once and "reuse" it then
you mean instead of separate scene nodes?
no I just meant if you are scattering tree prefabs for example the tree should be a prefab
but either way creating the gameobjects at edit time and putting them in a subscene should be fastest because subscenes store them in entity format which can just be copied to memory
it makes sense, thanks
I wrote some code assuming that GameObjectConversionSystem.GetEntities would return the children of the primary entity. Apparently I was totally wrong and I still can't figure out what GetEntities actually is
but my question is now: how am I supposed to get the children of a gameobject I am converting to entities? Shall I just traverse the hiearchy?
Yea i had that issue
theres something like, GetPrimaryEntity
and then off that you can get the LinkedEntityGroup
not sure if theres a better way but it worked
hmm using the EntityManager somehow I presume
physicsWorldEntityManager.GetBuffer<LinkedEntityGroup>(primaryEntity); ?
thanks
if you find a better way let me know ๐
I read an article about GetEntities, I didn't understand it...it seems that a lot of options are thrown there just to solve very specific cases, but add confusions when the specific cases are unknown. Thoughts?
i think GetEntities is cause a gameobject can have more then 1 entity
using something like CreateAdditionalEntity
yes that's what I read from the article, didn't understand the use case at all
ummm
so for me
im building a networking system
each networked entity has a 'shadow' entity
the idea being is your gamplay entity needs pretty much 0 changes in order to be networked
all my network data for that entity is on the shadow, then synced over to the client shadow as well
So i can use CreateAdditionalENtity during conversion so i dont have to make those entities at runtime
saves me a very small amount of cpu for startup ๐
probably not worth
two entities in the same world?
in the same world
and both have two entities per gameobject
so your Gameplay entity => server shadow ===MAGIC===> client shadow ==> client gameplayEntity
yup
cant read a buffer from command buffers
command buffers is write only
you can add a buffer
and setup its values
and if you need random read to a buffer
oh wait
theres something like BufferFromEntity or something
there is GetBuffer<T>(Entity