#Aspect Alternative

1 messages · Page 1 of 1 (latest)

tardy cargo
#

Quick question , is there any alternatives to aspect recommended by the community ?
Like an aspect like this one :

public readonly partial struct ComplexAspect : IAspect {
public readonly RefRO<ComponentA> ComponentA;
public readonly RefRW<ComponentB> ComponentB;
public readonly RefRW<ComponentC> ComponentC;
public readonly RefRW<ComponentD> ComponentD;
public readonly RefRW<ComponentE> ComponentE;
public readonly RefRW<ComponentF> ComponentF;
public readonly RefRW<ComponentG> ComponentG;
public readonly Entity Self;
}
foreach (ComplexAspect aspect in SystemAPI.Query<ComplexAspect >()){
// do something with ComplexAspect
}

I could use :

public static EntityQueryBuilder AspectQuery =>
new EntityQueryBuilder()
.WithAll<ComponentA, ComponentB, ComponentC, ComponentD>()
.WithAll<ComponentE, ComponentF, ComponentG>();

But can't use that directly with an idiomatic foreach

I could use a ToEntityArray() but I would have to query the components manually everytime with the entitymanager.

Is there any Solution on that side ?

lucid crater
tardy cargo
#

Cause :

  • You are limited to 7 components max in your queries, If I added for whatever reasons a H component that would not work.
  • Lack of maintenability maybe ? if you have 50 system using the same query and need to change some component you now have to do the modification in 50 systems.

Concern :

  • Is there any performance drawback with the fact that let's say 50 systems use the same queries but basically copy pasted everywhere ?
lucid crater
tardy cargo
#

Even if my example you could, i agree, the scalability & maintenance could be very annoying from a user of the api standpoint

tardy cargo
lucid crater
#

we have over 400 systems in our project and we never have a single system with exact same set of components

tardy cargo
#

How big are some of these systems ?
Could they be broken into multiples smaller one ? -> for the sake of testability and responsability of each individual system
But anyway , again , my example was extreme & not really relevant to the base question ^^#.

So to answer my question : Just use SystemApi.Query. That's fair, I wanted to see if there were other alternatives 🙂

lucid crater
#

you are meant to use jobs

tardy cargo
#

An idiomatic foreach is automatically compiled into a Ijobchunk in the background , right ?

lucid crater
#

it's main thread iteration

tardy cargo
#

i'm mixing with Ijobentity , my bad

#

Funny enought btw I do remember that during unity last stream about dots they went throught all methods to iterate over entities and they were advising to use idiomatic foreach for most stuff and use jobs only when you really need multithreading.

#

what you are telling now is a bit against that, i'm curious about the why behind your reasoning 🙂

#

"when yo use idiomatic foreach ? For most of the things" basically

lucid crater
#

some other ECS frameworks provide much more simplicity for single threaded application

#

as they fully take advantage of it

#

while unity ecs is fully focused on multithreading

tardy cargo
#

LoL again, again , you generalise something ....

In our project we NEED multithreading , just maybe not for ALL the queries

#

So we definitely NEED the job system , the burst compiler etc ...

#

It's more for the situation where we don't need it that's i'm looking for solution here

lucid crater
#

anything on main thread = sync point

#

if you don't accurately create your architecture - you end up nullifying all job impact

#

because main thread would wait for them to finish all the time

#

before the queue up enough

ruby latch
#

there is no alternative to aspects right now, other than writing things by hand and rearchitecting your stuff

