#archived-dots
1 messages · Page 240 of 1
However inside one of my systems, in OnCreate, when i try to get the singleton i get this:
Actually it's not OnCreate, it's being called from a mono, hmm
yeah, so not sure
Curious also that as you can see for example FirstPersonCamera, which is a GameObject existing in the GameScene, isn't shown as a child of GameScene in Entities view
cause it's probably not being converted to an entity
since the main camera can not be an entity anyways currently
it's a hybrid it has ConvertAndInject and you can see above it exists in the original scene hierarchy, but also in the Entities view
you're using convert and inject in a subscene?
something's telling me this is an issue with the order in which systems are created
subscene does ignore any convert to entity components
no that was just referring to the FirstPersonCamera which exists in the main scene
oh
no object in a subscene needs a convert to gameobject component and if there are any on any object it just get's discarded
yeh ignore that it was a separate observation
if you're grabbing an entity from OnCreate, subscenes aren't loaded yet 🤔
Try OnStartRunning, not OnCreate
Hmm sadly not working either
btw can someone convey the usefulness of multiple worlds to me?
are you sure the entity exists and has the component on it?
yeah
but that's a tag. not a component
Multiple worlds can allow you to un-chain an entity processing cycle from the primary graphics FPS. I use a loading world during startup to generate my 2.5M entities on a job thread in a separate world while the FPS is completely unaffected.
it's still a component though right.. i don't recall having an issue with GetSingleton and tags before 🤔
Actually doing logic beyond basic loading is fairly tricky on a separate world and Im still trying to figure it out. Lots of bugs and Im getting the impression that multiple worlds is not really supported on 0.17
i am not sure. but like....why'd you need a singleton tag anyway? what's the point
only other thing it has is a buffer
hm, interesting. i mean yeah....i kinda understand it? but if your primary world doesn't render anything, does it change / benefit anything?
i've tried using GetSingleton<myBuffer> also but then tried with the tag same problem
The plan is that you put up some sort of pre-rendered loading screen while a very very long job on a separate world creates all the entities and assigns their data. Then transfer over the entities from that loading world onto the primary world. Then you remove the loading screen and boom, your game is ready.
That at least works, mostly. SharedComponentData and ChunkComponents are not supported in transferring between worlds. You need to re-assign them in the primary world using EntityQuery EntityManager commands, which is fairly simple and quick.
interesting. i've only ever seen a different world being used to do some physics calculations and then display a trajectory based on those in the main world. but that was ages ago and to me it just felt strange
imo you should add a HasSingletonComponent<T> check, not sure what the order/timing of conversion is but maybe its just not getting converted right away?
well i would try moving it outside the subscene and then test if it even gets it when it's 'globally' available
or requiresingleton for update
yeah i'm thinking it's an ordering problem ie it just doesn't exist yet..
basically i've had the problem where my dots character animation clips are not running when i build the project, apparently they don't unless they're included in a subscene
they run fine in the editor..
so i'm having to restructure my character prefabs into a subscene to get the build working
it's probably for the better that i learn subscenes and also restructure some of my code to have clearer separation between monos and systems
animation only converts in editor, so for a build you have to use a subscene to preconvert them(elaborating on my previous comment)
yep, thanks for that as i had no idea of that caveat
id assume they will change it in the future because that seems a bit half baked but then again not really sure what the future of conversion is supposed to look like
how'd you figure that one out?
it mentions it somewhere in the anim samples, also theres a comment somewhere in the conversion code that is if def'd for the editor I think. I wanna say it was curves? maybe if you are particularly brainy you could even wewrite it to run at runtime 🙂
heh yeah maybe later, i'll try figure this out first..
although i think i did have to dump animation package into assets to make something public at one point
ah thanks
not sure if there's any way to debug the subscene loading, for example do a console print when a subscene loads
might help debug ordering
bit of a black box atm
So I'm just starting out learning and using ECS and I've run into something quite annoying: namely that the ConvertGameObjectToEntitySystem doesn't run ahead of everything else by default, which is annoying when I'm trying to use it for configuration :/
What's the best way to make sure that my system's onCreate runs after ConvertGameObjectToEntitySystem has done its thing so I can use a singleton from the editor for config?
what are you trying to do? do conversion stuff after the bulk of gameobject entity conversion has taken place but before runtime systems start? or something during runtime only?
I'm trying to use the mesh, material and couple of other things I can define in the editor with a dummy gameobject, by grabbing it from the entity that is created, to config the initialization of other stuff
I mean ideally I'd not mess with Conversion at all but apparently this is the best way to do this according to this thread https://forum.unity.com/threads/best-practice-for-passing-config-data-to-an-ecs-system.649864/
except that well yeah
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
dstManager.AddComponentData(entity, Config);
Debug.Log("added component");
}
we sorta just went over this, not really sure on the specifics of conversion timing but options could be to do
if(HasSingleton<T>)
//stuff
else
return;
or theres also RequireSingletonForUpdate<T>();
Yeah I noticed that that exists, but I'm hoping I can avoid merging the intialization of the system with the normal update loop?
RequireSingletonForUpdate can go in OnCreate
also shouldnt be a problem to query within the update loop for certain things I assume if you arent going crazy, thats literally what its there for
I'm not sure how this really solves my problem because from what I understand that still would require me to put the initilization logic somewhere in my update or am I missing something?
Also that's fair but it just feels wrong to make the same check for if a singleton exists for the entirety of my game's existence when I just need to run after something once 😅
you pasted the getsingleton error so I assumed you were trying to do this during runtime, the alternative is doing something in conversion, and outside of that Im not sure what you want?
actually singleton stuff shouldnt be connected to conversion, im not thinking straight 🙂 but im still not sure what the issue is tbh
Sorry, let me clarify again.
I have a system whose onCreate sets up a bunch of stuff, and then runs my my current test logic.
I wanna be able to tweak the config outside of code for ease of use and being able to drop meshes/materials/etc in easily.
The solution I wanted to use would have been do define my own authoring component which would allow me to do this in the editor (which creates an entity from the gameobject with create and destroy)
And then have the system try to grab that Entity during onCreate, except as we can see, it doesn't exist yet
I read into it some more and apparently there's some other approach with an addressables key? so I'm going to look that
ah, you shouldnt be changing entity data in oncreate afaik
I mean technically I'm only trying to read it, but why/where can I read up more on that?
well its just for system initialization, id wager that across all examples and their own packages, you wont see unity doing any entity component data reading/writing in a systems OnCreate
assumably you could dig into the code and see if entities exist prior to a world running system's oncreate
That's fair, but does that mean I just have no solution for easy configuration?
what are you doing in OnCreate?
But yeah basically just wanted a way to get that info in the same way you could normally do with a monobehavior
lets assume this slice worked on OnCreate, are you wanting to change this again sometime during gameplay? oncreate wont run again
ok then use conversion 🙂
I...
I'm confused
Gameobject -> Entity conversion apparently runs after onCreate
So I can't?
conversion in subscenes runs prior to gameplay, conversion outside of subscenes should i think run before, and conversion can happen later during runtime ie if you have a gameobject(and dont tick ConvertToEntity checkbox before the game starts, and tick that during the game it will convert while the game runs(in its current state and runtime conversion may disappear in the future, unity havent been clear).
entities shouldnt be accessed in oncreate
access the entity and its data during OnUpdate
Alright, thank you
Seems someone else is having ordering problems!
@safe lintel i've noticed if you have role 3dArtist you don't have a little icon next to your name.. should put in a formal complaint to server admin regards this horrendous injustice
as a long time 3d artist ( and coder as it happens ) i find this an insult of the highest order
i guess im a generalist these days, but I cling on to my roots 🥲
What can i potentially do wrong?
this code causes error (screenshot). When i comment this code then no error happening
var count = _argsBuffer.BeginWrite<int>(1, 1);
count[0] = group.y;
_argsBuffer.EndWrite<int>(1);
_argsBuffer initialized through this code
// Argument buffer used by DrawMeshInstancedIndirect.
var args = new uint[5] { 0, 0, 0, 0, 0 };
// Arguments for drawing mesh.
// 0 == number of triangle indices, 1 == population, others are only relevant if drawing submeshes.
args[0] = (uint)_quad.GetIndexCount(0);
args[1] = (uint)INSTANCE_COUNT;
args[2] = (uint)_quad.GetIndexStart(0);
args[3] = (uint)_quad.GetBaseVertex(0);
_argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments, ComputeBufferMode.SubUpdates);
_argsBuffer.SetData(args);
is that even dots related
sorry, i saw compute buffers was mentioned few times in this channel + i use here native array to write data + also IMHO here in dots channel sitting the most experienced devs. Yes, this probably more related to shaders channel or to advanced code channel
anyway i've got no idea why why that throws an error. looks functional to me. did you try it in a blank project?
yep, this is blank project
maybe it's in some other area of your code?
mmm, i don't think so, because comment this one completely stops throwing error
but i mean, if you don't push that buffer to your shader because of commenting out, well.......then there's no data to be worked on which might stop the error.
no, i pushing this buffer to shader, and this buffer has initial values passed with array in initialization code, i only comment out code which edit 2nd value of buffer
maybe the stride is too small because you pass in an array, not 5 uints? idk
i think i get it, initial values is uint, and code which edit values tryes to write int
i mean that shouldn't really change anything?
i'll check
no, the issues is in using SetData() lol, when i use BeginWrite/EndWrite instead of SetData, all goes well
very strange though.
no the other way around
but you said the code crashes it, the code you showed uses Begin/EndWrite
new code is:
_argsBuffer = new ComputeBuffer(1, 5 * sizeof(uint), ComputeBufferType.IndirectArguments, ComputeBufferMode.SubUpdates);
var args = _argsBuffer.BeginWrite<uint>(0, 4);
args[0] = (uint)_quad.GetIndexCount(0);
args[1] = (uint)INSTANCE_COUNT;
args[2] = (uint)_quad.GetIndexStart(0);
args[3] = (uint)_quad.GetBaseVertex(0);
_argsBuffer.EndWrite<uint>(4);
no SetData now
ah ok sorry
so the first arg is the offset i'm assuming 1 is accurate, you're skipping 0?
no the 1 is how many elements are in the buffer
1 aka 1 array aka 1 * 5 uint
ah i was looking at the first code he posted:
var count = _argsBuffer.BeginWrite<int>(1, 1);
count[0] = group.y;
_argsBuffer.EndWrite<int>(1);
oh my bad
So apparently the Jobs system isn't recommended for multiframe tasks, what is the recommended way of working on a longer task? Why shouldn't I use a job?
normal async await.
jobs can only be ~ 1 frame long
That's unfortunate since it doesn't let me multithread background tasks (not easily anyway afaik?)
i as well as others hope that there will be a possibility for long running tasks eventually though
wdym exactly?
Only beginning to work on this but the standard stuff eg reading a bunch of files or procedurally generating a bunch of terrain
Is stuff I'd wanna have done fast
i think Wad1m is running long jobs, there's a bit of a chat about it here:
#archived-dots message
But I could probs get away with not focusing literally every single resource on
He def mentioned his mesh builder is taking 1-200ms
mesh building definitely can be easily done in 1 frame if you chunk up your terrain, which you'd probably want to do anyway
is this running in a system or a mono update?
wow ty that looks really promising
in a system
he did post a link to his code in github
I'm just giving theoretical examples that I could see taking a while depending on how much I wanna do, like I said still early on and mostly trying to set up robust systems which I can expand in the future so wanna know what the possibilities are
it's ded xD
have it any difference to write it in mono or in system? It is all called on main thread
yeah just wondered if there's nothing else obvious, because it's writing to gpu maybe test in a mono also
I could definitely find it but not trying to build anything rn, just wanted to know what the possibilities are
burst literally is magical. do not underestimate what you can do in 1 frame. especially if you only need it every now and then and not every frame
Oh I thought you meant on the forum thread ty
filesystem stuff :/
why crossed swords?
well that is not meant for jobs / burst anyway
Burst I can understand, but jobs why?
(I mean obvs for burst)
cause IO is unreliable and you don't do IO every frame. jobs is totally irrelevant for that. if you'd make a long running job that does IO it would pretty much be a worse writeasync which already exists
keep in mind if your frame rate isn't high like 120fps + it would cause visual lag ( if your job is running more then 3 / 4 frames )
+1
ty
ah so does it stall the main thread in some way, how do you mean?
yes , a simple test like adding a spinning cube will confirm this , u can see the visual tearing even tho the frame rate might be 60
Why is it worse if I want to read a bunch of XMLs for example and convert them into entities?
(not actually sure that this is the best solution to my problem but am curious)
you would definitely want to do this before the game starts
loading screen etc
so it's not then possible to have a job run for several frames and harvest the results later
i am quite certain that's the case
Why wouldn't I do it in the main menu, allowing for settings changes or save game selection etc while everything is still loading?
what do you mean? jobs can run as long as they want as long as a) they don't use entity data b) don't use tempjob memory
of course you can do it there. but then you definitely don't need jobs
do u have a laptop by any chance ? This is a frequent error i see since win10 attempts to use both GPU's ( integrated & build in )
Could you elaborate on this?
if you're on the main menu, for what would you need jobs
that was what i had assumed based on the link to what Joachim was hinting at
To load something as quickly as possible? Why wouldn't I want to use jobs?
best i can think of is to run a benchmark job on the device and then based on the machine speed separate one big job into chunks and each frame give it a start index and execute count ...
? jobs don't automatically increase loading speed
maybe if the long job is parallel, and it hogs all available threads, it could block entity system jobs
yes if you run a long job in parallel you will block everything else running
you need to ensure you still have workers available for regular work
ideally you only run long jobs in a single worker
okay thank you, this is what I was missing
Is there currently no way to ensure this with the regular jobs system?
an example of long running jobs + loading data off disk (ignore the flickering, was just because I at the time hadn't stopped chunks from despawning before all children had spawned)
so technically you could schedule ( not parallel ), it'll start the job on a single thread, ensure it operates only on class/system level native data
At that point there's no advantage (aside from using a standardized system) to using Jobs though I guess
nice
how do you get the job to execute though if you don't call .complete()
complete finishes a job, not starts the execution
but a job isn't executed until .complete is called
JobHandle.ScheduleBatchedJobs();
will start all jobs scheduled immediately
so i suppose the question is how do you know when it's completed and/or setup the dependency
so what happens if i call MyJob().Schedule() ?
it gets queued for schedule and won't run until the above line is called
this is handled after a system finishes usually
ah interesting. that was a key element i didn't know. cause i have tried long running jobs and they never ran without complete
/// <para>By default jobs are only put on a local queue when using Job Schedule functions, this actually makes them available to the worker threads to execute them.</para>
/// </summary>
[NativeMethod("ScheduleBatchedScriptingJobs", IsFreeFunction = true, IsThreadSafe = true)]
[MethodImpl(MethodImplOptions.InternalCall)]```
so i thought it was impossible
now btw, this is called in AfterOnUpdate on a system
so you shouldn't have to call it yourself (and I don't for the above example)
well i only tried long running jobs in OnStartRunning()
is there no way to designate specific number of threads to jobs
the system does to see if any new jobs were scheduled
{
AfterUpdateVersioning();
// If outputJob says no relevant jobs were scheduled,
// then no need to batch them up or register them.
// This is a big optimization if we only Run methods on main thread...
var outputJob = m_JobHandle;
if (((JobHandleData*)&outputJob)->jobGroup != null)
{
JobHandle.ScheduleBatchedJobs();```
that i am fairly confident you really cannot. because of the workstealing algorithm and stuff
shame, would be nice for that kind of stuff
yes, i have one, can test it on laptop, but i've solved an issue
wow so much i didn't know yet
and you can manually calculate the indices per thread
i worked with c4d's c++ api quite a bit, and i'm pretty sure from memory it had some nice threading tools with the ability to be specific about launching thread count
but you can automate this a lot less effort if you just write a custom scheduler
As a simpler question, is there a way to setup an entitycommandBuffer to playback automatically after a job is finished, and before later queued jobs?
doesn't it do that automatically?
Uh the examples suggest otherwise but I haven't actually tested
ecb will playback in the ecb system itself afaik
if your other jobs are in others systems you should have no problem
that's the whole point of the EntityCommandBufferSystem
and while I recommend against adding new ones (sync points) you can
So if I just add one without calling playback, and a job is queued after, everything will work fine?
man they really need to update the examples this is stupid lol
if you want to be really specific you would probably chain the dependencies of the jobs, and specifically order the Systems
not sure what you mean? the later job does depend on the other
yes
yeah well, there will be constantly updated examples when 1.0 launches. in about a year
from what I've heard optimistically in about a year xD
well with scheduling the jobs can be actually run in any order unless you specify that one job depends on another
yeah yeah, that's why I've specified
btw @rotund token do you happen to know if theres any way to use dynamic buffers with dataflowgraph?
i don't sorry, i'm not that familiar with dfg. i wasn't that happy with it/performance when i looked at it way back and have my own graph implementation
Also also, if I have a really simple thing I wanna have done after a job is completed and before some other stuff happens, (some cleanup) is it fine to schedule a small job for it or should I be doing something else/not doing that at all?
small job should be fine
Alright, ty you guys have been a massive help and probs saved me anywhere from an hour to many of googling and trial and error
appreciate it
if you can cram the cleanup in after the actual work in the same job, that might get you a bit better performance? although that may depend if it's a parallel job or not
ah ok, thanks anyway
the job is parallel, the work isn't
the cleanup that is
im not sure if it's the same with full jobs, but with the Entities.ForEach you can chain Dispose() between jobs..
dependency = Entities.ForEach((..)=>{}).Schedule(dependency);
dependency = myNativeArray.Dispose(dependency);
dependency = Entities.ForEach((..)=>{}).Schedule(dependency);
i think 😛
dependency = myNativeArray.Dispose(dependency);
i've always found this interesting
why does the next job care about this dependency ^_^
because that's how it knows what order
we just leave all our dispose dangling at work
we don't care when it disposes as long as it does
well i guess it clears temp memory of that array data
I don't really understand how foreach works, some of the documentation I found suggests its singlethreaded? but then the more recent stuff wasn't really clear?
then you move on an do other bits
no it can be multithreaded too
schedule is singlethreaded. scheduleparallel is multithreaded
I see, okay
yeah that's also confusing when I used IJobParallelFor
though schedule doesn't mean all that use schedule will be on the same thread
even componentsystem isn't marked as deprecated
actually thats a good question, ive been meaning to ask unity about that and conversion systems
and if anything is changing
SystemBase or probably System with 0.5 all the way
ISystemBase will definitely be ISystem
i suspect they're not calling it System due to issues with the System library
but i don't have confirmation on that
idk. it's def ISystem though. not ISystemBase anymore
and i actually doubt that they would call the class SystemBase then because that would just be even worse even with considering the system namespace
I think this shows that it's still called SystemBase
https://forum.unity.com/threads/basic-cube-shifting-benchmark-and-it-looks-like-there-is-an-overhead-from-using-dots.1196671/#post-7656256
if class: SystemBase
if struct ISystem
probably lots of people would be upset
currently yes
I'm not sure how to translate easily? I want to iterate a known number of times and create that many entities, with IJobParallel for I can just pass the total number of iterations and the innerloopbatchcount, but with IJobFor I need to pass entities?
ijobfor is the same as ijobparallel for except it has proper separate Schedule and ScheduleParallel methods
ah it just requires an explicit jobhandle
i can't really say much more but i wouldn't expect it to be called System because it breaks everything
which IJobParallellFor didn't
you can just pass in default if you don't n eed it
breaks everything? like what?
only if you use the system namespace
ty
which you likely won't in dots
shrug there's always aliasing
but maybe you're right. but then i would not like to see ISystem as well
then they should just stick with SystemBase / ISystemBase or like better JobSystem / IJobSystem
Any reason I shouldn't use Job.withcode() to create a job? specifically thinking to use this for the cleanup stuff I mentioned earlier but also asking for more complex stuff
no reason it works perfect for what you're suggesting
Awesome ty
since we were on compute buffers recently, i've got a tangential question to that. a computeshader has a .SetBool() method
with the SRP's you are required (encouraged?) to use a commandbuffer though. but i can't find a commandbuffer.SetComputeBoolParam() method or similar. all other param types have a method though. anything i'm missing?
Is there a way for me to force a sync for a new entitycommandbuffer after a job is completed/before a new job starts without doing a .playback in the main thread (regardless of where they are structured relative to the predefined ECBSes)?
i don't think so
Well while we're on the topic of bad news I might as well ask, can I do something like this in Entities.ForEach?
[BurstCompatible]
public struct FillHexGrid : IJobEntityBatchWithIndex
{
public HexGrid Parent;
[ReadOnly]
public EntityTypeHandle TypeHandle;
[ReadOnly]
public ComponentTypeHandle<Hex> HexHandle;
public void Execute(ArchetypeChunk chunk, int batch, int index)
{
var entities = chunk.GetNativeArray(TypeHandle);
var hexes = chunk.GetNativeArray(HexHandle);
for (int i = index; i < chunk.Count; i++)
{
Parent.Hexes[Parent.getIdxFor(hexes[index].q, hexes[index].r)] = entities[index];
}
}
}
specifically having the parent field, (I'm effectively trying to modify a nativecontainer).
When I try this
Entities.WithBurst().WithAll<Hex>().ForEach((ref Entity e, ref Hex hex) =>
{
test.Hexes[test.getIdxFor(hex.q, hex.r)] = e;
}).ScheduleParallel(handle);
I get
InvalidOperationException: The previously scheduled job TacticalSystem:OnCreate_LambdaJob0 reads from the Unity.Entities.EntityTypeHandle OnCreate_LambdaJob0.JobData._lambdaParameterValueProviders.forParameter_e._typeHandle. You must call JobHandle.Complete() on the job TacticalSystem:OnCreate_LambdaJob0, before you can deallocate the Unity.Entities.EntityTypeHandle safely.
first, you do not need WithBurst() foreach is burstcompiled by default. second, you do not need to pass the handle into scheduleparallel
ty for #1, as for #2 why do I not need to pass the handle?
oh wait, right, um, maybe you do need the handle
Also either way that isn't solving the issue
From what I understand it doesn't like that I'm trying to access/modify the nativearray but I'm not sure how I'm supposed to do that then?
hm, well i have to think about it a bit. btw, you should not pass Entity by ref or in
ah right ty
for the error itself unfortunately i'm not a big help. i haven't worked a lot with typehandles
The typehandle stuff doesn't seem to be relevant, I just need to know if/how I can reference a nativeArray in a foreach
you can just access a native array in a foreach
it must be a method local native array though
There's no way to avoid this I assume? seems rly arbitrary considering IJobEntityBatch lets me do so
Also even then I still get the same error
the error has something to do with the entity type handle though
Oh
I'm an idiot
lol
had to do handle = foreach and then complete
w/e
ugh -_-
👌
Well I'm having a great time, I'm trying to set up a grid of entities in an ECS manner, but it seems to be impossible.
Trying to set up a Singleton Entity which would hold references to what is effectively a 2d array of Entities(yes I know it's not really the ECS way to do this, but the alternative is not only a larger execution speed cost from having to iterate over all entities every time I wanna find some entities within a certain range, but also some memory overhead as all the Entites have to know their coordinates)
I can't use NativeArray because it's not blittable, but I also can't use a Dynamic Buffer because not only do they not allow for parallel writing, but I also can't do something as simple as
public DynamicBuffer<HexEntities> HexEntities;
[ReadOnly] public HexGrid HexGrid;
[ReadOnly]
public EntityTypeHandle TypeHandle;
[ReadOnly]
public EntityCommandBuffer.ParallelWriter Ecb;
private static readonly float Sqrt3 = Mathf.Sqrt(3);
public void Execute(ArchetypeChunk chunk, int batch, int index)
{
var entities = chunk.GetNativeArray(TypeHandle);
for (int i = 0; i < chunk.Count; i++)
{
var coords = HexGrid.getHexCoordsFor(index);
HexEntities.Add(new HexEntities{Value = entities[i]});
Ecb.AddComponent(index, entities[i], new LocalToParent{Value = ComputeHexPosition(coords)});
Ecb.SetComponent(index, entities[i], coords);
}
}
because I'm restructuring the DynamicBuffer every time.
Is there a reasonable way to do this with relatively pure ECS or should I really just use a NativeArray and use some system fields rather than a singleton?
impossible
obscenely difficult*
I can't use NativeArray because it's not blittable
what is stopping you use native array
also dynamic buffer has the exact same parallel limitations of nativearray
i guess the question i have is, what are you actually trying to do
any reason why you don't use the ecb to write to the buffer?
well i guess i'm looking at it from the context of ForEach jobs, but you could maybe try using the ecb for the buffer..
if you really want to do this like this, which i wouldn't recommend, you might as well use a fixed buffer. that's probably be the best way for this approach
I can't make it a componentData for my entity
Like I said, basically have a Grid that I can use later on to for example get all hexes within x hexes,
I didn't know that was a thing I could do
Not sure how to since from what I could find I can't declare the size of my buffer at runtime, only at compile time?
And what alternative approach would you recommend?
i thought you had a fixed size grid?
Well the grid is fixed once I intialize it with a certain width/height
theres also fixed list for dynamic size
From what I could gather, the fixed lists aren't anywhere near bug enough, since I'm trying to plan for anywhere from a minimum of a few hundred to a max of a few thousand hexes
i would suggest get it working then optimize from there..
i think using a DynamicBuffer is possible it's how i do some stuff..
but also just having a dedicated system, with a member NativeList might be the simplest approach
but i'm not exactly sure on your setup/requirements
I didn't know I could use a command buffer to queue changes to a dynamic buffer to be honest
yes you can
Also how could I clarify further?
ecb.AppendBuffer i think
maybe just an explanation of what you're doing, i guess maybe already you've explained some of this, but maybe it'd help
also if that's your need, and you want it editor only, not in a built, you can easily just write a small source generator to get this done
I'm trying to create a hex grid system for my game, basically.
The main requirement for this is to use coordinates somehow and be flexible enough to use in at least two situations later on down the line (one where the grid is relatively small, and one where it's much larger) and potentially some variability within each of those examples
From my thinking, I can either store the coordinates for each hex inside of each hex so whenever I wanna get all the hexes within x tiles of another hex I check them all to try to find the ones with matching coordinates,
OR
I have some sort of data structure that holds all the references for me in a structured way so I can calculate the exact hexes I need mathematically and just use those directly.
(This is for example to highlight them)
I mean maybe I'm doing this completely the wrong way and ECS and Burst are so efficient I should really just iterate over the max few thousand hexes and compare their coordinates vs what I need, but that seems fundamentally wrong to me 😅
maybe @robust scaffold can help you here more
Quite similar to a spacial lookup system then like quad trees etc
With the benefit that all your hexes are fixed in position so once you have your data layout of hexes, you're just looking those up right
Exactly
And yeah vaguely from what I understand
Some interesting math involved obviously to convert a lookup of a bunch of hex positions around a specific radius to a lookup of a linear list of hexs
But not that difficult really
Yeah, I'm quite looking forward to setting it up cuz it'll be quite satisfying I'm sure but need to figure out how I'm storing it first 😅
Hexes are cool
i mean the quickest an easiest would literally just be iterate all with burst as you said
but definitely possible to optimize that further
so for example say your hex's are a bunch of entities each with a Hex tag and a Translation component.. just iterate all and check if dist of your focal point and translation.value is less than certain amount, and if so update that hex or add it to a NativeList which you can then process in an additional step
something like a basic quadtree system could optimize this by quite a bit though
and then there's other ideas that go even further
Yeah I have thought about doing it that way as well, by using in-game position rather than hex coordinates, but it still means I need to iterate over them all even though I can calculate exactly which ones I need which again seems wrong
I'm just really worried about linking the amount of time it takes to get these hexes for a certain set of arguments to the size of the grid when I don't have to
yeah that's really where stuff like quad trees etc can come in handy
rather than brute forcing the whole thing you're breaking down into a predictable number of steps no matter the size of the data set
I mean the appendBuffer stuff you suggested should work exactly like I need, tbh. I'm just uncertain how performant adding stuff to a buffer is at this point
When I'm potentially adding a few thousand entities
Yeah that does actually seem quite interesting as well
and disadvantage is your results are delayed until after the ecb has played out
i would definitely suggest, look up basic quadtrees and get an understanding, and then re-think how you're doing it in the context of ecs
In this case that's fine though right because this is still an initialization job really
ah i was thinking in the case of, say you wanted to highlight the hex's around the player every frame, or something like that
so you're constantly doing lookups and modifying say the material of the hex grid or whatever
That wouldn't require me to modify the buffer though unless I'm missing something?
Once I've created it I have all the references I need to then be able to do the stuff mathematically and getting a subset of hexes to (for example) highlight a certain way should be very simple
Thanks for discussing this for so long btw, I rly appreciate the help
Ah i see what you mean yeah you're just trying to populate the array
Really it shouldn't be that difficult i think you should be able to initialize a NativeArray or even NativeList in a systems OnCreate if you're able to pass in the count
and then burst through all the hex's and update the specific indexs
let me try and do a quick ForEach example of what you've attempted above with your struct job..
Okay so roughly, something pointing in this direction ( again not exactly sure if it fits your exact use case but this is how i'd roughly approach with just a ForEach ):
protected override void OnCreate()
{
hexQuery = GetEntityQuery(ComponentType.ReadOnly<HexTag>());
var hexCount = hexQuery.CalculateEntityCount();
HexEntities = new NativeArray<Entity>(
hexCount, Allocator.Persistent);
}
protected override void OnUpdate()
{
hexEntities = HexEntities; // local copy
Dependency = Entities
.WithAll<HexTag>()
.WithNativeDisableParallelForRestriction(hexEntities)
.ForEach((Entity e, ref Translation t, in int entityInQueryIndex) =>
{
var coords = GetHexCoordsFor(entityInQueryIndex);
hexEntities[entityInQueryIndex] = e;
ECB.AddComponent(entityInQueryIndex,e,
new LocalToParent {
Value = ComputeHexPosition(coords)
});
t.Value = coords;
}).ScheduleParallel(Dependency);
}
So yeah only thing i'm not sure is if it'll let you init the NativeArray in OnCreate with the result of a query count, worth a shot though and i'm sure there would be a workaround
I'm assuming your HexEntities is essentially just an array of Entities
There's other approaches also, you could simply create a list of hex entities directly from a query, and store it to the array
*just updated to add WithAll<HexTag> and also writing directly to the Translation t instead of using ECB to set that ( if coords is indeed Translation value )
Yeah that looks basically like what I want to do, but then my issue was that I couldn't attach that data to an Entity as IComponentData because NativeArrays aren't blittable. I guess the best way for me to store this info is inside of the system class or something rather than a HexGrid Entity?
Or an entity with a HexGrid component rather
I have to say i'm not exactly sure what you mean, sorry i'm probably just being a bit thick 😛
Nah I'm probably not being clear enough since I don't understand the limitations of what I'm working with.
I'm unable to use a struct containing a NativeArray as a component because they aren't blittable. This means that if I go with this approach, I wouldn't be able to easily pass this HexEntities data structure to other systems by having it exist as a singleton entity with a HexGrid component. (If my HexGrid is the struct containing the NativeArray).
I'd wanna store the HexEntities array for as long as I want since I'm using it to get the other hexes so I have to store it somewhere
Yeah i mean with my approach you'd need to reference the system/nativearray with the data, from other systems that need it, and i'm not sure of the overhead of that or if it breaks the ecs paradigm, i did have a discussion a week ago or so on here about that..
So definitely the alternative approach is just to use a singleton entity with a DynamicBuffer containing the data you need.. which is i take it what you were trying to do originally..
Essentially i think with the code i've written above, just replace HexEntities with the dynamicbuffer..
var hexEntities = GetBuffer<HexEntity>(hexBufferEntity);
Something like that i think
And either add to the buffer inside the ForEach or make sure the buffer is pre-inited to the size you need and fill the indexs directly
Yeah that's fair, I guess this is still very new and there aren't 'perfect' ways to do this like I'd like 😅, again thank you for taking the time to help me out!
Hehe not sure i was any help at all but no problem either way 🙂
I mean I think I'll end up going with the ECB setup since that feels more 'right' to me and hopefully I'll be able to update it with something better in the future, and that was your suggestion.
So just wanted to thank you and say that the good news is that it all works and is great so ty all, the bad news is I now realize that when using localToParent apparently the parent also gets a buffer of its children which has equivalent data to my Hexentities buffer LOL so now i'm gonna see if I can hopefully just use that the same way to avoid duplication
You keep saying is not blittable but what makes it that? You can't put non blittable data in a dynamic buffer either but you seem fine using that.
From what I can see you're making a hex grid out of entities correct?
I can't put non-blittable types in a IComponentData
yes
But from what I gather buffers are specifically meant to allow something like this
Ok so it's just you want to attach it to any entity got it.
So my actual question is, why are your individual cells entities in the first place?
This seems to be a common early mistake people fall for; making everything into entities
yeah that's fair, I have thought about doing it in different way but for now this lets me do stuff like apply effects special effects to a hex, store the actor standing on a Hex and easily adjust meshes based on the height component of a hex which would be more difficult if I handled it all in a HexGrid
eg to get all the actors within x tiles of a hex i'd have to either have an array (or equivalent) with a bunch of empty fields that actors would could walk around in, or iterate through all actors' coordinate data
I mean idk maybe I misunderstand but from what I understand of ECS idrk what else I'm supposed to make stuff into 😅
Without knowing your exact requirements, in general the best approach imo for handling a world grid is just building a 'standalone simulation' and just attaching it to a singleton
And if I wanna allow variable sized grids?
just create a super massive one and shrink it based on requirements?
Nothing stopping you, I have an infinite world
If you don't want to deal with the complexities of storing this in a singleton (unsafe code) , you can do what we did at work and just have a single system hold and manage the dependencies for the grid access
Personally I find this gross but it's a very very common approach
Honestly the part I'm most worried about is dealing with the graphics aspect of variable heights for my mesh because I don't have much experience with Unity and almost none with the graphical aspect of 3D games so wanna make that part of this project as straightforward as possible
I also am uncertain how this is different from what I'd been intending to do?
I was planning to have the gamelogic aspects all in one system (or something like that), I do however need some way to store the additional data I mentioned
Or say if I wanted to highlight all the hexes within x tiles of a central one, how would you approach that?
On a fixed grid that's purely maths
I mean that's true
On a hex grid slightly harder but still the idea is the same
Are you using physics or something for this?
Yeah that's what I thought
So I don't see why making it entities helps you for this
Being able to adjust heights easily is #1
#2 is like I said all of this stuff, how would you get all the actors within x tiles of a hex? would you iterate over them all and store their coords?
Id just use a spatial query on a point
Yeah
Whether it's physics or my own collection
I'm personally not a fan of that approach idk
Would be cool if the system was easily drag and droppable in 2d as well
also something like pathfinding could be annoying without hexes I think?
again, how does making the hexes into entities help any of this
instead of just using collection of structs or something
Oh no I absolutely think I could do that, but isn't that against the ECS spirit?
not at all
It also doesn't really offer the advantage of easy rendering but that's minor
unity writes most of their solutions as standalone simulations
i.e look at physics
they convert all the entity data into rigidtransforms etc
and only use that in the physics simultion
they don't use entity data at all, it's a completely standalone simulation
you generally wouldn't want to render each cell individually would you? it'd be shocking for performance
I was gonna see how bad it would be tbh I don't really know, it would've been easy to change that down the line though
hm
anyway i should at least say, if it works for you go for it. maybe your game is quite simple and it doesn't need an elaborate optimized design.
i currently spend most of my time at the moment trying to make stuff run on old consoles so performance is at the forefront for me and I am hyper focused on this.
however i will leave you with a warning though and that is in the past 4 years I have seen a lot of users fail trying to implement entities are grid. these are mostly really large grids/games so scale matters.
I mean I want to allow the possibility of creating a large scale grid, I'm just uncertain which part of this wouldn't work with that :/ Is it just trying to draw them all or is it something inherent to using Entities rather than a structured array of data? are you saying I should just be doing that?
There's a lot of pitfalls, however if you say stick to only using 1 system to do all your game logic and are just using entities to store your data you avoid a lot of this
but again, if you are just using entities to store your data the question comes back around to, why store it on entities instead of a separate struct if you not are iterating/working on them? just slowing down everything for no reason.
Just to chime in - i think your grid will be a bunch of hex objects being rendered tho right, either way..
I mean you could obviously cheat and have a single texture which draws the hex's all onto a plane, if that suits..
but if you're hex grid is physical hex's ie 3d objects then i'm guessing you're instantiating those in your world.. in which case i'd understand the requirement to map Entity id's to the logical spacial data
protected override void OnStartRunning()
{
_altWorld = World.All.Where(world => world.Name == "Alternative World").First();
var pullState = _altWorld.CreateSystem<PullSystemState>();
_altSystemState = pullState.StatePtr;
_altWorld.DestroySystem(pullState);
var simulationGroup = _altWorld.CreateSystem<SimulationSystemGroup>();
var testSystem = _altWorld.CreateSystem<TestSystem>();
simulationGroup.AddSystemToUpdateList(testSystem);
}
protected override void OnUpdate()
{
if (!_altSystemState->Dependency.IsCompleted)
return;
_altWorld.Update();
}```
I'm gonna try to see if I can create an independent-from-FPS updating world by manually calling update and checking the World's dependency chain. I think this works... hopefully without blowing up spectacularly.
The root of .IsCompleted is an internal C++ call that is marked threadsafe readonly so theoretically this should work
Fuck, doesnt work
still stalls main thread until dependency is completed...
Oof. I dont think unity likes what I'm trying to do
nope, not at all
alright, unity really doesnt like that. Crashed my whole computer when I ran it again. Full blue screen of death
Hrm, job completion upon end of frame seems to be baked into IJobEntityBatch inherently. I've tried all sorts of ways to get IJobEntityBatch to last longer than 1 frame but it just wont
Exact same issue with IJobChunk. I'm thinking its something to do with the query mechanism.
TODO tomorrow, attempt to port IJobChunk to IJobFor. I know that IJob and IJobFor / IJobParallelFor are frame independent. There could be a way to instead use the framework of an IJobFor to iterate through chunks independent of frame...
not exactly the same but our server world is broken into 3 frames
initialization + simulation2 first frame
simulation second frame
networking third frame
and we have jobs that run into the next frame without issue
do you have any other work in your other worlds? because if you ever hit a situation where all your worker threads are full it will stall until it's made space
i seen this popup so many times , considering to use this as my lock screen wallpaper
Anybody know what works and doesn't work within the ecs/dots ecosystem on Unity 2021?
Currently using 2020 but there are a couple of things i'd like to take advantage of in 2021 ( addition of a buffer input to vfx graph - currently using a workaround which writes data to a texture which is then fed into the graph )..
Since the official stance is that it's not supported I don't think it's worth getting in to. Worst case scenario you just end up having extremely hard to debug behaviour. 2021 support is probably not coming until late Q1/Q2 of 2022 according to their latest post
From what I've seen in this channel it seems to run fine on 2021 but it's at your own risk
Yeah that's kinda what i'd thought.. I'll maybe clone my project and test it out at least.
Hi! I converted my project to DOTS and added the ClassicBuild configuration and am trying to build a scene, but when I do it the content for the sub-scenes is not loaded as well as the resolution is different in the build.
I installed platforms packages as well as all the dots packages. See the screenshot. Any Ideas what am I doing wrong?
I've actually just had the same problem moving to subscenes, it works fine in the Editor but running a build doesn't work..
Theres only one IJobEntityBatch running. I do have an IJob that runs for about 20 seconds multiple frames so I know it's possible.
Entities itself, not hybrid renderer, works and builds perfectly fine in 2022 beta. So I would assume it works fine in 2021 as well. The other packages though, no idea.
here is a strange observation , i compared single threaded vs multi threaded jobs ( for the same code base ) , where i schedule them and won't force them to complete , and check each frame if handle is complete on the next frame and time the duration it took for the execution since the schedule and the handle.isComplete , some numbers :
Single Threaded is around [ 50ms ~ 100ms ] , at [ 400fps ~ 500fps ]
Multi Threaded is around [ 15ms ~ 25 ms ] at [ 250fps ~ 350fps ]
first metric is measuring Timer difference , second value is looking at the Game Stats
Which kinda looks like the single threaded jobs free up space for the unity internal jobs when looking at the profiler
Is checking the handle.IsComplete at an arbitrary point in the frame a useful way to get an accurate time?
its less accurate then looking at the profiler but at a high enough frame rate its not too bad ( considering my jobs are quite heavy )
i was surprised at the fact that multi threaded jobs execution reduces frame rate
@proud pawn afaik you shouldnt have to explicitly include subscenes(maybe thats breaking it?), also to be sure you are building from the inspector panel of the build configuration asset?
I'm reading the DOTS thread and there are just so many people asking for Unity to incorporate Rust or just switch to Bevy. I get it, bevy is just superior in terms of language and foundation but theres more to a game engine than just DOTS. Bevy is better compared to Godot in terms of a game engine than Unity...
the guys asking for a whole new language to be the driving core of dots is stupid, thread keeps getting derailed from actual development q&a
Yea it's just so dumb. I think I recognize one of them who previously complained that DOTS was so inaccessible. And now they want people to code in Rust?
Maybe Unity was right in never talking to us. Restarting the discussion about DOTS was a mistake.
i sure as hell wouldnt want to touch that thread if I were a unity dev
That one dev/employee answering questions is really brave.
And that answer to DOTS Audio recieving no updates in 0.50 is shocking. What the hell were they doing this past year?
its a good question, maybe the core devs left leaving it in a lurch? i dont have any other ideas
Core shouldn't be changing that much. I doubt there'll be any radical changes to EntityQuery or the underlying structure when they spent so long patenting it.
well maybe my other idea is the whole direction dspgraph was going in was the wrong one?
Maybe we should just get together and rip apart Entities.. I'm planning on spending a few days to maybe weeks trying to find a way to implement a frame independent IJobEntitiesBatch.
i hate that one guy in the thread who's like: uhhh, i think dots was a mistake. literally only big projects benefit from it. unity shoiuld've focused on something that does graphics better. like unreal engine nanite, .........
Well I think we'd all like nanite but that's a completely separate issue
I do wonder if unity has madly rushed something experimental in the works to compete
i kinda see it like a whole new paradigm, basically taking everything every game engine and platform has ever done over the past 20 years and throwing it out, doing it a different way
so i think architecting that should take a lot of time.. they've been good enough to give public access while they do it
they're kinda simultaneously creating something entirely new, whilst trying to bridge it to the old world..
so you look at the thing as whole, and say to yourself, have you ever worked on a big project that didn't require substantial refactoring along the way, rethinking parts, etc
with DOTS trying hard to be native & non GC, the question was if it’s going to be worth jumping through all those hoops. Nobody suggested Unity using Rust.
when every game and app out there sucks the life and battery out of mobile devices, hogs memory really inefficiently and yet, hardware year on year has got multiples more powerful, you have to say - there's some pitfalls to oop, devs are being reckless
it’s kind of like asking Microsoft if this whole linux subsystem is going to be worth it over say using Linux directly.
I have jobs chain like
JobA0 writes to array 0..5 indexes then JobB0 and JobC0 reads 0..5 in parallel (so JobB0 and JobC0 depends on JobA0)
all this happens N times, so next
JobA1 writes to array 6..10 indexes then JobB1 and JobC1 reads 6..10 in parallel
but safety system throws an error, because JobA1 scheduled after JobB0 and JobC0
i can schedule all JobA before all JobB and JobC, but it leads to unnecessary iterations. Maybe i can use some attribute like [NativeDisableContainerSafetyRestriction]? Will it help?
i'd love to see an A/B comparison between two simple cases, a simple game with all the usual OOP inheritance and spaghetti junction stuff, against some equivalent dots/ecs thing - i reckon even without using schedule or parallel, just run, with well structured cache friendly data etc it's going to be 200% faster and better.. probably, paradoxically, easier to deconstruct and understand also than the OOP mess.
well if you strip it back to just burst/jobs i have a few examples of converted code
- i experimentally rewrote our template placement at work and it went from taking ~4 seconds to ~200ms
- i also have a person project with a multi frame noise/terrain gen function that takes, no joke, 180 seconds to execute without burst on in mono but only ~1 second with burst
(because of that last one I asked Unity and they're investigating if it's possible to always force burst on with an attribute because it basically prevents me turning it off project wide for debugging)
burst in itself is a revelation.. someone shared an article here with the whole thought process and reasoning behind it, just amazing, imo
i mean i'm not blowing smoke up their *** i genuinely love what they're doing, but i do also wonder maybe they could get shit done a little bit quicker ( and be a bit more transparent on it )
there were people asking unity to support rust so they can write their dots code in rust
Ya know, Im staring at EntityComponentStore source and I'm thinking... why dont I make my own entities from just a collection of NativeArrays. Roll my own ECS?
And write it in rust?!
The primary issue with rolling my own ECS is how I would manage chunk segmentation via my equivalent of ISharedComponentData...
Fuck rust.
Maybe a UnsafeList<UnsafeList<ComponentType>> EntityChunks?
The scheduling is probably going to be absolutely god awful.
Just noticed they've removed the little icons next to peoples discord names
icons?
Yeah because i have 'generalist' role i had a little 3d unity cube, 'programmer' had a pc monitor.. directly next to peoples names in the chat
What the fuck unity
Parallel jobs can not cross multiple frames?
WHHHHATTT?
also god damn that optimization (the lack of it)
Yea, it's a problem with parallel jobs, not IJobEntityBatch.
this warrants a deeper dive, something is rotten in the state of IJobParallel.
ah that's not true, i have parallel jobs crossing frames fine
really? Do you have an example?
let me load up my terrain gen library
the only job that causes me issues (atm) is IJobParallelDefer because it uses some tempjob memory internally when scheduling for some reason
Something is calling complete() but I dont know what. And it's not my scripts
hrm... yea
are you writing it back to Dependency?
do you have the scheduling code?
Dependency = new ApplyDeltas
{
Deltas = GetComponentTypeHandle<Deltas>(true),
Inventories = GetComponentTypeHandle<Inventories>()
}.Schedule(_econQuery, Dependency);
SystemHandle = Dependency;
// SystemHandle = new TestJob
// {
// Deltas = _deltas,
// Inventories = _inventories
// }.ScheduleParallel(_deltas.Length, 1, default);```
yeah you can't do that
The commented section remains in one frame
if you write to Dependency it'll be completed
I'm manually updating this world
if (!_incrementTransactions.SystemHandle.IsCompleted)
return;
_world.Update();```
I traversed this entire method and there is no Dependency.Complete(). Which allows the singlethreaded version of ApplyDeltas to cross frame boundaries as expected
But conversion to ScheduleParallel(_econQuery, 1, Dependency) results in a frame lock
I can remove the Dependency and straight write to SystemHandle but it wont change anything
{
if (!this.lastUpdate.IsCompleted)
{
return;
}
this.lastUpdate.Complete();
this.Dependency = JobHandle.CombineDependencies(this.lastUpdate, this.Dependency); // TODO should not be needed
// Apply Update
this.lastUpdate = this.ProcessOperations(this.Dependency);
var camera = Camera.main;
FrustumPlanes.FromCamera(camera, this.frustumPlanes);
this.lastUpdate = this.clipmap.Update(camera.transform.position, this.frustumPlanes, this.lastUpdate);
}```
all the jobs are scheduled in this.clipmap.Update(camera.transform.position, this.frustumPlanes, this.lastUpdate);
just looks like this
(more jobs above it)
hrmmm, I need to keep testing my IJobFor / IJobParallelFor version then.
but yeah, if i turn off burst and turn on my noise generation, this will run for nearly 3 minutes in separate threads in mono until it completes
without a forced sync
I'm running this job completely independently from Entities (other than the SystemBase it exists in), so it's not an issue with the query systen
how are you creating the world?
_econWorld = new World("Econ World");
'just finding the world then calling update
ok but not added to player loop or anything hmm
nope
completely independent
The issue is with this: _incrementTransactions.SystemHandle.IsCompleted. It's returning true even when the job is not completed
If I were to instead singlethread execute the same job, SystemHandle properly returns false when the job is not completed
Interesting. Turning off burst to extend the runtime of this job shows that IJobParallel can cross frames
However it's not stable.
and still bleeds into the FPS of the main loop
Well fuck. Turning off vsync crashed my entire laptop
Singlethreaded: no crash of computer. Multithreaded: crashes my computer. Clearly the conclusion is self evident.
Does anyone know the state of DOTS audio? Should I skip over it for now and use a hybrid solution? Going to read the DOTS Audio Discussion forum thread right now
It works but not documented at all. I think someone chimed in here before that it even works in 2022.1 b
Roger that. Thank you
Do note, Unity has said that there will be no update (code wise, unknown documentation wise but probably the same) to DOTS audio in the upcoming 0.50 update
Oh, interesting
You'll be in for the long haul for any update to audio
Gotcha. I think I'll just go hybrid unless I realize my audio perf is too slow
Something i've been curious about, has anybody tested performance with using several components each with a single or very few variables, compared to fewer components with a larger spread of variables..
i can understand the practical advantages of using more components, say if you have one system that works on only say health, another that works on weapon data, and another that only uses movement speed and translation, it would make sense to separate that data out into different components
just curious what the balance of that might be.. i would guess it comes down to cache utilization and stuff, which is something i've not really spent any time doing the math on
Alright, I've crashed my computer about 10 times already. I think I got a reproducible system for the burst guys to look at.
In theory smaller components are better, in practice it doesn't make much difference unless you're in some critical path that is highly optimized.
my advice is generally do what makes sense for usability. optimize when you need.
Yeah that makes sense, easier to split apart larger components if/when needed later
There we go, a reproducible bug report, at least on my computer. Hopefully the burst team will help.
I've been trying to get a shadergraph material to work with DOTS, but as soon as I put something as simple as a color into the base color node, in play mode the object with given material starts flickering many colors. Black, unlit black, red, green, blue, UV. Every frame a different one. Anyone know what the problem is?
I've overridden the property declaration for the Color Property to be Hybrid per Instance, and enable GPU-instancing on the material itself.
I've been pondering about this myself. Burst really like structs with 1 field for auto vectorization. The CPU doesn't seem that smart about reading several small sized structs though. (On profiling I have read stalls) It would be interesting to essentially force feed a full chunk into the L1 cache because then it doesn't matter how small or big the structs in the archetype are. Reading them by cacheline and doing something in between doesn't seem that great. I've asked this in the forum lately (to support other memory layouts) but it wasn't that helpful. I've a lot of reads in my biggest job but merging the data makes little sense. Maybe I get around in making a dedicated test for this to see how much merging would really get me.
@still pewter did you add ENABLE_HYBRID_RENDERER_V2 to your scripting defines?
yeah i think it would be really interesting to test that
it could be one of those situations like for example parallel jobs, where it's not really worth it below a certain point, but beyond that it makes a big difference
so i'd guess it depends on the situation also
@still pewter No meme/reaction gifs here.
That was it, thanks!
was it not the case in the past ?
I came across this when browsing forums, not sure if you've seen it: https://forum.unity.com/threads/dots-and-2021-2-known-issues.1183456/
I thought they could
Quality of forum discussion here mates. Unity was right in never updating us. I now regret my wishes for unity to talk to us.
is that a Keren developer ?
Stopped reading that guys posts 2 years ago
God damn there's some salt on that forum, jeeez
🥲 this guys on forum makes me feel pain
If you look at what's happened over the years with 3ds Max, it's interesting and maybe relevant..
When i started out it was pretty much the industry standard for 3d modelling, animation and vfx, although of course there were others, Maya etc. It's now essentially a dead horse, new generations of artists learning Blender and old artists jumping ship, because they see that Max is a sluggish, bloated pile of legacy junk, the codebase is legacy and Autodesk have spent the last few years just buying third party tech and strapping it on top of the old.. and on top of that it's expensive..
Compare that to something like Blender, not only is it free but it's lightening fast, actively developed and constantly evolves and develops on the cutting edge of tech. Blender does everything Max does but 100x better and faster. Just starting Max takes several full minutes, Blender starts in an instant..
Now looking back, Max could have kept on top of the game, if they'd wanted and had vision. Substantially refactoring old legacy code, cutting dead weight, making it faster and better over time. But they didn't, they just kept piling on top of the old until it fell over..
So where i see the analogy is with what Unity are doing with ECS/DOTS.. A few people complaining 'why don't you just give us new features instead of working on this' etc etc.. I guess it's a toss-up between what's more important, the current Unity 'works' and new features would 'make it better', but looking ahead i think that at some point you have to make big decisions and do some work that's better in the longer term. If ever there was a time to refactor Unity at it's core it is now, before it becomes just another bloated dinosaur, and essentially gets replaced by the next Blender of game engines.
Despite UnrealEngine's awesomeness and all it's very cool work i feel under the hood they're doing the same, gunning for faster and leaner and better, because they know they literally have to. I think they just tend to do it more in a way of providing the end-user finished tools with these improvements rolled in, rather than the approach Unity is taking which is more bottom-up i think. I prefer Unity's approach and in a bunch of years i can see Unity's groundwork now taking it ahead of even Unreal.
uisng the AcidArrow's way of conversation i want to say: I AGREE with all your points 🙂
Hehe, it's just my 2cents tbh.. i understand peoples pain, but as the saying goes you have to break a few eggs to make an omelette
yeah what autodesk did(or didnt do) to their top 3d products is really just sad, mudbox, 3dsmax, softimage, maya all languishing with few or zero updates. but at least in this case they never made any announcements of "rebuilding the core" or had open demos/preview builds of anything demonstrating anything close to such an initiative. that alone should give people some indication this isnt quite the same case for unity, nor was there ever any real developer interaction on these types of things to my knowledge. I dont even know if the 3dsmax team is different from the maya team 🥲
You forgot the passive aggressive cheers
ha I just tested the forum ignore function, i just added his name and poof, all posts vanish like magic 🪄
unity recommends to only have the exact minimum data in your IComponentData that is needed for jobs. a job should not only require a subset of the data. then it should be split up into multiple components
i believe this example covers only rebuild something instead of increase old stuff, so yeah unity still have this bad "wow, look at dots, million rotation cubes, whooooa" and today we celebrating each new joachim's reply on forum. But i completely disagree with all this "drop dots unity pls" replies
fully agree. although something like nanite would be nice to have......
yeh, they should add support for mesh shaders (not geometry/vertex shaders), that is in DX12, in vulkan there is only the Nvidia version currently :c
Mesh shaders is already on the roadmap for a few months. While definitely powerful, they're not really a complete nanite replacement
Also, they require more dev time to work with whereas nanite is all about less dev time
Every forum has an "AcidArrow". It's like some universal rule.
Having him on ignore makes threads a lot more sane and focused. His derailing is insane. I think hippocoder has just given up at this point. He'd have to delete like 98% of his posts outside of the general subforum.
I wonder when someone will port EnTT to burst 😄
finally happy with my camera/cinemachine implementation
might dump it unsupported on github (the cinemachine conversion, not my camera/state system)
https://forum.unity.com/threads/cinemachine-dots.1215168/
There we go, video + code dump if anyone needs
I would've sworn unity was on 0.21 or 0.23 internally. Yet the most recent DOTS training samples are on 0.20. Odd. The preview number though has increased from 25 to 45 within the past 3 months so something is going on. I just wish these guys would use struct based jobs and not lambdas...
they are writing "optimized" code for a framework that doesn't exist. welcome to unity development
They were floating the idea of lambda jobs in ISystemBase in that most recent announcement. The fact that none of these training samples use it means it's probably a stretch goal.
they still haven't talked what's actually in 0.5. it's really weird.
Ya know, now that everything is a singlethreaded job, coding is so much easier. No need to do weird hacks to access behind the scenes class buffers or pointers. Having frame independent system update is so liberating.
Race conditions? Never heard of it.
Performance? Look that way, the graphics thread is updating at 60FPS. Ignore the simulation ticker updating at 60 SPF.
From the training samples, doesnt look like anything at all.
have you read the thread from the guy who uses rust for lots of stuff?
The one with using rust as extern calls from within unity c#?
yeah
Thats pretty much what Unity does with their game engines. If I wanted to program a game engine, I wouldnt be here.
it's interesting in that rust has bevy and c++ has EnTT
It's not new or radical tech, you can attach native DLLs but its a bit of a security concern.
tbh im not expecting 0.5 to be much different
I dont expect much either but I really wish there was an explanation of where the year or so worth of development time went into.
into an ifdefed enable/disable feature that needs another year to iron out the edge cases ... 😆
Just take a look at burst for example. In the same amount of time, they introduced SIMD / manual vectorization commands for nearly all CPUs, improved function pointers and enabled additional connections across the main - job thread barrier, and drastically improved the burst inspector. The DOTS team: uhhhhhhh... nothing visible. Possibly source gen'ed improved lambda code?
apparently the entities team works on the HR and netcode too
I dont think so about Netcode. That was branched off and now is a fully released package. Unless you're talking about DOTS netcode which has gone radio silent. Same as DOTS physics.
working on a new renderer in 2021 and then seeing Nanite ... ouch
of course dots netcode
@robust scaffold yeah me too, doubt we will ever know though
at least tims name is in the patent of entities
so he must be involved more than just in netcode
DOTS netcode is definitely a different team. No way is mainline Entities gonna get this clear of an answer of whats coming in 0.50
technically nanite was in development for like 10years though, must be disappointing to see epic leapfrog your work again but then again that was brewing for a loong time
Also the DOTS netcode team said no to ISystemBase upgrade of their provided supporting systems. Which doesnt bode well. SystemBase pretty much only needs entity query capability in bursted OnUpdate and it's feature complete compared to SystemBase.
pretty good read https://skypjack.github.io/2019-03-07-ecs-baf-part-2/
However, the main issue you can encounter with archetypes is the fragmentation.
Shortly, an aspect that is less evident but still present is the fact that archetypes aren’t primarily designed around usage patterns.
Something I'm definitely dealing with.
Fragmentation as in shared component data or enabled/disabled entities?
some serious pros and cons with archetypes with the biggest pro being so easy to multithread
nothing like that. I brought it up in a thread about memory layout where the problem is that reads from arrays can not be exploited well when you just read a bunch of components from a single entity/archetype. for every array access you read the data of the next entities but they are never really used so the L1 gets fragmented
Hrm, yea. I guess unity's implementation of Array<Array<ComponentType> Archetype> Entity doesnt really work well with single entity access.
I've gotten identical (well slightly faster by fractions of ms) when iterating through a NativeArray<UnsafeList<float>> as using IJobEntityBatch to access float components.
right, which ends in weird stalls. I haven't found a good solution for this. merging data is one but really meh. it's the same problem with authoring<->runtime data. now it's component<->chunk data
ah interesting, I thought about dropping Entities for data that doesn't fit.
What do you mean? Ive never had any issues with accessing a chunk component then assigning all sub entity components by that chunk component(s). Very fast and vectorized.
yes, when vectorized 🙂 but what if not? 🙂
Yea. I did some tests earlier yesterday and the performance of a vectorize add across 32 bytes in a single struct for NativeArray<UnsafeList<32Bytes>[2,400][1,000] was identical to a DOTS implementation
If you're not linearly accessing across a data array, you either need to find out how or eat the performance cost because that's OOS coding.
Sometimes, it simply can not be avoided. Or i'm just not thinking creatively enough
I sent you one of my code files. 🙂
That's one giant IJobChunk
My most complex job is about the size of that GetNativeArray section
My head is exploding. I dont think I can properly think in SIMD...
I even pulled out a sheet of paper and a pen to figure this out...
I've got a BuildPhysicsWorld system that takes about 20ms each frame to run, I've got a terrain (1000 by 1000) which I generated a manual PhysicsCollider for, to bring it into ECS land which I suspect is what's causing the long run time and thus low fps, any ideas on how I can reduce the per frame run time?
in the profiler what is taking up the time?
profiler timeline view that is
make sure to expand the jobs view
I'm not that familiar with the profiler tool, here's a screenshot of it - can you point me to areas that stand out to you that i should investigate?
Lots of blue, have you considered burst compiling your jobs?
also lots of empty idle time, have you considered collecting the job handles and then calling Handle.Complete() at the end of the frame?
It does help when I burst compile, however I can't debug very easily when it's on, I'll do so for release (if that ever happens).
I thought the "handle.Complete()" for ".ScheduleParallel()" jobs was optional - I'll make a note of this and go through all jobs/systems and add it in. thanks!
Wait, dont add it. If you're not calling complete, thats fine
The problem with your frame utilization is that you're waiting on one very long job at the end of every system. Locking the main thread
Try turning every schedule parallel to just schedule.
I currently have about 3 meshes - 2 characters (low poly) and one terrain mesh - on the scene. The terrain is the one that has a lot of vertices, so I presume it's the thing that's holding everything up, just my assumption though
only 3 meshes yet it's holding up the entire frame. something doesnt seem right
From the EntityDebugger, looking at the systems run time, it points to the BuildPhysicsWorld as the system that takes the longest at 20ms per frame - I don't have any control over this system, how do I go about changing it?
Ya gonna have to find someone more experienced than me because I have no clue why that runs every frame
looks like the fixedstep systemgroup is doing catchup because the frame time is so long or something
can you circle the part of the screenshot I sent, that shows the frame waiting for a long job of each system? for my learnings so I can spot this stuff in the future
wait did you disable burst or something?
can you show me what tells you that? just so I know how to see these things
sec
I did disable burst, to debug code, as with it on, I can't seem to hit breakpoints. However, with only 3 meshes on my scene, something still feels not quite right and it's easier for me to see if changes result in frame rate improvement in non-burst, rather than in burst
This is usually what I use to watch which system might have issues - which is why I'm drilling into BuildPhysicsWorld as it takes up the majority of the frame time, of ~22ms
With Burst enabled, everything runs smoother and I'm hitting 33fps, but it feels like I'm just sweeping a possible issue under the rug with "burst"
I circled what I suspect are the repeated runs of the physics stuff
if you click the three dots by the arrow I made theres an option to turn on something that shows what jobs are spawned by what system
cant remember the name but there are only a few options there
without burst, a heavily ecs project in unity will just run like ass, theres no real way around that.
like burst is essential and you shouldnt consider perf with entities without burst to be anywhere close to even good, its leagues worse than stock unity gameobjects which genuinely surprises me
as for debugging with or without burst, not at main comp so cant check atm and cant remember if I need to disable it for breakpoints to work
oh I see - Yeah that's where I'm coming at this from, I thought without burst is just the base gameObject speeds
no, yeah its shockingly low 😅
alright, then maybe there isn't a problem here and I'm testing this wrong without burst.
If you could let me know how I can debug and hit breakpoints with burst enabled when you can, that'd be much appreciated!
ill ping you tomorrow if I remember to check it out
requires a native debugger to pick up breakpoints
what does that mean? I'm using rider to debug
Native debugger is a special type of debugger that can pick up breakpoints called from compiled code. Or something like that. Rider does not have that capacity. Visual studio however does: https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-debug-in-mixed-mode?view=vs-2022
apparently this is on their radar https://youtrack.jetbrains.com/issue/RIDER-11810
giving it an upvote to hopefully improve chances it turns into a feature
A few sheets of paper and I've done it. A vectorized way to evaluate two 8xints for most positive grouping
It's so beautiful. So purple
If you're not a robot and can not immediately understand what is going on, this is basically what that chunk of code does:
T1 = 2, -2, 1, -1 -> 2, 0, 0, -1
T2 = 3, 4, -2, -3 -> 3, 2, -1, -3
With a delta change from T1 -> T2 of 0, -2, 1, 0
right, lets see. Maybe burst knows what they're doing?
damn it burst team, too good for me. Actually knows how to properly vectorize. I just spent the past 4 hours writing code that doesnt even matter.
Lesson learned. First see if burst knows what they're doing
<@&502884371011731486> scammer ^
Where thelebaron has circled in red, the multiple instances of BuildPhysicsWorld, i noticed this in mine also.. Try putting the following line inside OnCreate somewhere:
World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<FixedStepSimulationSystemGroup>().FixedRateManager = null;
I have no idea what this does, but in my case it seems to prevent multiple instances of BuildPhysicsWorld and i think StepPhysicsWorld
I think i got this from the ECS Physics samples when trying to diagnose a problem.
It stops physics running in fixed update
Mm no i still get physics build and step in the FixedStepSimulationGroup.. i just get one of each instead of multiples of each..
Not sure really why that is either way tbh 😐
Yes but you deleted what makes it a fixed update
FixedRateManager is what makes it fixed update, if it's null is just a regular update group
Wow, that actually helped a lot! Went from 22ms to about 3ms without burst! Thanks for the tip!
Now, to try understand what might be going on, does anyone know what the repercussions of deleting the FixedRateManager are?
Hmm yeah i definitely need to look into this more i think, it's definitely faster that's for sure, and again only does that single physics step.. is the determinism aspect more related to the networking side?
you're not running with a fixed step anymore
so the first time you run it your timesteps will be different to the second time you run the simulation
technically it's only faster if you're < 60fps, it's slower if you're above
just reduce the update of the fixed update manage to like 20fps instead of 60 in editor
if you are concerned about lag in editor/debugging
Yeah these are the technicalities i need to get my head around with physics.. I appreciate the knowlege there..
Was just looking for the thread i got the dots physics terrain collision script from, this is the thread here:
https://forum.unity.com/threads/using-unity-terrain-with-dots-workflow.755105/
I did notice it seems to be pretty slow maybe similar to uneatenbreakfasts problem.. So i guess the question is - with just terrain and a couple of characters, why is it like 20ms+ doing physics
ie without this deleting FixedRateManager hack
So if it's better to not delete that manager, why is it so hella slow
it's the fixed update feedback loop
if you have a fixed update at say 60fps, and you are running less than 60fps - let's say 30 fps
then your fixed update has to run twice a frame
but now that it's running twice a frame your frame is taking longer, so your fps is even lower and well now you need to run some frames 3 times a frame
anyway from memory it's mostly slow because of jobs debugger
turn that off and it speeds up a lot
ok yeah i think that makes sense
i did notice tbf i get 30 or less fps in the editor and like 140 on built project, i wonder how much physics itself is held back in the editor
if you turn off debug mode in editor and all the safety
it runs nearly identical to builds
but yeah, then no safety + can't attach debugger 😅
but good for your artists/designers/qa
stupid question time - how do i set my unity.physics fixed update to a specific rate? assuming i could set application.targetFramerate to a specific value and tie fixed update to that, or is that fixed update?
ah ok, seems obvious, thanks!
you know that fixed FixedRateManager? change the Timestep
by default it's 1/60
so what, 0.0166~
make it 0.05 for 20fps etc
Anyone knows if its possible to run ICollisionEventsJob jobs in an Entities.ForEach or Job.WithCode (on main thread)?
All code examples seem to rely on Job.Schedule(simulation, physicsworld, ..) but the project I work on the guy wants it written as ForEach or WithCode to run sound and vfx (not possible on parallel threads)
i dont think you can yet, seem to recall it was sort of on their roadmap but then again that was before they paused public releases. not a bad thing to ask on the roadmap thread
245ms - OptimizeFor.Default
346ms - OptimizeFor.Performance
That's not ideal >_>
I made a dev build of my game, however I'm running into a crash. Attaching the debugger to the build, I see this error:
"Exception thrown at 0x00007FFE73526059 (lib_burst_generated.dll) in mmo.exe: 0xC0000005: Access violation reading location 0x00000280D649425F."
Any ideas on where I might look for further information? It seems like something broke in the burst sections
this is mostly commonly caused by something like
ComponentFromData<Translation> trs;
var tr = trs[entity];
where entity doesn't have a translation or doesn't exist
you should be able to find the exact job/line of code that is crashing from the dmp file
there's no safety in build so any failure like this is a crash
I've got the crash.dmp opened in VS, where do i look?
by default I think, top right is a button that says something along the lines of play
basically just hit that, link your pdb if you need
and it should show you the call stack of your crash
Great, there's a "debug with native only" button there, and it's kicking up the process of loading in all the pdb files, it's taking a while.
Is there any way to get this kind of error showing in debug/editor? I don't see this particular issue as warnings or errors at all in the editor
In theory, the safety system should error this out for you in Unity. In practice a lot of timing issues will only show up in builds, or at least more frequently.
thanks heaps for the help, I was able to find the line that the error is coming from.
Does the debug mode from unity crash dumps show variables too? or is that asking for a bit too much?
/depends/
is it a setting or certain way I need to create the build?
dmps are just a memory dump of your application when it crashes. by default this only includes general information, the stack, etc
the pdbs store a list of all your symbols and their address of your application to link against it
Hey guys, been severely ill in Nov/Dec, did I miss something since ?
No I missed that, and looks like what I was looking for. Thanks a lot Script.
Just in the hope I find someone. Anyone here know how to debug a Unity coredump from a crash in Linux?
somehow my compilation never ends, anyone know why it may be?
is NativeArray.Sort job unready to use in prod or its my special case? (editor profiler)
Burst crashed / stalled. Gotta task end unity then reopen the project
The packaged sorting function is not a good sorting method. Theres articles online on how to implement your own.
articles on top of dots or parallel sorting in general?
the thing that helped was rerolling burst version to previous one
https://coffeebraingames.wordpress.com/2020/05/24/nativearray-sortjob-is-fast-or-is-it/
https://coffeebraingames.wordpress.com/2020/06/07/a-multithreaded-sorting-attempt/
And there's more on the internet. Those were the first on the google search
There's also a section of dodbook dedicated to sorting -> https://www.dataorienteddesign.com/dodbook/node8.html
Sorting
I see in burst docs that burst can't compile generic jobs which gets context indirectly like being scheduled in generic method
//from docs https://docs.unity3d.com/Packages/com.unity.burst@1.4/manual/docs/OptimizationGuidelines.html
public static void GenericJobSchedule<TData>() where TData: struct {
// Generic argument: Generic Parameter TData
// This Job won't be detected by the Burst Compiler at standalone-player build time.
var job = new MyGenericJob<TData>();
job.Schedule();
}
// The implicit MyGenericJob<int> will run at Editor time in full Burst speed
// but won't be detected at standalone-player build time.
GenericJobSchedule<int>();
How then NativeArray<T>.Sort compiled in standalone? Is it even compiled? I've seen thread somewhere on forum, where someone have mentioned that NativeArray.Sort isn't burst compiled in build and some unity dev was like "its a shame that built-in functionality isn't burst complied, because performance by default and stuff". And it still in uncompiled state?
i know, because sample code is from this docs. So it is well known fact that sort extension isn't burst compiled, ok
i was under the belief it worked from about mid last year after one of the burst updates, though i haven't tested i've always just call sort from within a job already
side note: my personal trick for burst and generic systems
where T : struct, IStateComponent
where TP : struct, IStatePreviousComponent
{
/// <summary> Create the job struct for burst support. </summary>
/// <remarks> You only need to return default. The struct is populated for you. </remarks>
/// <returns> The job struct. </returns>
protected abstract StateJob CreateStateJob();
[BurstCompile]
protected struct StateJob : IJobEntityBatch
{
}
}```
{
protected override StateJob CreateStateJob() => default;
}```
just been the easiest/cleanest approach I've found
if this is so simple and it works then i wonder why burst still can't detect such cases
because burst needs a concrete implementation, i'm providing this
but if you just gives it default why then they can't do the same in analyzer when it faced indirect context
the answer is mostly, performance
it could take a long time to compile if it did what you wanted
I'm not able to use NativeHashMapExtensions.Remove(key,value) despite having Unity.Collections in my project. This is strange considering that other extension methods like Unity.Entities Schedule are working
I was trying to call NativeMultiHashMap.Remove(key,value), but keep getting compilation errors claiming that the method does not take 2 arguments
Nevermind, I forgot to implement IEquatible for the value type of the multi hash maop
argh I see I use translation not transfrom.position, but still not working 😄 will crack on trying more
sorted
what's MethodImpl( MethodImplOptions.AggressiveOptimization ) and can / should we use it with burst ?
i noticed that mathematics package is using AggressiveInlining , which i guess strips the method at compile time and writes the function body were its been called
Yep. The opposite is NoInlining which isolates the method into its own block (typically at the very start) and the executing code would function call it. You want to use AggressiveInlining always during actual production code and NoInlining when debugging and checking your burst outputs. I believe the default is somewhat in between the two depending on the length of the method.
Any ideas whats AggressiveOptimization AggressiveOptimization ?
i read a stack0erfl0w - p0st and it had s0mething t0 d0 with a JIT - which kinda seems like what burst already d0es , n0 ? ( I L0st my "0" key )
How did you lose a key? Ouch. Uh, aggressive optimization... it's not documented. I personally have not seen any changes to burst output with and without it.
laptp getting 0ld might need t clean the keybrd r s0mething
Which burst are you using? I dont see aggressive optimization in the method impl attributes options. Although I do remember it existing
was actually checking 0ut s0me 0ther rep0 0n github and it included that
s0 i th0ugh if there is a need t0 make it burst c0mpatible 0r* n0t
OPTIMISE = 512
probably what they are doing is this [BurstCompile(FloatPrecision.Low, FloatMode.Fast)]. This allows for MADD and other less accurate single operation mathematics. Also assuming no null or overflow values so stripping the checks off the process log.
s0 the0retically this shu0ld give similar speeds t0 burst ?
That looks like to be a different .NET complier, not burst, so who knows.
Doing some testing on shared component propagation to chunks. Apparently copying of shared components to accessible chunk components is in fact worse in terms of performance than an external HashMap containing a lookup of <int, ISharedComponent>. The HashMap lookup resulted in about 1.05 ms vs accessing a chunk component of 2.0 ms. Odd.
Definitely recommend anyone who cares do tests themselves but having external databases may be better than attempting to use Entities components. Which is probably why Unity has not yet implemented a ISharedComponentAccessableInJob or whatever.
Just a quick question:
Does reading from a randomly accessed entity represent a sync point when doing it outside of a job (e.g. in a monobehaviour)
No
However, it will call the job complete for the dependency of any jobs accessing that component of the entity.
Which, depending on how you structured your jobs, may be a sync point.
Thanks
That is a very helpful answer! :innocent:
I'm trying to install the entities package in my project but am getting this error after it is done
Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Serialization\BinarySerialization.cs(47,81): error CS8377: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'NativeList<T>'
How can I resolve this?
Are you on the latest collections package?
I'm on version 0.15.0-preview.21
I'm not at my computer right now. Is that the one released in november?
it's from january, but updating it will only show a november release as the latest (I'm on unity 2020.3.15f2 btw)
after having updated that, I'm getting 165 errors that all have the same error code
Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Iterators\EntityQuery.cs(1222,100): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('EntityDataAccess')
if you add entities to an empty project you can see what dependencies it needs and then change your project's packages accordingly. the latest collections isnt compatible with it though not sure about some other packages
say I have a bunch of data components, each with unique X value.
how do i simply say get entity with component value of X if exists, or create it?
I justg entity query for all DataComponents... then loop the resulting array and see if an item that is what I want exists?
Yeah i think you'll have to iterate over all instances of that component and check the value
There is an 'change' filter which will return a query only if the component has changed, but not for narrowing down on specific values
after downgrading to the previous version of the collections package, which did solve the errors in my previous message, the BinarySerialization.cs error CS8377 occurs again. Thus bringing me back to my first question on solving that.
So i was trying to reimplement the boids demo from the Mike Acton talk (https://www.youtube.com/watch?v=p65Yt20pw0g) to learn DOTS and but have seen that "IJobNativeMultiHashMapMergedSharedKeyIndices" has now been removed from the collections package. Is the way this was done now seen as bad practice in DOTS and are there better examples/docs i could look at? The ECS samples still seem to use the removed job type.
it's not bad practice, they just decided it wasn't suitable for the package. the exposed the data required so you couldn't implement it yourself
fair enough, thanks
as a related follow up, in the boids example they copy all the translation components from the boids entities into an array to access later. Is this significantly faster than just calling GetComponentDataFromEntity?
for this type of critical work it can be
So I'm having trouble understanding something. Where are the gains from dots supposed to kick in? I'm instantiating 5000 trees as game objects, and then 5000 trees as entities (converting from the tree prefab; it's the tree in the unity standard assets)
And it turns out those 5000 trees as game objects run a lot faster in terms of FPS than as entities. Is this normal or am I doing something wrong? I'm not doing anything other than instantiating game objects and entities
This appears to be true even for empty game objects and entities; 250k empty game objects runs faster than 250k "empty" (containing only rotation, translation, prefab and localtoworld components) entities
Why is this happening?
Are you measuring the overhead of Hybrid Renderer because it exists regardless of how many objects that exist. If youre doing nothing with the entities / objects, then yea DOTS isnt gonna do well
What you want to compare is the performance when you start rotating all the objects
So if my objects are fairly static, as in I won't be doing anything with them all at once (maybe I'll occasionally raycast against one); if could go with game objects and be fine?
Basically yes. Either that or roll your own render pipeline.
if these entities have a prefab component attached they won't be part of any system updates so kinda sus that gameobjects would be faster here
could be base overhead but shouldn't be a large diff
So it turns out for default cubes, 50000 dots entities is much faster than 50000 game objects cubes. So there is a difference that favors dots in this case
DOTS hybrid renderer suffers from being a "generic" solution. A customized render pipeline and something like DrawMeshInstanced or a compute shader solution is what you want.
I mean, thank you for the technical advice but I'm just not going to be able to do that 😅
I only render 3 game objects and one of which requires virtual texture tiling. I am not capable of programming the compute shader required for rapid redirection table updating so I use HDRP and do simulations on 2.4M entities (not rendered). However if you are capable of doing so or slogging through the text books to learn how to, you can get 10x better performance at most just programming your own rendering solution. But then you might as well make your own engine and so on.
I was going to reply exactly this but I didnt want to come across as impolite. Basically at this point I'll be rolling my own game engine. I'm not a studio, just some guy thats doing gamedev
Even then, you can go extremely far with the DrawMeshX variant Burst arrays - compute shader pathway. It's highly recommended if you need to do anything more complex to 10k+ objects than rotating them.
A few other ideas that seem worth mentioning:
Make sure the enable_hybrid_renderer_v2 define is defined. Make sure you’re testing in a build, or at very least ensure burst enabled, safeties disabled, warm start etc. Very possible that however this tree is made is breaking instancing for the version of hybrid renderer we have access to. Lastly, dots isn’t going to help perf for a lot of people as most projects are gpu bound. Static meshes are never usually the biggest pain points either. Will mostly help for cpu simulation… though Unity continue to promise eventually job/system code should all execute faster than MBs but it’s not always the case currently.
I'll make sure to check these things. I'm trying to create a voxel simulation game and the two most obvious problems I've ran in to is that you're going to have a lot of really simple entities representing small objects (things the player uses) and a lot of chunks (mostly static meshes you raycast against, change a couple of data around, and rebuild)
Clearly the GameObject object is far too heavy to have as many of these things as one might desire
What you said makes sense and I'll try to make it work
Yea don’t use entities for voxel representation- there’s no need. Quite a few posts about voxel stuff on the forums that’s probably worth digging through
I'm using them for chunks, not individual voxels if that's what you mean
Cool yea that sounds sensible.
Still, 1000 chunks and 5000 "entities" as in small drops, rocks, etc. as GameObjects will absolutely grind unity to a halt; which is why I'm experimenting with dots
If you plan to do voxel sim on cpu (rather than eg compute shaders), I’m sure dots will be much faster than GOs, yea 👍
This is preferable imo, cpus are general purpose processors with general instruction sets. with gpus you'll have to worry a lot more about the version for which you're compiling your application, some wont have good gpus, in some gpus your compute shader wont work, etc.
I’m not advocating either way. Just pointing out that the biggest scale voxel stuff out there is mostly gpu afaik. Doesn’t mean that’s what you should be aiming for at all - just checking you were actually aiming for cpu.
As otherwise dots isn’t going to help much (sweeping general statement, burst is always lovely)
i have a pretty good dual contouring (with seams) implementation working with burst that can update in real time (posted a video here before)
i believe no mans sky uses a combination of cpu/gpu for their implementation
pretty certain their uber noise function is going to be the gpu as it's just not feasible on a cpu, but i think a lot of the dc is done on the cpu
they dont have the problem with most simulation games in that most of that part of the game runs on hardware they control, you're not supposed to be able to run the master server for a no mans sky instance from your laptop
whereas with minecraft you might even be expected to run it from a mobile phone
hello everyone. i am newbie. how i can translate object using local axis?
translate/rotation is in local space
i mean in ecs, i have child entity object, who should look at another entity
yes, translate/rotation components in ecs are in local space
you can use the LocalToWorld component to get world space forward/etc
unfortunately at this time it's a lot more manual / less helper methods
Is there any tools to help debug/see entities in a development build? I'm trying to get animations to display, but they use a method (toDenseClip) that only exists in the editor, so apparently I need to build the project in a way that embeds the prebuilt subscene in order to use the animations from it. However once built, it's empty, the build runs, but I can't see any of my entities anywhere - Is there an entity debugger but for released builds? How would you guys tackle this?
Is it possible to disable the IJobParallelFor write range restriction for the entire job, as opposed to the per-collection basis?
The problem I'm having now is that I have a custom struct that contains 2 NativeArrays. Adding the usual attributes to fields of this custom struct type in the Job does not work.
Highlighted in red is the field in question
...which contains:
Of course I could just put these two arrays in the job as two separate fields, but I was wondering if I could prevent such a workaround
Is this not what you're looking for?
This window will list all the entities
& click on an entity to view its components
Does anyone happen to know what the threshold size is for these to occur with Allocator.TempJob?
can we add buffers to components?
using Unity.Entities;
public struct EngineData : IComponentData {
public DynamicBuffer<RequiredActiveMapTileBufferElement> requiredActiveMapTiles;
}
I keep getting '<> used in NativeArray must be unmanaged and cannot itself be native' if i try
it compiles ok but then when i try to use the buffer
To get around it, I just added the buffer seperately to the same entity using the manager:
EntityManager.AddBuffer<RequiredActiveMapTileBufferElement>(engineDataEntity);
which I can work with, just wondering if the 1st way is possible
Yea you wouldn't be able to add a dynamic buffer directly into a ComponentData You can add pointers to your component datas/fixedlists/unsafelists tho (pointers and unsafe lists would require you to manually manage their memory)
fixedlists are fixed size, so they're also safe candidates 👍
I just wanted a list of tiles near my player, does this system make any sense to achieve that?
https://pastebin.com/9CEEY5vk
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
It also accesses some global engine settings variables and stuff, so hopefully its ok to use it like that
this task isnt heavy so i not worried about schedule parallell at this point
Can you not just make a public struct EngineData : IBufferElementData {}?
maybe but enginedata will have reference to multiple different buffers
That sounds like object oriented coding right there but there are ways to get arrays into components
yeah 😛
public struct EngineData : ISystemStateComponentData {
public UnsafeList<RequiredActiveMapTileBufferElement> requiredActiveMapTiles;
}```
You will need to manage the allocation of that unsafe list (basically a NativeList) and dispose of it manually, hence the ISystemStateComponentData
This will massacre your Burst auto vectorization so I highly do not recommend this. Lists and references inside Component Data is highly object oriented coding and goes against DOTS design
ok, I will for now leave it as:
EntityManager.AddBuffer<RequiredActiveMapTileBufferElement>(engineDataEntity);
How many elements do you need? You can use a fixed list interpretation inside a component as well. Also how often are you requesting that data?
Im still experimenting but just trying to code a 2d ecs chunk loading system, but am very new at the moment 😄
have done a load of tutorials including a standard unity 3d chunk loading system series before: https://www.youtube.com/watch?v=h66IN1Pndd0 *20+ hours) so have done siimilar, but not using ecs
JOIN THE DISCORD SERVER!
NOTE: I have NO idea what happened around the 6:30 minute mark with the epilepsy-inducing flashing red screen. Sorry about that :-/
This is my first attempt at a coding tutorial video. As I explain in the vi...
I recommend not diving into DOTS at all, or at least the DOTS ecosystem, when starting out. Start first with the Burst system. Bursted jobs like IJob, IJobFor, and so on. Learn the NativeArray structure by heart.
On that note, I just finished a manual vectorization of a exponential estimation function, currently 2x faster than math.pow() but requires all positives and only accurate within the ranges of 0.5f and 7f.
private static void ComputeTaylorExponential(v256* inputPtr, v256* outputPtr, v256* powerPtr)
{
const int vectorLength = Length / 8;
for (var i = 0; i < vectorLength; i++)
{
var input = inputPtr[i];
var power = powerPtr[i];
var ln = new v256(0f);
var numMulti = X86.Avx.mm256_div_ps(X86.Avx.mm256_sub_ps(input, new v256(1f)),
X86.Avx.mm256_add_ps(input, new v256(1f)));
for (var j = 1; j <= Expansion; j++)
{
var numerator = numMulti;
for (var k = 1; k < 2 * j - 1; k++)
numerator = X86.Avx.mm256_mul_ps(numerator, numMulti);
var denominator = new v256(2f * j - 1f);
ln = X86.Avx.mm256_add_ps(ln, X86.Avx.mm256_div_ps(numerator, denominator));
}
ln = X86.Avx.mm256_mul_ps(ln, new v256(2f));
var exp = new v256(0f);
var multiplier = X86.Avx.mm256_mul_ps(ln, power);```
var sign = X86.Avx2.mm256_srai_epi32(multiplier, 31);
sign = X86.Avx2.mm256_mul_epi32(sign, new v256(2));
sign = X86.Avx2.mm256_add_epi32(sign, new v256(1));
sign = X86.Avx.mm256_cvtepi32_ps(sign);
multiplier = X86.Avx.mm256_mul_ps(multiplier, sign);
for (var j = 0; j <= Expansion * 2; j++)
{
var inverseMulti = new v256(1f);
for (var k = 0; k < j; k++)
inverseMulti = X86.Avx.mm256_mul_ps(inverseMulti, sign);
var numerator = new v256(1f);
for (var k = 0; k < j; k++)
numerator = X86.Avx.mm256_mul_ps(numerator, multiplier);
var denominator = new v256(1f);
for (var k = 2f; k <= j; k++)
denominator = X86.Avx.mm256_mul_ps(denominator, new v256(k));
var main = X86.Avx.mm256_div_ps(numerator, denominator);
main = X86.Avx.mm256_mul_ps(main, inverseMulti);
exp = X86.Avx.mm256_add_ps(exp, main);
}
outputPtr[i] = exp;
}```
so yea, absolute pain debugging that
Benchmark, the first number is math.pow() result, second is estimated
Anyways, if you done that before, focus first on converting that tutorial to a bursted job chain rather than diving into the deep end of DOTS.
yeah i mostly achieved that tutorial using DOTS in the past, but I had performance issues so didnt have it right, and 3d is complex so figured i could do a 2d :D. Ill try a few more days see if i get anywhere.
For any performance improvement, you must understand how the burst compiler works and all the tricks it requires. A correctly designed DOTS entity component structure requires a completely different way of thinking from standard OOS mono coding.
Taking a tutorial designed for mono scripts and converting it to DOTS correctly is honestly one of the most challenging tasks I think a programmer can do. Very low skill "floor" as DOTS is fairly forgiving in what can actually be computed but stratospheric skill ceiling as doing it correctly requires knowing the Entities source code inside and out.
the main bit I struggled with is, I can burst my entire game logic using the burstable stuff inside my arrays, but my world is split into 16x16 tiles each with own array. And I can burst within a given 16x tile, but never worked out how to access a neighbour tile well to calculate logic at boundarys.
then it got a bit OO'y
What are you doing per tile?
what are you computing?
not sure yet, but maybe want to try a sand simulation..very basic style
also 16 * 16 is divisible by 8, which is good, but it's 32, which is ouch, quite a bit.
https://www.youtube.com/watch?v=5Ka3tbbT-9E that kind of thing
Download and play with this simulation here: https://tinyurl.com/43dzu9r5
Java Repository: https://tinyurl.com/88ndcdez
C++ Port Repository (In Progress): https://tinyurl.com/a246r6pp
Links:
All the old Java Applets: https://androdome.com/Sand/
Exploring the Tech of Noita: https://www.youtube.com/watch?v=prXuyMCgbTc&t=322s
Conways Game of Life...
but i will use perlin to generate a random world, you could drop sand / water into
Right, that's even more complex than what we should start out with for DOTS.
I have made a simulation work before, but want it in an endless generating world 😄
not a predefined size grid
Something simple would be a flat sand surface and then clicking or just a random distribution at the start would smooth the surface out over time via diffusion.
Woah there, endless generation is extremely difficult. If you do not wish to implement a sphere of reality, that's the sort of design that gives people PhDs in comp sci.
honestly Burst is not structured properly for 2D or 3D arrays required for something like a sand simulation.
yeah my game logic uses 1d array, with functions to know the above/left/right cell
Burst works linearly along a 1D index and preloads linear data for vectorization along that index.
but i struggle at Chunkboundary, to get the cell
Even knowing above, left, and right breaks vectorization as those are random accesses.
What you want is a compute shader. Those are designed with 2D and 3D wavefronts in mind with proper index access.
And do you need chunks? What's wrong with just simulating everything singularly? And yea, check out compute shaders. They're basically Bursted Jobs with a little less flexability.
Maybe for a 2d game its ok, but for 3d game i use chunks, so mesh only exists for nearby chunks
so i only have about 4x TileMesh Gameopbjects at a time, that get dynamically created and destroyed
using data from my DynamicBuffers
as you scroll around
If you want mesh culling and modifications, yea. Focusing on GPU side calculations will be the best way forward.
unity tilemesh is limited size etc, so chunks of data there
the game iutself is simulated singularly
but in chunks hmm :S
i wanna make a basic minecraft in 2d ideally
but with some OxygenNotIncluded style machines or something
No, this only exists in the Unity Editor. How does one see what's in the builds?
Debug.LogError and it'll show up in your development console using build setting Develop (not release). Otherwise you need to code it yourself. Good luck.
Ah like that. You can always query entities and components as is depicted in this screenshot. Simply iterate through World.All to get a World-instance, which has EntityManager. From there, its trivial enough to start creating entity queries and running jobs, etc.
I wrote this bit for my own specialized 'entity inspector' within the editor. But the same idea could be done for development/release builds as well.
Note: EntityQueries have to be disposed though if created every update like this. Its something you dont have to think about when doing this from within a System.
When creating a query via EntityManager, EntityManager first looks to see if there is already an existing query and returns the best possible match. If it doesn't then it registers a new query and tracks it. Don't think you really need to dispose it 🤔
The Holy Grail of reusing your Old GameObject code game and adding DOTS/ECS levels without ever having to recode your player controller twice: https://youtu.be/GIEV14B20Pc
Sorry it's stupid rambly, and wait about 10-20 a few minutes for upload/processing on youtube.
I'll give you my really well done version in a week or two after www.starfightergeneral.com mmorpg launch.
Everyone who has old GameObject games can simply make DOTS/ECS games without starting from scratch, it is awesome.
The basic concept is this: After making entity off your player gameobject, keep gameobject in memory, do not render gameobject it and remove collider from game object
Then as you move gameobject with your ol player controller, Entity player just mimics it
In the basic idea: You force the entity player to be where the gameobject player's position/vel/angle is.
The advance idea: You read in the entities' velocity/angle/position
Then player controller adjusts it
And you send back the velocity/angle
for if you force position, you mess the collision engine