(they will remain until 2.0 so you don't have to avoid them yet depending on the scope/length of your project)

you're not the only one with the idiomatic foreach/jobentity query "problem" at least

#

they were advising to use idiomatic foreach for most stuff and use jobs only when you really need multithreading.

I agree with this advice for most people, because its easier to get started with, is more permissive/flexible in terms of code composition, and for many projects already sufficiently fast. If you dont have tight performance constraints for your code then ife will probably get you to your goal faster especially as an ecs beginner

timber frost
# tardy cargo https://youtu.be/3pLun0GKSAs?t=4032 around this moment they are talking about it

sorry, i have a hardliner opinion about this and this advice of "use idiomatic foreach for most stuff" is plain out wrong. i get that it's easier, at first glance, but actually it's not. once you decide to start scheduling a job, say goodbye to your codebase, you'll have safety problems and hard syncs left and right. the whole idea of entities, jobs and burst is gone. i'm actually perplexed that dani talks about this without any nuance. if you use only idiomatic foreach, writer a manager that calls your monobehavious updates and wait for CoreCLR to hit, it'll save you the headache of entities and once CoreCLR hits, free performance on nearly burst level.

#

what i think is the right answer here, use schedule as base, scale up with scheduleParallel and only use idiomatic foreach if you're FORCED to do so (UI, Monobehaviour access, web requests, etc...)

tardy cargo
#

so I'm not counting on that for any of my projects

tardy cargo
#

Am I missing something ?

tardy cargo
timber frost
# tardy cargo Am I missing something ?

system A schedules job that writes to compA, system B is idiomatic foreach and reads B - best case and i'm not clear if the automatic state complete resolves this for you, you don't have to write anything but have a hard sync point. worst case, you have to add a state.Dependency.Complete(); before your RO access. profiler timeline now looks worse as before as main thread has to wait for the scheduled job in system A to complete. this is a cascading problem and gets worse and worse because the whole architecture was built on main thread. i'm not having this opinion out of spite. i've been there in my first projects of ECS and it was the worst things i've done. i've started from scratch again because it's not a mess you can just solve. it's true, you don't have to think about anything on main thread but it's not when scheduling, you have to think about order, read/write access dependencies, when ECB should run and how to get back to mainthread without causing a mess (hard sync point) in the process. when you schedule from the start you won't have any problems or just some very local ones.

timber frost
timber frost
# tardy cargo Yeah I don't get why they don't make it so you can iterate over an entity query ...

it's actually very straight forward to do so, just not as convenient. EntityQuery has a method ToEntityArray which you can iterate over. using SystemAPI.GetComponent<T>(entity) codegens enough performant code to not be required to use SystemAPI.Query - actually, i don't know if this has changed in the last few versions but idiomatic foreach and EntityManager.Instantiate wasn't working so I had to write in the style I described

sick wigeon
#

EntityQuery has a method ToEntityArray which you can iterate over. using SystemAPI.GetComponent<T>(entity) codegens enough performant code to not be required to use SystemAPI.Query
Doesn't that still have the overhead of looking things up vs already having a chunk to read from

timber frost
#

yes it does, as alternative there's also ToChunkArray but with that code is getting messy.

lucid crater
#

And incremental change won't give any results, until you almost fully eliminated all sync points

#

On top of it, if your codebase didn't consider multithreading it's likely you will have things that aren't as straightforward such as structural changes

#

So most likely any mid size codebase is going to be a nightmare to convert

acoustic dragon
#

fwiw, if i were prototyping with dots, i would use ife/main thread stuff for everything to start with, and jobify if and only if i had a performance problem. yeah ok i'd have sync points, but most prototypes are not that slow anyway, and even if it is too slow, i can probably get away with jobifying just one or two things here and there. also, most prototypes aren't fun, so why worry my pretty little head about jobifying everything when i'm probably throwing it away anyway.

if it turned out to be fun and i was on a sufficiently big team that we had to agree on performance budgets and whatnot in advance, i suppose i'd rejigger things to jobify then, to the extent that the performance budgets seemed like it probably merited it, which might well be totally fine still doing like half the things on the main thread.

yes, there's more total rejiggering this way, but also you only incur the rejiggering cost when you're really sure it's necessary, and only as much of it as is necessary.

ruby latch
#

that being said, of course I agree that in an ideal world you jobify everything you can

wheat salmon
#

I personally think that IJE is no extra effort (actually I find it less painful to write for anything more than like 3 lines of code) than SystemAPI.Query so I see no reason to do things on the main thread

#

Now I'm not saying you should go out of your way to figure out how to parallelize everything, a simple schedule is enough for a prototype

tardy cargo
timber frost
tardy cargo
#

Maybe not cause you are scheduling it and it use the dependency of the system maybe....

timber frost
#

there's no sync point, only a job dependency. the job system figures it out when the job is able to run

tardy cargo
acoustic dragon
ruby latch
lucid crater
ruby latch
#

last week it literally told me they weren't allowed when accessing a container from a component lookup; I guess perhaps I needed to add an attribute, but that kind of proves my point anyway

that being said I am jobifying everything now as well, just playing the devil's advocate really

lucid crater
#

so in order for you to fully understand that safety is all yours you are required to add an attribute that would disable safety tracking for this field

#

but it works just fine