#archived-dots
1 messages ยท Page 206 of 1
Oh, when you say spawning from a gameobject prefab...I think you might be a bit mixed up there
Do you mean like - converting a gameobject to an entity at runtime?
Because that's something that should only happen once when your game starts
Preferably via conversion
Then you instantiate from that entity prefab
Oh right, okay, right. The process of spawning from a "GameObject prefab" (which I'm now putting in quotes) involves a conversion to entity anyway first, right?
I know there's optimizations under the hood that make that "GameObject prefab" never actually be a GameObject.
Yeah, that's expensive, but you would just do that once, then insantiating your entity prefab is no worse than just building the entity from code
Maybe faster
Gotcha, okay. So either way you're generally keeping entities around for the sole purpose of duplicating them.
Yup
And then yeah, in my case, I'd use a blob or a native data structure to keep track of which entities to duplicate when.
When you go through the typical conversion process you end up with a single entity with all your components and a Prefab component. Entities with a Prefab component are ignored by queries by default, so that gives you your prefab to instantiate from
Oh, I'm doing it wrong then, because I'm actually spawning the entity and seeing it.
The readme there explains it a bit
Basically you set up your gameobject prefab, reference it in your conversion script with IDeclareReferencedPrefab and when you call GetPrimaryEntity on your gameobject prefab inside your conversion script, that gives you your canonical prefab entity which you can assign to a component or whatever to be instantiated from later
Ah, right, okay, this was my problem.
I want to take a prefab like this, but programmatically create variants as prefab entities.
So from one Unity asset prefab (in the project directory) to multiple actual converted entity Prefabs, each with different values for their RenderMesh.
(One per sprite off of a sprite sheet, in my case.)
I can spawn actual entities like this, but I'm stuck trying to get them to just be prefabs instead of actually existing.
You can instantiate from the prefab, set the rendermesh on the new entity, then re-add the Prefab component, then you have a new prefab variant
If you add the Prefab component yourself it should be ignored by everything
Oh, seems simple enough.
private static void CreateSpritePrefabEntity(World world, Entity prefab, string name, Mesh mesh, Material material)
{
EntityManager entityManager = world.EntityManager;
Entity entity = entityManager.Instantiate(prefab);
entityManager.SetName(entity, name + "_SpritePrefab");
entityManager.SetSharedComponentData(entity, new RenderMesh
{
mesh = mesh,
material = material,
});
entityManager.AddComponent<Prefab>(entity);
}
Exactly
Cool, and then that can live in some native data structure, and I can pluck those out when I need to create those sprites. Awesome.
Thank you for explaining this to me, been very helpful.
Anyone messed with SubScenes in the Editor?
I want to have a editor tool that finds a bunch of prefabs, adds them to a subscene and converts them
Then i can use the world as i like and dispose when done
I figure i can use the older Conversion APIs, do they do the same things as subscenes ie the custom conversion systems?
Trying to track down the cause of a crash a user reported to me. The log seem to indicate the problem is in the allocation of a NativeArray, which would mean it's one or both of these NativeArrays that have been used once or more than once then disposed of just prior to running a compute shader:
computeShader.Dispatch(kernelHandle, width / 8, height / 8, depth / 8);
nearestColoursComputeBuffer.GetData(nearestColoursOut);
nearestAtomComputeBuffer.GetData(nearestAtomDataOut);
NearestAtomsToGridPointsArray = nearestAtomDataOut;
NearestColoursToGridPointsArray = nearestColoursOut;
NearestAtomArray = new NativeArray<NearestAtomsToGridPoint>(NearestAtomsToGridPointsArray, Allocator.Persistent);
NearestColoursArray = new NativeArray<NearestAtomsToGridPoint>(NearestColoursToGridPointsArray, Allocator.Persistent);
nearestAtomComputeBuffer.Dispose();
nearestColoursComputeBuffer.Dispose();
the log:
I'm unclear why this crash could have happened as I've been very careful to manage the native arrays
Yeah that's the way to do it. I suggested inject mode because you said you didn't want to write authoring stuff and in my mind it would keep the object components and make them available in ECS. At least that's what I thought back when I tried with a particle system. Looks like my memory fails me, maybe I had to write a conversion system to make it work ๐ค . Now I need to review the conversion part, maybe I went through it too quickly and mixed things up ๐
Anyway glad you achieved your end result ๐ And yeah that's a great blog
Hi guys! Am I the only one who missing a "Go from game Object to Entity" feature?
it's called "Authoring" if that helps the searches!
I want to click on my view gameObject in a scene and somehow navigate to corresponding entity in EntityDebugger.
Sorry, I generate all my entities from plain old data rather than anything from the Inspector or GO-land, I'm sure others can help more.
if there was an API for selecting an entity in a debugger... Something like:
#if UNITY_EDITOR
Unity.Entities.Debugger.SelectEntity(entity);
#endif
It would be super helpful
having such an API, it would be easy to make an MonoBehavior that tracks the click and selects the desired entity
Unfortunately that isn't implemented yet. I hear there are plans for it though.
I am trying to extend Addressables to use it with entities. Anybody has experience with that? I currently hit a roadblock regarding reference counting: https://forum.unity.com/threads/entity-conversion-with-custom-operation.1073135/
I don't suppose anyone know why I'm getting this error NullReferenceException: Object reference not set to an instance of an object from this code if (!World.DefaultGameObjectInjectionWorld.IsCreated) return;
the whole point of that code is to make sure there isn't a null reference it's not supposed to need one ๐
World.IsCreated is not the same as World.DefaultGameObjectInjectionWorld. The latter could be a world, but it may not have been created yet, as it could be deferred. You can just check against null directly, and probably also check IsCreated
you can't do world.IsCreated
Why not?
it doesn't let me, and how would it know which world you could have several
Right, I was thinking on a specific instance
So you would have to do if (World.DefaultGameObjectInjection != null && !World.DefaultGameObjectInjectionWorld.IsCreated) or something like that
its weird because that check works in another older scene but just not in this new scene
Probably because of some race condition
Race condition here being loading time
So in your old scene you were just lucky it worked
there's no race conditions because its running in the edtior in a gizmos code thing
The world could still not be created though, I'm not sure why that would have anything to do with it
that's why I have to check that the world exists so that the code only runs on play because otherwise it runs in editor and I get errors
Then just do what I just told you, I don't see the problem
Same error?
yep
What does the code look like now?
if (!World.DefaultGameObjectInjectionWorld.IsCreated && World.DefaultGameObjectInjectionWorld == null) return;
You have to do the null check first, and you have to turn it into an 'or' instead of 'and'.
The reason is that you will still try to access the world before you check if it's null, so if it's null you'll get the error
And the reason why you want to turn it into an 'or' is because you don't want that code to run if it's null, or if it's not created yet
awesome, that works, thanks
Is there official support for ECS particles, or I need to go hybrid with it?
hybrid unfortunately for now
kind of annoying as vfxgraph doesnt batch calls, so you get a performance hit with lots of similar emitters
I though VFX graph was quite performant ๐ฆ
well.. I already had a particle manager for GameObject handling of particles... I guess I will try making a ECS bridge for it using that event system thing
it does handle like millions of particles from a particular emitter easily, but in my case where i just have a handful of particles for bullet sparks, and then potentially a hundred of those emitters separately, it sorta is a perf hit. at least its on the product board as being addressed(at some point)
Is there a way to have a single emitter and give it your hit locations?
(i havnt used VFX Graph yet)
yeah last time i looked into arrays it wasnt implemented, not sure what the status is now
oh well
something to hope will be implemented in the future ๐
Anyone tried storing a burst FunctionPointer in ComponentData OR a BufferElement?
Hi is anybody good with DOTS audio?
I just realized unity 2020 LTS was out. does that mean there's no chance we get enable/disable component on 2020? I don't want to go through unity upgrade hell again xd
@odd ridge Pretty sure i read somewhere that the next version of Entities (0.18) will depend on 2021 (but cant remember exact version)
alright, no enable/disable for me that means xd
what are you doing thats so painful to update?
(so i can advoid it ๐ )
also they said enabled bits wont be complete in the next version anyway (https://forum.unity.com/threads/entities-0-17-changelog.1020202/page-2#post-6774380)
also i cant find the message that said 0.18 will depend on 2021, maybe i made that up sorry :/
But if enabled still wont land in 0.18 then seems higher chance that 0.19 will end up depending on 2021
it's just that I have a LOT of tag remove/add every frame and I would get stutters every now and then because of the structure changes
Anyone know where I would go to report some code that doesn't compile in Burst, but probably should? Is there an issue tracker specifically for DOTS/Burst stuff?
@odd ridge I've seen some advice to put a Enabled flag into your components and edit those instead
as that would be very easy to update to the new Enabled/Disabled bits when its finally out
@vivid lotus Use the normal bug reporting, and maybe make a fourm post
@odd ridge but it really depends on what your doing, as there a good cases to use tags
Anyone have an example of a JobComponentSystem that uses an ECB? I can find code examples of one or the other, but not both combined.
Not sure how to go about passing the ECB into the job to be used.
Or are JobComponentSystems out of style now? I see IJobForEach is deprecated, apparently.
There's an example in the manual
And yeah you should only be using SystemBase now, not ComponentSystem or JobComponentSystem
Does it make sense to implement some sort of progress/progressbar as an entity ? It should float somewhere under or beneath a mob/character to show the progress of its current task. Like chopping down trees. So it actually has an location inside the world. And it also has multiple conditions when the progressbar should dissappear or stop the progress. Like when the mob moves away during chopping. So i think its actually worth being an entity. Or ?
@craggy vault Store a reference... just have some component that stores like this : PositionReference{ Entity b } on A and loop over them to acess components of B.
@craggy vault Use GetComponent<Translation>(EntityB) to get the position
yeah I think that makes sense, what are you comparing it to doing instead?
I imagine you could do progressbar as component, and have a system iterate over that for rendering
but i think using separate render entities makes a lot of sense, and means your chunks will be cleaner (can just have 1 chunk full of progressbars regardless of what components the target has)
@hollow sorrel Thanks, i already implemented a little prototype and it seems to work fine ^^ Im just always a little... undecided if it comes to decide between using entities or using oop/structs. I just cant find a good guideline for that :/ Actually its possible to implement everything as entities, but not everything should be an entity.
yeah that's fair, implementing it with just structs outside entities/components would be not bad either, not sure when to do which
guideline I've been trying to follow is if it's game data then it belongs as entity, because ideally I think you should be able to serialize your world and deserialize, and your game should still work as if nothing happened
but when it comes to rendering it becomes more fuzzy, that doesn't need to be part of game data
@hollow sorrel That actually seems like a pretty good guideline ^^ But whats game data in your case ? Everything that has a "hard coded" structure like a buff for example : Buff{ name, effect, duration } ? Or everything that has no "logic" ? If so features could vary a lot... for example, if a game has items without any logic on them... they would be game data. But if they have logic ( Some cool stuff happening when used, or something that gets executed every frame ), then they would be an entity ?
imo anything that is needed to reconstruct your game from a serialized state
so logic, mobs, etc
assets and static data might be an exception, so for buffs you could just have your entities have an id to a buff type stored in a table somewhere, and that table is not part of ecs (could just be an array constructed at startup, or a blobasset/scriptableobject etc)
but the actual remaining/current duration would be stored as part of an entity since that'd be game data
so when it comes to rendering progress bars, if you restore your game state, you could just recalculate the progress and create/display a new progressbar, it doesn't need to be serialized since it can be recreated from existing game state
so in those cases where it's not really part of game state, then you have the choice of making it an entity anyway or not
basically i'd think of the game as a deterministic simulation, even if it's not deterministic, i just mean architecture wise
Is there a way in dots to prevent hierarchy conversion? What i want is to be able to have nested gameobjects in my prefab, which are convertable and linked by parent gameobject (entity) but not included to his hierarchy after conversion (no parent, no including to LinkedEnityGroup, no including to Child).
do it manually yourself? maybe using something like a GameobjectConversionSystem
how to read entity data from mono behavior ?
found it :
var EM = World.DefaultGameObjectInjectionWorld.EntityManager;
EM.GetComponentData<Translation>( PlayerA.ENT );
// where ENT is set manualy via GameObjectConversionSystem
As i understand it will completely stop converting
think i misunderstood, not sure if theres something only to stop the hierarchy. Could always remove it from the hierarchy with another system?
I think about to write late GameObjectConversionSystem which will get all gameobject's tranforms (only which i want to not add transfrom components) and remove LTW and others, and also ask if it is nested HasComponent<Parent> and then exclude it from parent.
I don't suppose anyone knows simple way to draw wire cubes and lines in game mode with hybrid renderer
I'm trying to use Gizmos.Draw... etc and it seems it will take about 20 mins to draw a frame
you can use ALINE but its a paid asset
its by the guy who made the astarpathfindingproject
works in editor and game, I quite like it ๐
cool thanks, I will definitely buy it, that stuff is really useful
Through the EntityManager of your world or schedule it for a CommandBuffer
systembase doesnt change how entities are deleted from componentsystems or jobcomponentsystems.
When reloading the scene it seems to leave all of entity data and rendering. Is there a command to flush it or should I be keeping track and disposing of all the entities manually to recreate or reset the world?
dont think theres anything builtin to handle scene changes yet ๐ฆ
cool thanks for the info
If you have a lot of entity pairs (A, B), where an entity type B needs to read information from its linked entity of type A every frame, and there's a lot of both, is there a good way to batch that information transfer? I feel like just looping over every B and having it look up its A one by one would be cache miss city when everything is potentially in different places or different chunks entirely.
Are entity pairs components an option for you ? Relationship : IComponentData {Entity entityA; Entity entityB;}
Possibly. To ground it a little, in this example I'm thinking about splitting the gameplay entity from the visual representation entity, and I need to have the visual representation entity receive the world position from the gameplay entity.
But they could all be in arbitrary places in memory relative to one another, and the visual representation entities may be created/destroyed depending on how far the gameplay entity is from the camera.
I'm trying to figure out how best to optimize the position transfer from gameplay entity to representation entity, in big batches, every frame.
For camera culling you can look SharedComponentDatas, to group them in chinks
chunks*
I can do that. My situation is complicated because the position of the gameplay entities can't be represented by a normal transform (the world is too big for a traditional float3).
So I can't just, for example, parent the representation entity to the gameplay entity.
I need to do a transformation in the process.
So I have to have a component on the representation entity that points to the gameplay entity, and is responsible for converting the gameplay entity's position into something renderable (the camera never actually moves).
But since there's potentially lots of represented entities, I want to make that transformation as optimal as possible, which means avoiding caches misses as I can.
Yeah I see, floating point precision. I will face the same problem soon. I think I'll try to hack my way with subscene "chunks" (not ECS chunks) streaming.
Yeah, my game positions are double-based.
So I need to transform the game positions into camera-relative renderable float positions, if that gameplay entity is close enough to render at all.
For the link and transform part... ๐ค maybe I'd try a one-way link yeah. Maybe
That's what I'm thinking yeah.
The render entity just stores the entity it represents. If it exists, it draws, if not, then no work.
Sounds like the first idea at least.
But that means each pass each render entity needs to random-access the gameplay entity it represents, which could be anywhere in any chunk basically.
Which is cache miss city.
Just wondering if anyone has wrestled with this before.
What I could do is move gameplay entities that have a representation to a dedicated chunk, and make sure it has the same index in its chunk that the representation entity has in its chunk. Then that's minimum possible cache misses I think.
But that causes fragmentation in other ways, and also means I can't use chunks to optimize those entities any other way, either.
Yeah I'd go subscenes chunks octree style as my first try, ignore anything else than current + neighbors
Keep in mind chunks are not infinite anyway, you don't have only one of each archetype. Entities will span multiples chunks anyway
Yeah I'm not well versed in chunk manipulation in DOTS yet.
in the entity debugger you can see how much space they take
And yeah I'd prefer to use them for spatial decomposition instead.
The other option is to use some sort of intermediate data structure, where I iterate over every gameplay entity that has a representation (via tag, I guess?), and have it write its position to some structure, and then have the representation entities read it.
But that seems wasteful.
another option is, each time you iterate through a gameplay entity, you push it on the front row of a cache collection
you can control size of the cache
Mostly I'm trying to make sure that I'm reading data sequentially with lots of locality, so I don't get hardware cache misses.
I don't see if there is a better way than spatial partitioning at the moment
Someone is/has concerted most of dots to use doubles instead of floats
Specifically core transform systems and physics
I think rendering was a issue but if your using hdrp there's some sort of camera relative rendering you can use
I'm not too worried about that part.
@vivid lotus i'd copy the data you need to the render entity (position etc), which is cache miss city but you'd only have to do it once per frame and can then reuse that for whatever other render systems you have
since then you can do whatever rest you need to do on the render entity with proper cache linearity
It's the transfer of gameplay entity position to render entity position every frame that I want to optimize most.
i think cache misses when dealing with paired data is inevitable, but you can def minimize doing it
Hm, yeah, you're probably right. Even if I did have an intermediate data structure I'd have to contend with concurrency write issues.
I've missed part of the conversation but has a custom renderer been suggested? Using the graphics.draw .. apis?
I was thinking a two phase pass where I have a big list/vector of "mailboxes" basically for this data, and both the gameplay entity and the render entity agree on a slot. Then I pass over all the gameplay entities and have each write to its slot, and then have the render entities read their respective slots. Then the data would all be packed at least, but there's still cache misses to be had there, and it's a lot of extra (hard to parallelize) work.
I'm not too concerned about drawing. I have representation entities that work fine, I just need them to know where to be.
I could skip the representation entities entirely but then I run into issues of having to store reference data (meshes, materials) in the gameplay entities.
And I'm not sure how parallel-friendly the graphics APIs are from the request-making side.
not sure the mailbox thing is worth the effort, there's no guarantee your render entities in your list ends up the same as your archetype iterations, and if you end up trying to do that then that'd prob cost more perf overall
Yeah.
What I could do is move gameplay entities that have a representation to a dedicated chunk, and make sure it has the same index in its chunk that the representation entity has in its chunk.
this might technically work but defeats the purpose of having separate render entities imo
Also yeah.
Manually drawing could open some options. If I bypass this process entirely, what I could instead do is iterate over every gameplay entity, decide if it needs to be drawn, and if so, queue up all the draw information for it in a ConcurrentQueue (or some other parallel-producer structure) and then resolve that.
The complication again is that I need to convert the coordinates to be camera-relative, since I can't move the camera out to low-precision land.
It isn't so much about getting DOTS to use doubles, it's about the camera, which is still a Unity GameObject with a float-based transform.
So my plan is to just leave it at (0, 0, 0) and move everything else instead.
yea you could do that regardless tho, like a culling system that does the coordinate conversion and checks if it's in camera view, and if so marks it for rendering
and if not marked then don't even need to create a render mirror entity for it
Yeah that was what I was originally thinking. Sweep all the gameplay entities, see if they're close enough to make render entities for.
Or if they have render entities and have since moved away, so they need to be destroyed.
yeah
My issue with manually drawing is that I'd probably lose out on instancing and lots of optimizations there, unless I did that all myself.
i think the separate render entities thing is independent of however you choose to render
i'm doing the separate render entities + copying data, and then manually drawing, but could just as easily swap out the manual drawing for hybrid if wanted
Interesting. Mind if I ask why that design choice? For me it seems like I'd want either/or. That is, either manually draw and don't bother with distinct render entities, or use render entities as a conceit to take advantage of the hybrid renderer.
trying to make a deterministic + rollback game, but even without that i'd prob still do it this way
there's a lot of benefits to having render entities, for example your archetype chunks are much cleaner (instead of having 10 AI with slightly different components spread across different chunks, they'd just be split on the gameplay side, they're all the same on the render side so fit in 1 chunk there and have good cache linearity)
and imo it's much easier to think about the game architecture being split this way, because your game still plays exactly the same even with a black screen and 0 rendering, they're basically separate worlds
actually in my case they're literally in separate ecs Worlds
for automated testing, you could add a bunch of prerecorded input data into your simulation and play it at 500x speed and query some test results at the end of it, and not have to worry about rendering since you don't need that during tests
That makes sense. I have a ton of questions about that because that's super interesting but I don't want to get too sidetracked. Maybe another day. That said, for your manual drawing, is there a lot of work on that sort of thing out there for DOTS? I figure this is a common use case. Are you batching and instancing and all of that good stuff?
nah atm i haven't gone too deep into that side yet, current implementation is very naive and inefficient
one of big reasons i went this route in the beginning is because i didn't like how hybrid rendering has 1 chunk per mesh, i'd prob end up with a lot of mostly empty chunks
overall i'm sure hybrid rendering is much more efficient than mine with batching and all that good stuff, but now i don't have to deal with unity's shit (or less at least) so that's reason enough for me
Hah, fair enough. I've never used Unity's explicit draw tools so I'd have some digging to do to get started, I suppose.
Which render pipeline are you using, or does it even matter?
atm just the old legacy built-in, which hybrid renderer doesn't support
and yea i don't know too much about the drawing stuff either tbh, i've just started using Graphics.DrawMesh for now and worry about the rest later when it becomes a problem
i know hybrid renderer internally uses BatchRendererGroups which is a relatively new thing but no idea how that works
actually not sure if that's what it was called, but they don't use Graphics.stuff at least
There's CommandBuffer.DrawMesh, I believe.
yea that's a different thing too i think
not sure if built-in rendering supports those
but yea if you wanted to go the Graphics.DrawMesh route, that's trivial to set up
pass in your mesh, pass in your ltw, pass in your material
pewpew now there's stuff on screen
it's the fancy optimization stuff where it gets hard
Yeah, that's what I'm worried about if I go the homegrown route.
Looking into BatchRendererGroup. This is definitely a rabbit hole.
yea that's fair, i think if hybrid renderer works for you it's good to go with that
i might switch to it some time too, just for now it seems like a lot of complexity that i don't wanna worry about yet
I don't know, actually after this I'm leaning away from it.
This might be doable manually.
what kind of game are you making
Think something along the lines of 2D RTS, but at scale.
2D, trying to keep it simple for now.
(He says, while diving into DOTS and manual rendering.)
Perfect thing for ECS, but certainly comes with complications.
yea
Since you're doing rollback (I assume for multiplayer), are you using fixed-point?
what's nice is unity's Sprite assets have vertices data already that you can use to make meshes out of at runtime
i would imagine that's how the default SpriteRenderer also works, not sure tho
I actually don't do that. I just make mesh squares.
I have a thing that takes in a sprite sheet and spits out squares with the UVs set up.
nah not fixed-point, hoping by the time i start doing actual multiplayer burst will be crossplatform deterministic, no idea if it will but if not i'll prob just inflict pain on myself and convert to fixedpoint when it comes to it
Granted, Unity's approach is probably better since it uses vertex as well as fragment on the GPU, whereas mine is mostly fragment.
yeah quads works too, not sure which way is better
I want to be able to grab sprite sheets out of Resources.Load for modding, so I can't rely on Unity's sprite tools.
oo fancyy
So, thinking about it, I've still got all the same problems actually.
I don't think there's a good way for a parallelized system to write out all the batch render information safely in parallel.
Unless there's like a NativeConcurrentQueue or something.
Pretty sure there is a native queue to concurrent
Or it supports concurrent, can't remember which
Oh, guess there is, huh.
You could also look at native streams, they are built for the many producer to many/one consumer
But are kinda painful to use
Well so the issue is that I would have to have each game entity spit out its rendering information, and I would then need to pack it into these arrays (being careful to stay under 1023 per).
Also highly agree with @hollow sorrel saying to split up your data/worlds into simulation and rendering
I agree with that, but I may not need any entities for rendering.
But would focus on poc first then redo it later
I'm curious to see how to make it work first and foremost.
I'm also building a networking stack which is built on the same idea, spit server/clients, and using curves to playback everything. Basically making clients a "dumb" video player
Yup definitely start with getting your core gameplay loop working
forgot nativestreams exist, that could be a good idea as well (but agreed on the make it work first redo later)
I'm actually less concerned with that. I'm interested in the tech right now. The game is mostly an excuse to learn it for the time being.
Yea building all this "tech" kinda killed my poc. As I had to keep going back and changing things and eventually spent most of my time there instead of either getting the poc happy or finishing the tech stuff
That doesn't bother me. I always come out the other end with more tricks up my sleeve.
But that's all beside the point.
Exactly, I learnt tons and now have really good ideas on how to do rts networking and modding
I guess I need to decide if all the random access of representation-entity reading gameplay-entity is worse, or if doing the batch rendering via a queue or stream or something (and sorting out which goes to which batch) is more expensive.
I honestly found native streams more work then they were worth. But when I start stress testing they might be a better idea
In reality the rendering entity is pretty superfluous, especially if all of its relevant state is changing every frame.
I found the break between ecs data, into native container, processing on those containers and back again to other entities frustrating
In my case I have a finite (but indeterminate) set of possible sprites, each with one unique mesh and one (potentially reused) material, plus some overridden material properties for things like team colors and such.
So each gameplay entity maps to exactly one of those.
The gameplay entity doesn't need to provide, or know, more than a couple of index values.
The rest would just be lookup tables into the assets.
So iterate over all the gameplay entities in parallel, determine if they're worth even trying to draw, if so, spit out into a stream their lookup table data, and then a separate pass reads that stream and packs everything into batches, essentially.
The issue is that that latter part would be very difficult to parallelize.
ohyea you'd have to map it back so would be a buncha random lookups anyway right
Sorta.
I could prepare one batch group for every sprite, since I know them all ahead of time (they're loaded at startup). And then if a gameplay entity wants to draw, it knows its sprite ID is 342, so that goes into the concurrent stream along with its position (and any additional) information during the preparation pass. Then a process reads that stream and puts that info into the prepared 342 batch.
There's two complications. One is that that stream reading process would be difficult to make parallel since the batch stuff doesn't look like it's set up for that. The second is those batches have a limit of 1023, so I might need to add additional same-batches for a given sprite.
that sounds like an absolute pain to work with
Could be. I don't know offhand.
It's really just two systems. The ECS system that reads the drawable gameplay entities and ushers their information into the buffer, and then the other system (I guess just a MonoBehaviour?) that reads that buffer and gets everything into batches.
Ah, wait, okay.
This is probably why the HybridRenderer uses a SharedComponent for the MeshRenderer.
To pre-group batches at the chunk level.
Burst gives warning about exceptions while building:
An exception was thrown from a function without the correct [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] guard. Exceptions only work in the editor and so should be only thrown in a function protected by this guard
and they originate fromcome.unity.collections.
Do I need to worry about them?
So, I have it... kinda? working: https://gist.github.com/recatek/fdaa7cecbe6a8c453de90217a56ed52e, if you're interested @hollow sorrel @ocean tundra
On the collection task I can't ScheduleParallel unfortunately, since NativeList doesn't let you Add() in a parallel write context. Makes it sort of a waste to make it a job, but I'm gonna keep playing with that aspect of it.
Uh, does NativeMultiHashMap<TKey, TValue>.Concurrent not exist anymore?
Ok so many comments but base looks good
Native collections, are better to create in on create and keep persistent
With burst is default, don't need it
Never complete a job handle if you can advoid it
Yeah, that's placeholder for now until I can chain a followup job.
Still trying to figure out how to organize it all.
With schedule you don't
Need to pass in handles and store them
By default Dependancy will be tracked for you
It's called AsParallelWriter now
You can just use World when inside a system
Don't need static access to world.def....
Same with entity manager
It exists as a base property of systembase
Ah, that was code I just ported from a MonoBehaviour, but good to know.
What if you have multiple worlds?
Is Matrix4x4.Translate the new math stuff or old?
Your systems will exist in every world
By default, but you can change that with ICustomBootstrap
It's old, but it needs to be old because that's what BatchRendererGroup wants.
Hmm that sucks, means you'll miss out on some burst magic
With respect to pre-allocating native containers, when would you clear them before use? Couldn't a job still be running during the next frame's OnUpdate()?
Every OnUpdate(), I need to clear an array (or now, a MultiHashMap), and refill and use it.
That's why I was allocating with TempJob.
Though I'm not sure when you dispose when you do that.
It won't let you clear a container if it's being used in a job before the job gets Complete()ed
Clearing a NativeMultiHashMap is extremely expensive by the way
If it's large
So it's better to Allocator.TempJob?
NativeMultiHashMap is its own thing, AFAICT.
How do you get a native container to dispose once you're done when you're using Entities.ForEach.ScheduleParallel?
There isn't that thing like in regular jobs where you can mark a field to dispose.
NativeStream may be better depending on what you're trying to do
I'm trying to organize and bin.
So I need to separate by index.
Essentially I have a whole bunch of entities with a label from 0..n and I want to get them each into batches for rendering.
Pass in Dependency to Dispose
Like... .ScheduleParallel(myArray.Dispose)?
Or a new job?
Oh wait.
Gotcha, I see now.
Hm, doesn't like this either
NativeMultiHashMap<int, Matrix4x4> binnedMatrices = new NativeMultiHashMap<int, Matrix4x4>(100, Allocator.TempJob);
var pleaseJustLetMeWrite = binnedMatrices.AsParallelWriter();
JobHandle gatherAndBin =
Entities
.WithName("GatherAndBin")
.ForEach((int entityInQueryIndex, in RenderPositionComponent renderPositionComponent) =>
{
Matrix4x4 matrix = Matrix4x4.Translate((Vector2)renderPositionComponent.RenderPosition);
pleaseJustLetMeWrite.Add(renderPositionComponent.SpriteIndex, matrix);
}).ScheduleParallel(default);
binnedMatrices.Dispose(gatherAndBin);
So the only way to get a handle out of ScheduleParallel is to feed it default for dependencies, but that strikes me as wrong. Is there something else I should be feeding in there?
You should be passing in Dependency to your job
Try this. Dependancy
Oh. That makes sense.
Perfect, alright, that all works.
I would kill for nested native containers right now.
You can do it with unsafe containers
Apparently it's pretty bad for performance though
Yeah I've been trying to avoid that due to risk as well.
Think I've thought of a faster way to gather the data for your batchs
Use a entity query to component data array
And renturprate (dam phone spelling) into your vector 2
Will still need to matrix it
I'm not familiar with this. Does it just spit out all the components as a big array?
So my concern with that is most entities will be offscreen, so I'd like to filter them in-place before allocating space for them.
And renturprate (sp??) Allows you to turn one struct to another if they have the same data layout (eg component has a single sub struct)
I did consider putting them all just in a list, and then sorting by type, and then slicing.
What I would need, ideally, is the ability to sort several arrays in parallel treating one as the key and the rest just as data.
The culling should probably be a separate job
In my case the culling is really, really easy.
Where you add/remove a visable tag
Hm, I could do it in three passes maybe.
Gather the components (parallel), sort (not parallel), and then convert (parallel).
There's IJobNativeMultiHashMapMergedSharedKeyIndices maybe?
Or no, that's gone now apparently.
It is really hard to bin heterogeneous types efficiently in Unity jobs, huh.
NativeStream lets you write arbitrary data/types to any index
Just as bytes, right?
Essentially my issue is, I have 1..n batches, each with a NativeArray<Matrix4x4> and Count that I need to populate. I've created one batch per type of sprite.
And then in the ECS I have just a bag of unsorted, undivided entities, each with an index value of which sprite (and thus, which batch) it should go into for rendering, as well as its position.
And I'm trying to find the most parallel and efficient way to get them to the right batches.
The fact that I can't nest native containers means I can't just do something like NativeArray<NativeQueue<Matrix4x4>>.
I could do a queue, or a stream, or a query, but they would come out in an arbitrary order because I want to do this as ScheduleParallel.
Could using a shared component help, as that would sort your entities into chucks with matching values
So you could use that for your batch id
I'm trying to avoid chunk coercion because I want to use that for spatial decomposition for queries.
Can't an entity only be in one chunk at a time?
Yea but your chunks would get smaller
Your chunk "key" would be something like batch id, int 2 positive
Yeah, in that case I'd like to reserve chunk logic for distance queries and the like.
Hmmm my gut feeling is using chunks for spacial stuff might be a mistake
But no real evedince for it
Maybe checkout what physics does
I believe internally it keeps some sort of spatial tree
So far I'm thinking
- Filter entities and populate an unordered queue from a ScheduleParallel
- Convert the queue to an array
- Sort the array
- Figure out the slices and send them off to batches
It's simple enough to turn off the actual physics work and use it as a pure spatial query system
But 3 is tricky.
Well native arrays have custom sort methods
Think you could just call that from a job
They do, but they don't have multi-collection sorting.
See if I sort, I need a key. That means the key has to be in the struct.
So then I have an array of SomeStruct, not Matrix4x4, which means after they're sorted I can't just direct slice into the batches.
(The batches take a NativeArray<Matrix4x4>)
Ideally I would have two arrays, NativeArray<Matrix4x4> and NativeArray<int> and I would sort them both in lockstep using the values of the latter as a guide.
Then ditch the int array and just slice up the Matrix array so I can very efficiently copy it into the batches.
Have you considered entity slicing?
In what sense?
Using a master entity with most gamepad stuff on it, child with your rendering stuff, your child could use chucks to sort based on batch id. Parent is your spatial stuff
That would just bring it back full circle. I'm trying to avoid having to have a separate child render entity.
That's how this whole thing started in the first place.
Kinda sounds like premature optimization :p without testing it it's hard to say if the random read to copy data will be slow or not
My curve based network relise on the same concept, each frame I check for changes, and if there is a change I copy it
Eh, I'm not afraid of premature optimization. As I said, I'm doing this to explore the tech.
If I was shipping on a deadline it would be one thing, but this isn't paying my bills, it's just to learn.
There's a ton of ways to optimize too
There are, but in this case I want to take advantage of parallelism and locality of data.
Yea I get that
Which are two very reliable ways to optimize.
The issue is mostly in the limitations of the native containers in this case.
But would this complex sorting bit be slower or faster then just copying 1 float2?:p
Depends on when the copy occurs.
The issue is that I need to know the count of instances in the batch ahead of time.
Before I copy the matrices into the array.
Based on how the batch scheduler works.
You need to declare the count and then populate.
If your using chucks and entity querys you could call get entity count
I'm trying to avoid using chunks for this.
There will be other, expensive things I'll need to rely on chunks for. I don't think this is it.
Also another trick I've learnt, is not everything needs to happen instantly on the same frame, if theres a single frame delay from a new unit spawning/deleting is that a issue?
No but I don't see how that applies in this case?
And I absolutely do want each frame to draw the entity in the correct spot without delay.
You could have a 2nd job that updates your counts, it's output data is used in the next frame
I'll likely have several dependent jobs.
Yup
It's just a matter of how I can make the most out of parallelizing those jobs.
Just throwing ideas out there :p
Don't really have answers, just hoping to help spark some good ones
It's tricky. I don't think any of the right ways are possible with how the containers work, without going to unsafe and untyped containers.
Oh yeah, I appreciate that for sure.
Also they deprecated/removed two of the things that could have helped me here, NativeArrayFullSOA, and IJobNativeMultiHashMapMergedSharedKeyIndices 
Usually when they remove something in dots there's a better way of doing it
These both just seem to have been very obscure and underused.
So to rephrase the issue
You have entitys with a batch id(sprite Id) and position (a matrix)
You need to break that out into a list of the matrix's per each batch id
?
Pretty much, yeah.
Awesome
The position as stored on the entity isn't actually a matrix, but it can easily be converted to one.
And the challenge is to do this without chunk manipulation, and without additional entities.
The result has to be one native array per sprite ID, and a count.
Uh, can we? I don't know.
If the answer is yes, then I'm thinking native streams is the best option
Wait no
:(
Native streams would need the data sorted by batch id first
I thought about having a stream where you have a consumer job for each sprite ID that packs its own array, but as the number of sprite IDs grows you're going to have a ton of thread churn.
The consumer doesn't have to be many threads/jobs
Could be a single
But it won't work
You can only begin/end for each index (batch id) 1ce per frame
Well the core problem is you can't have second-order addressing.
Because you can't have nested containers.
2nd order?
NativeArray<int> - first order[]
NativeArray<NativeArray<int>> - second order[][]
If I could do second order indexing in jobs this would be easy.
Just have an array of queues and feed each queue then convert to arrays and load into the batch..
Yea my tricky for that was code gen
My multiplayer kit has a "queue" per player, and the game dev sets max number of players
So I gen out a container with 100s of native queues and things
But your batchs (sprites) are dynamic
Hmm ok what about dynamic buffers?
Attached to a entity
So 1 entity per sprite, with a dynamic buffers of positions
Your entities "add" them selfs into the buffet
And tracks their index within
So they update the same index next frame somehow
So the issue with entities referencing other entities is that it's all random access.
That's tons of cache misses, which is part of what I'm trying to avoid.
Well, a big part of ECS is data locality in memory, so I'm trying to play to that strength as best I can.
Your output would be in your required formats (buffers have a as array method)
It's simple to debug/test/understand
I think it would have similar parallelism issues.
Also you only have to update when data changes
Depends
I think cache misses are ok if you focus on keeping them low
Like watching for data changes
And doing things per chunk instead of per entity
I'm assuming that most entities will move most of the time in the sim side.
I'm pretty committed to not relying on chunks for this.
But there's huge amounts of static things in games
No I meant chunk based jobs
Instead of entities.foreach
For each is great to use
But slower then down chunk based jobs
The best is to use ScheduleParallel if I can.
The more I can do in that context, or equivalent job contexts, the better.
Yea you schedule parallel on chunk jobs
How can I use a SetChangedVersionFilter in a MonoBehaviour? I have a method I want to run only if a component changes. Creating a query with CreateEntityQuery and applying the filter doesn't do anything. (CalculateChunkCount is never 0) But if I do the same thing in a SystemBase it works as expected.
How would you implement server/client communication ? My game server is java based and runs on an ecs and my client is unity based with dots/ecs. Not all server entities are represented in the client. For example only trees, mobs, items on the ground are represented on the client.
Should i serialize those entities on tje server and deserialize them on the client to construct unity ecs-entities ? Should i fire single events like : position_updated from the client to the server ? Whats the common workflow for this ?
So either sending the whole entity from the server to the client to construct the "same" entity... Then send component updates when something changes...
Or instead only send events like, oh a entity of type xy spanwned. Oh the entity moved to that position.
Both waya are actually quite interessting.
That doesn't sound right, it sounds like you're accessing the component as read/write in the monobehavior
That was my first thought as well, but I'm doing nothing with it only CalculateChunkCount, it's also a brand new comp on a brand new entity, so it's completely isolated from other systems. I think it's something related to CreateEntityQuery (which I cache) but I can't wrap my head around it.
Can you show the monobehavior? Post it to hatebin if it's too large
Yeah, here's all there is https://hatebin.com/brqlkopbbp
This logs 1 all the time, but doing the same in SystemBase (Using GetEntityQuery) will return 1 for 1 frame and then always 0, as expected.
question, not a DOTS question but:
is the Default Unity Rigidbody physics multithreaded?
Just tested it and you're right. Seems like a bug to me
But maybe I'm missing something
I worked around it by having my SystemBase invoke a delegate in a Run job that I can listen to from my MonoBehaviour.
Is there a chart somewhere or some documentation about when systems update relative to MonoBehaviours? Or a way to control the ordering?
Havenโt been able to find anything about it.
Trying to delay a systemโs OnCreate until some MonoBehaviours have done Awake and Start.
What is the difference between ComponentSystem and SystemBase ?
ComponentSystem is what came before SystemBase, is mainthread only and shouldnt be used over SystemBase
it's in its way to deprecation ?
yeah
JobComponentSystem was ComponentSystem but for multithreading, it too is deprecated in favour of SystemBase
alright then thank you
postupdatecommands is just an entity command buffer, you can do it yourself like
var postUpdateCommands = new EntityCommandBuffer(Allocator.Temp);|
//foreach yadayada
postUpdateCommands.Playback(EntityManager);
postUpdateCommands.Dispose();
is it better than using existing ones like EndSimulationEntityCommandBufferSystem ?
its just different point where you playback an ecb. it is preferrable to try to limit where and when it happens so if you can use EndSimulationEntityCommandBufferSystem then use it, but in some instances you will want results sooner so choose whichever suits the situation.
i see does creating one causes "sync points" ?
i'll have look thx @safe lintel !
Why exactly does a command buffer improve the performance ? Does it really matter if we create an entity now or the next frame ? ^^
It groups all your structural changes in once place instead of potentially having them staggered throughout an update cycle which could cause disparate jobs to be completed when they may not have to be
@zenith wyvern Ah, so its main advantage is basically that it does not wait for the jobs to finish... and at the start of the next frame, the jobs are finished and we can easily create new entities and components. Lets say we wouldnt use any jobs at all... then it shouldnt have such a big impact on the performance to not use the command buffer, right ?
I'm not sure what you're getting at there, why would you need a command buffer in the first place if you're not using jobs?
Yeah... thats what my question is ๐ If it does make any sense to use it when we arent working with jobs
AFAIK it's purpose is to queue entity related commands inside a job or even on the main thread to group structural changes in once place. Not sure what you would want to use it for apart from that
By "no jobs" do you mean you're only using main thread jobs?
Or literally no jobs?
Alright, thanks. I just heard that it would make things faster. So i thought about using it. But if its only good for multithreading, then im gonna pass here. Only mainthreaded jobs... Just Entities.ForEach(...).withoutBurst(); where ever that runs ๐
Yeah I'm not sure there any benefit to using command buffers if you're doing everything on the main thread anyways. I can't think of one anyways
Revisiting my earlier question: If I need a system's OnCreate to depend on stuff from a MonoBehavior (like loading assets and making them available via a singleton) is there a way to do that? Or is there a better approach? It's hard to get serialized data into a system, it seems. Or to pass data between systems.
Pretty sure OnCreate gets called before monobehaviors even exist. I would suggest making your monobehavior into a hybrid component then you can get it in OnUpdate with GetSingletonEntity<MonoBehaviorType> and GetComponentObject
Otherwise you'd need to hook into scene loading in some other way, using the scene manager framework or make a custom static event on your gameobject
Or just access it inside OnStartRunning, I think Monobehaviors exist at that point
Hm, OnStartRunning would work. I couldn't find a lot about how to enable/disable systems. Like if I don't need all my systems running during my main menu scene for example.
Like ideally I'd like to do all of my runtime loading and precomputation during a staging scene before the game scene opens up, and only have systems started during the game scene.
Then they could fetch the MonoBehavior-made lookup tables and such.
I personally haven't found a reason to manually disable systems outside of testing stuff. I just rely on query matching which will prevent systems from doing work unless they're matching against something
It seems a little extraneous to have to make entities just for things like lookup tables. Surely there's a better way.
I don't know, GetSingleton/GetSingletonEntity provides a simple built in global point of access to some piece of data
Seems like a good fit for something like that
I think that just moves the problem of when that singleton is created.
And there's a limit to what kinds of data can be stored in a component like that, right? Since it still has to be blitted?
Not if you make it a class https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/component_data.html#managed-icomponentdata
So I'm seeing something like this
public class SingletonTest : SystemBase
{
protected override void OnCreate()
{
World.EntityManager.CreateEntity(ComponentType.ReadOnly<SomeComponent1>());
SetSingleton(new SomeComponent1 { value = 1 });
}
protected override void OnUpdate()
{
SomeComponent1 test = GetSingleton<SomeComponent1>();
Debug.Log(test.value);
}
}
That doesn't seem any different from just having data in the system itself.
So the game starts up. As part of the startup process, it reads some config/ini files and such for settings. Ideally the game systems would create after that data is read so they could bind to those settings, but it doesn't seem like there's any way to control that.
Sounds like you should be setting up the data during conversion
I'm not sure what I'm converting in this case.
This data doesn't live in the Unity editor. It lives in a text file that the standalone game reads at startup.
What I'm trying to do is convert it to shared lookup tables that various systems can easily access.
Oh, also apparently singletons can only be structs, they can't be managed.
public void SetSingleton<T>(T value) where T : struct, IComponentData;
Use GetSingletonEntity instead
There's gotta be a better way than that. You're paying multiple indirections every update pass (get the entity, get the component from the entity, get the table from the component) then just to get one lookup table.
I'll keep digging for something I can do.
Hooking into the scene manager might be the way to go if it's an option.
You could use a singleton just as a tag I guess, to let a system know that the table is available in static data somewhere.
Have a MonoBehaviour singleton that does the work in its Awake in the scene, and then creates some empty MyDataIsReady singleton, just so the system that RequiresSingletonForUpdate<MyDataIsReady> can start updating and fetch it statically and cache a reference to it, not from the singleton component directly.
You can cache it on the first update. I have a hard time believing that could ever become a bottleneck anyways
I could yeah. I'm thinking more that I could just manually create the system after loading the data and giving it the lookup table in the creation process, then adding it to the world myself.
NativeArrays are just pointers right
storing a reference to the same array a bunch of times is relatively cheap
Yep.
Gets more complicated when having to go through managed data though.
All of this also ties in to weird things like what you do if the player wants to go back to the main menu and start another game, etc.
Having systems always exist seems counter to that kind of flow.
Unless you truly only have "pure" systems with no global state, but I think that's an unattainable goal in most ECS approaches.
Also @zenith wyvern It's actually more efficient to create a new ECB and playback it right after an Entities.ForEach than using WithStructuralChanges
What sort of data are you looking for? Also, does it have to be in OnCreate?
Arbitrary game asset data loaded at runtime. Text files containing weapon stats for example, or scripted events, or textures loaded via mods. OnCreate would be nice since that's generally where systems do their setup. I'd like to avoid polling for the existence of the data every OnUpdate.
In MonoBehaviour world it would be pretty easy. You'd do the loading part in a staging scene, and then when that's done you transition to the main menu or gameplay scene.
But I'm scratching my head at how to do this in DOTS world. Or at least, in an elegant way.
Well, OnCreate is called very early in the pipeline - I don't think this would be a good place to depend on any arbitrary data that could come into the game. Unless of course you go with some custom bootstrap, but that will probably be even worse.
You also don't have to poll this every frame - you can always just have a one-off OnUpdate for a system with a RequireForSingleton.
Another thing that might also interest you is just streaming in subscenes, but that's already a specific type of asset, so not sure if it's relevant. But Entities was basically built to have scene streaming built-in.
You might also want to think whether you only want users to be able to load assets when the game is launched. It's a very nice QOL feature to be able to change and load mods without having to close down the game, if possible. This of course wouldn't work with scripts, but definitely with assets.
Is there a reason you can't do the same with ECS? Scenes are still a thing - and even SubScenes might be even better.
Subscenes are a Unity Editor concept, no? For mods, you don't really have that luxury.
Unless I design some way to make subscenes with some sort of mod metadata.
Most of my game assets and configuration numbers are not going to be in the Unity Editor. That's why I need to allocate time at launch or, as you say, in-game during a mod selection stage, to load and preprocess assets.
I think at launch is fine since most games require a reload to change mods anyway.
You also don't have to poll this every frame - you can always just have a one-off OnUpdate for a system with a RequireForSingleton.
The question is when you inject the singleton. Especially if your game has a main menu and such, when do you create the singleton for the system in question, especially if it's shared across multiple systems.
Why?
Well, what are the alternatives?
OnUpdate? ๐ค
That's what I'm trying to avoid, having to poll in every OnUpdate as per whether the data exists.
That's why you have RequireSingletonForUpdate
Well then you create the singleton whenever you want to load the assets
But again, where specifically? In what function?
Well that depends on when you want them to load
Okay, then you just create the singleton in OnCreate
Can that then be set in other systems that also want that same (managed) singleton?
As in, can the system responsible for loading and processing that data then reach out and provide it to other systems that want access to it?
Well, that system doesn't need to reach out. The other system should also just have the RequireSingletonForUpdate
Are singletons global, per-world, or per-system? The docs made them seem like they were per-system.
Per world - a singleton is actually no different than a normal component on a normal entity. It really only exists because the GetSingleton function is there - you can still create multiple instances of the "singleton" component, in which case GetSingleton would throw an error
There really isn't a concept of singleton in terms of how they're stored
Only in how systems interact with them
So any system can listen to the same singleton
For example, if you just start any entities game right now and look in the entity window, you will see the WorldTime entity with a WorldTime component. That's a singleton, but only because there's a single one of them.
A singleton is only a singleton because we want it to be a singleton - otherwise it's just any other normal component.
If you had a single enemy in your game which was the only one that had some of the components - those components would technically be considered singletons in (Unity) ECS terms
So any system can in fact listen to that singleton
Does that make sense?
It does, but that still seems like a fancy wrapper just for polling.
How would you avoid polling with monobehaviours?
By directly copying the table I want by reference as a field of the MonoBehaviour.
In its Start()
Which I would know is safe to do so, because the source of that data was staged in a prior scene in a DontDestroyOnLoad singleton.
Rather than here where I'm forced to check for the existence of this special entity, retrieve it, and then retrieve its component, every OnUpdate.
Which is minor, sure, in the greater scheme of things, but ugly nonetheless.
If you think that's ugly, then maybe ECS isn't for you, because that's literally what ECS is.
Your systems take all the entities with the specified component and then does some logic on it
The whole idea is to use components to specify what logic should run
Not necessarily. This handling of shared resources is unique to Unity's flavor of ECS, it isn't a fact of life for all ECS systems.
And "pure" systems are almost always a pipe dream. I haven't seen many substantial ECS systems that don't store data.
I think the answer, as I'm digging through docs here, is to just take better control over when and how systems are created.
Well, I just don't see how it's different than looping over any archetype of entities.
That's also literally just polling all the components. The difference is just that you know they're there
You're free to do your own bootstrap, but I don't think you're thinking in (Unity) ECS terms really here.
Right, but many is different from one. This is one shared, read-only resource. There's no need to go through a complicated lookup process every update pass for it -- it isn't going anywhere.
I don't think I've ever said to make a complicated lookup process?
And do it every frame?
That's what GetSingleton does, in my understanding.
It looks up the chunk, finds the component in it, and then you need to follow that through a third indirection to get your actual table.
Whereas, instead, you could defer the creation of the system, construct the system and pass the lookup table as you do so, and never need to do any entity or chunk lookups to get that data, you inherently have a bookmark on it.
Okay, let me ask this: How do you want to construct the lookup table?
Would it be something like looping through a folder and see what files are there?
Within either a system or a MonoBehaviour, in its OnCreate() or Awake() respectively.
I mean, how would you get the data for the table?
Resources.Load
And then parsing it, or if it's a texture or something, processing it into something usable.
And assembling it into an asset and data library for systems and gameplay entities to then use.
Hm okay, well that's definitely going a bit out of Entities land, since it returns any object.
But then you're probably right, OnCreate should be fine. Is your issue then how you would save and use that data?
I think what I would do is load the data in OnCreate, and save it to a managed component.
Any other system can then just have that manged component as part of their query, and you can do whatever with that data as you want
I think I would probably handle the world and manual system creation in a MonoBehaviour, most likely. Then I can easily feed in processed data to the systems as I make them, and exactly when I intend to during the startup process.
That also lets me destroy systems and worlds and recreate them if, say, the player goes back to the main menu and starts a new game.
If I feed in data during system creation I don't need to bother storing it on an entity. I never need the entity part of it to begin with -- I just want it to live somewhere easily accessible in memory as a lookup table.
public class SavedData : IComponentData
{
Texture2D texture;
}
public class LoadSystem : SystemBase
{
void OnCreate()
{
Texture2D tex = Resources.Load("SomePath");
var entity = EntityManager.CreateEntity();
EntityManager.AddComponent(entity, new SavedData{texture = tex});
}
// Empty update because it's required
void OnUpdate() {}
}
// Any system can then just listen for that data
public class ProcessTextureSystem : SystemBase
{
void OnUpdate()
{
Entities.WithoutBurst().ForEach((SavedData savedData) =>
{
if (savedData.texture != null)
// Do whatever processing you want. You can even save it to a different component if you don't want all the data stored in one component.
}).Run();
}
}
Just a quick example, the possibilities are endless.
Okay, how would you store the data in classic Unity?
Probably just in a static container.
Or on a singleton MonoBehaviour.
And then after it's created, subsequent MonoBehaviours could cache the pointer to the table itself and avoid later indirection.
Static container isn't really that ECS focused.
And singleton MonoBehaviour is basically the same as a singleton entity no?
It's missing a key step, the Start() pass, which lets me do the indirection once ahead of time and then every subsequent time I can avoid all indirection.
Sorry, what do you mean by indirection?
From quick googling it seems to be the data loading based on the path. But I'm not sure how the above is doing that?
public class DataLibrary : MonoBehaviour
{
public static Instance { get; private set; }
public Dictionary<int, Mesh> MeshKeys { get; private set; }
protected void Awake()
{
Instance = this;
SetupMeshKeys("ResourcePath/LotsOfDataFiles");
}
}
public class SomeUserOfData : MonoBehaviour
{
private Dictionary<int, Mesh> keysLookup;
protected void Start()
{
keysLookup = DataLibrary.MeshKeys;
}
protected void Update()
{
UseMeshKeysWithoutEverCaringAboutSingletonsEverAgain();
}
}
Okay, let me ask you now: Why are you even using ECS? It doesn't sound like you want to code ECS here
Well, I do, for everything else.
I just don't want to have my lookup tables be entities.
Why not?
Well, I see no reason why they need to be entities -- they don't do any entity things, they just exist as resource blobs. And looking up entities is more complicated and causes more cache misses than following a single pointer to a data structure.
Well entities are just resource blobs - they're just data
But
You could also create BlobAssets
But they also have to be stored in entities anyways
At least the reference
Right, which is what I'm trying to avoid.
This is essentially just static data. It doesn't really need to live in chunks (let alone have an entire 16kb chunk allocated just for a single pointer to it), and it doesn't need to be accessed through entity indirection.
Right, then I think BlobAssets are what you need
Can they be free-floating?
"A blob asset is an immutable data structure stored in unmanaged memory."
It isn't so much the data structure. How to store the data isn't a problem, it's how to feed it into systems.
Or rather, how to make systems aware of it without having to ask for it.
As I said, I think the "ECS world in a jar" where everything is wrapped in a MonoBehaviour that controls world and system creation/destruction is probably the way to go.
That gives the strongest tools for feeding in data to the right things at the right time during initialization.
I'm still not sure why you want to avoid the system to ask for the data
That's literally what all systems does
Unless you're writing some completely different ECS type than me
There's no reason for it to ask. The data doesn't go anywhere. It's set once at startup and there's no reason not to just have a direct pointer to it as part of the system's creation.
Okay, but then you can just as well store all data like that, right? I feel like you're actively working against ECS here
It isn't working against ECS, it's just storing some data separately.
Well, storing data separately from entities/components is working against it
Only in a situation where you expect everything to be an entity. That's actually kinda unique to Unity ECS, and a little odd.
If you look at other systems they differentiate between entities and resources, and let you access resources without making them ride on entities to do so.
(Rust's bevy is one such example.)
So I'm trying to recreate that here, essentially.
Taking control over the world and system creation process is the likely avenue to do so.
Well, if that's what you want, you're free to recreate it. I've given you a path that uses the tools available, and it seems your worries are only that you don't want to store it as a component on an entity or as a blobasset because you don't like it. If you really want to work against it, be my guest.
No I appreciate you pointing me to the singleton stuff, I think it's more just a lack of ergonomics on Unity's end.
Hm, ergonomics in what way?
Also sorry if that came out a bit harsh, it's been a long day ๐
"Everything is an entity" and "systems are always pure and store no data" are both ECS cliches that don't really work out in practice. I think most more mature ECS systems have recognized that and added more ways to better reflect reality.
If you look at how the HybridRenderer is written, it breaks both of those rules, a lot.
But because of DOTS's expectations, it has to jump through a number of hoops to do so.
Which I think is an ergonomics issue.
If DOTS had a nice way to just float static data for systems to retrieve independently of entities, some pain would be avoided IMO.
Have you looked at BlobAssets at all?
I have, but don't they need to live on entities?
Or rather, in components, on entities.
Hm, actually not 100% sure about that - but I think they do
I haven't worked with them in a while
Hm, I'll take a look. I'm going to go down my ECS-in-a-jar route and see where that takes me for now.
There's secondary benefits there like ensuring easy cleanup if you end one game and start another.
Yeah, that's the worlds in ECS are quite handy, that's true
But bootstrapping is not ๐
I don't think I'd actually use the bootstrapping system. It looks like you can turn it off entirely?
Unless I'm mistaken and you can't just arbitrarily instantiate worlds in MonoBehaviours.
I think you can? You can just create a new world anywhere
And then just add it to the update
Oh, then perfect. Make a MonoBehaviour, have it make a world or two, make the systems for it, and you have total control.
Set all your systems to [DisableAutoCreation]
UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP
Even better, if that still exists.
ยฏ_(ใ)_/ยฏ
But yeah, just looked up and you would still need to store BlobAssetReference on components
But I still don't understand why you don't like using components/entities to store the data
I just see it as unnecessary, I guess. It complicates the lookup process for something that traditionally has always been very simple.
Now, that's true of a lot of ECS things, but here, it's also less efficient.
So there's neither a code cleanliness payoff, nor a performance one.
Where normally I'd be willing to sacrifice the former for the latter.
I mean it's still one line of code. But I do see your point that GetSingleton is a lot slower than storing the reference directly.
But at this point, you should also consider whether it's really worth it. How often would you in reality access that data? GetSingleton isn't too expensive.
Oh it's totally fussing over little things for sure.
That said, I've worked on projects where we needed support from the engine provider because the profiling tools rounded milliseconds to the nearest tenth and we needed to see in hundredths or thousandths because our budget was that razor thin.
So, I'm a little less concerned about premature optimization than some.
Also, the biggest reason of all, it just irks me, and that simply will not do.
Though I appreciate you pointing me in a number of good directions. I'll check out the blob asset thing.
I definitely think it's an interesting problem as well, but I can't imagine that if you're using ECS in the first place, then a single GetSingleton (or even 50 or 100) in a frame will break any budget.
Yeah. It's the raycast thing. A few is fine, but they sneak up on you late in a project.
Probably true. I've looked at the DOTS FPS sample, they seem to have ~500 systems. It's of course not a finished game, but it is a complete vertical at least. And if you have much more than 1000 systems that each need to read the immutable data, then you might have bigger problems ๐
I would really urge you to try and follow the DOTS way at first, and then you can start optimizing with statics for the data if you start running into performance issues.
Something something premature optimization
Is your data coupled to worlds or fully static, unmanaged and/or managed?
Seemed like it's fully managed static
Yeah, fully managed static.
And read-only after initial load (usually).
Or not necessarily managed. Some things are in native containers.
Good point, wasn't considering that you're losing out on burst if you aren't using an ecb to buffer the structural changes
I think it's actually more to do with the fact that WithStructuralChanges in Entities.ForEach is doing a lot more behind the scenes than you'd think, rather than an ECB
what replace world.CreateSystem<T>(params object[]) now days ? i've tried world.CreateSystem<T>() but you can't pass params are you just not allowed to do that anymore ?
World.AddSystem(new MySystem(myParams));
I need help interpreting this. I'm doing a stress test for my A* pathfinding using jobs & burst (no ecs). This is an IJobParallelFor and innerloopbatchcount is 1. Paths are relatively simple since its just a complete open area on an empty 100x100 grid, so what I would expect is that every thread finished more or less within ~0.1ms from each other, but as you can see that is not happening
I'm using Temp allocator in the job and I have the feeling that is related to that, as I've read that if the memory that it uses is exhausted it fall backs to a much slower allocation, but the thing is that I'm not seeing those pink chunks that I believe are displayed when that happens
I've tried lowering the number of paths from like ~500 to the hundreds and seems to improve a bit but there's always a thread or two taking significant more time
are you sure its not the OS bumping the thread?
It is also interesting that on my old pc (4c/8t) it worked fine, i documented it a few months back and had screenshots
does this also happen if you do a bunch of dummy calcs (e.g. a for loop that does the same thing in same amount on each thread)? to check if it's because of ijobparallelfor
prob not due to temp allocator because that's 16kb per thread, if all those jobs are the same then would expect to see same slowdown in each (and even then, fallback allocator shouldn't take 2ms more)
I've got a 10k int3 array so I guess i'm beyond that
Just curious, how many agents do you have in this stresstest?
it's not the grid, it's the way I store pathfinding info (hcost & gcost and parent)
Ah right
I tried capping it to ushorts before, but didnt make it better
So you're passing in a nativearray of int3 array with temp allocation?
Or are you allocating that during the job?
its allocated during the job
it certainly has to do with the allocs, doing pointless work is totally fine, and removing everything but the allocs still happens
cant use other allocator inside jobs other than temp no?, if you meant by passing it form the main thread, I already tried making an array with its length * number of agents from the main thread, but since it has to be with cleared mem the bottleneck was so hard that I didn't even look at anything else
the only thing I have some faith in is moving to a bunch of IJobs instead
I've tried with the same number of agents as logical threads and works totally fine, so if temp mem is released after each IJob finishes it should hopefully work fine
So wait, do you mean that you are not disposing the allocations at the end of the job? Or is something else happening?
afaik, temp allocations do not need manual disposing, in fact, it does not throw any error like tempjob or persistent does
well, schoener reply seems appropiate to my case so i'll just hope that it'll work fine with a bunch of ijobs
So you basically gotta figure out a way to not allocate all that memory huh
Fixed it! Now it's 1k paths on a 100x100 grid, but also with obstacles (although the map is simple & open with no dead ends). Lesson learned: be extremely careful with temp allocators in paralleljobs
I can run navmesh queries directly on the job system right?
that's what the API says, but I've been told Jobs can't access the main thread
Nice! How did you fix it?
Just went from a parallelfor job to an ijob per path request
one job per path request has pretty significant overheads
have you thought of doing 1 job per core, but grabbing the path requests from a parallel queue?
Actually I've been doing some more tests and I have realized that now that I'm able to have substantially more paths, if there's very low work having all those path dependencies is pretty terrible, so that's a good idea
im not completely sure how that parallel for works, but a fairly common issue of them is that the work ends up varying too much, and it fucks up the distribution of tasks
generally on parallel fors you want to overlap them with more parallel fors so when threads finish their share they go to something else
Never tried to do such small parallel fors with uneven tasks like pathfinding before, I'm doing this just for the sake of learning so I'll see how it turns out ๐
I have an unsafe fixed length array struct implementation that I use with Burst.
To do some very simple memory leak checks, I have something like:
#IF UNITY_EDITOR
// On allocation
GlobalStaticClass.counter++;
#ENDIF
and
#IF UNITY_EDITOR
// On deallocation
GlobalStaticClass.counter--;
#ENDIF
And check if the counter is 0 at end of game.
Problem is that in Burst inspector, any job that uses it wouldn't compile and I lose the ability to check if I made a mistake in my actual jobs unless I comment out those checks.
Any idea how to get around it?
Are you currently using a shared static?
Yeah it's just one static class with a counter
It's only for development anyways to catch the most obvious memory leaks.
No it's just a plain old static class.
The docs show how you can setup a static field that you can use with burst
Thanks
Feels a bit overkill but I guess it's fine since these code will get striped out from production anyways.
I love when I update the hybridrender and random code is now broken in a completely unrelated script that has nothing to do with rendering ๐
ive found a number of times they introduce leak or error checks where there were none before, often ive been doing things incorrectly but it just happened to work fine until the update
yeah that's probably what I've done and things were going so well too 
That's probably gonna become better in the near future ๐
Whats the latest on terrain support in DOTS? I tried attaching a ConvertToEntity to my terrain and while the entity gets created nothing is rendered anymore
I don't suppose anyone knows why I'm getting this warning...
IndexOutOfRangeException: Index 0 is out of restricted IJobParallelFor range [4704...161] in ReadWriteBuffer. ReadWriteBuffers are restricted to only read & write the element at the job index. You can use double buffering strategies to avoid race conditions due to reading & writing in parallel to the same elements from a job.
for this job
Entities.WithDisposeOnCompletion(comparisonArray).ForEach((ref CellData cooldata, in DynamicBuffer<FlowfieldVertPointsBuff> flowverts) =>
{
cooldata.cost = 1;
for (int j = 0; j < comparisonArray.Length; j++)
{
var tempobsbuff = comparisonArray[j];
var tempbool = (flowverts[0].Float3points.x <= tempobsbuff.c0.x && flowverts[1].Float3points.x >= tempobsbuff.c1.x)
&& (flowverts[0].Float3points.y <= tempobsbuff.c0.y && flowverts[1].Float3points.y >= tempobsbuff.c1.y)
&& (flowverts[0].Float3points.z <= tempobsbuff.c0.z && flowverts[1].Float3points.z >= tempobsbuff.c1.z);
if (tempbool)
{
cooldata.cost = byte.MaxValue;
}
}
}).ScheduleParallel();```
is it because of the buffer am I not declaring it readonly properly ๐
probably because it thinks comparisonArray is readwrite
dunno how to declare that using entities.foreach tho
yeah just figured that, I used WithNativeDisableParallelForRestriction(comparisonArray)
and that seems have fixed that problem, now I have tons of others, I wish I'd updated sooner 
you can use WithReadOnly(comparisonArray) if you aren't writing to it
https://showcase.gdconf.com/session/unity-for-all-2021-tech-and-creator-showcase-presented-by-unity-technologies/880109 Seems there might be some DOTS news during the keynote later today
topics including visual scripting, the Data-Oriented Technology Stack (DOTS) workflow, graphics and rendering tools, netcode, quality-of-life updates, and more
โค๏ธ โค๏ธ โค๏ธ
There's also another one later dedicated on visual scripting only, but I'm afraid it means Bolt
will there be any performance gain to generate meshes using DOTS?
as in procedural meshes
@small arch yeah you can use burst + jobs to generate meshes and it's huge speedup
ty
Can i use Entity field in blob asset?
is it better to use Unity.Mathematics or Mathf performance-wise?
Unity.Mathematics
Another hidden gem ๐ how did you find it? Did you stumbled upon it by chance ? forum ? ...
OH MY GOD this one too https://github.com/Unity-Technologies/DOTS-training-samples
"2 years ago" ๐ฒ
yeah forums i think
might've been one of the "20xx.x beta" forums when a new release came out, not sure tho
they tend to post new stuff + examples on there
but they could def do a better job making it easier to find
+Stuff deprecates fast these days.
THough the ECS samples were great as a start
Sure, but seeing how it's supposed to be done is invaluable, then updating is not scary
But I'm happy how they keep their examples up-to-date, very much appreciated
Agreed x2
Thats confusing. Is GDC Showcase a different event from GDC as the Website says 19-23 July? And also the Unity for All session is not listed on the unit GDC site: https://unity.com/events/gdc2021 ๐ค
Yeah there's an online free-attending event this week (maybe more)
You just have to register
Yeah I just did. It says I will get a mail from noreply@swapcard.com but didnt get anything yet
nevermind I just got it ๐
๐
No, blob assets are immutable data
will there be a mention of dots at the gdc thing ๐ฅฒ
Yes, look at the link I posted further up
holy moly
time for a morning drinking game, if they mention roadmap or determinism, take a drink
will these be available after to view
There are supposed to be two GDC events this year, one right now and one in summer for bigger news so they have more time to prepare.
Yeah thanks for clearing things up
no probem
hey, the DOTS mesh rendering stops rendering the mesh when half of the mesh is off camera
any way to fix that
rebuild bounds maybe? seems like that might be the problem if its right in the middle
Not yet sure caus havent used it yet, will gotta later caus generation is looking kinda steep as it is getting bigger
how would i rebuild bounds
its for both the editor and the camera btw
i moved in the editor a tiny bit down and the whole entity disappeared
hmm do you have mesh culling on entity? I am bit lost there sorry if not helping, I stopped working with dots for now till the animations get more userfriendly pass.
this is literally the only code i'm using
the post from ivlsiuk is showing how to add your bounds
@small arch
No probem.
dots segment on the keynote
so far kind of a non segment to us i think, "its still in development, gonna be the future"
there still working on it thats good news ๐
they talked about a new netcode sample but i think it was gameobject based? unity.com/boss-room
think we concluded the dots segment
so is it normal for the hybrid renderer to not be that great, I get 15fps with 40,000 cubes
is it going to improve or is that just the limits of rendering in general
Yeah that was for GO Unity. Only thing was about the transport layer, but not really too relevant
You should definitely get higher FPS. Are you using V2? Also, URP or HDRP?
also assuming you're on desktop with discrete gpu?
that keynote didn't really bring anything new to the table, mainly the announcement of the new gameobject netcode sample project
Yeah they basically confirmed what we already know, "sorry no roadmap, you see we got feature-creep and wanna go all-in dots editor"
(and new 2D sample project on asset store)
And "the forum is the place to go to keep updated about DOTS"
yeah, pretty disppointing. i shouldve figured given joachim wasnt on the list of speakers for it
Yeah can't wait to see that one
๐
I think its new netcode-based, so ECS ?
I was waiting for Probe Volumes in URP to be showcased but not even HDRP ones got the place, so gotta wait to the summer I guess
I don't think I'm using either maybe that is the problem
I mixed networking and netcode. You're right @safe lintel, probably GO-based with custom network layer on top of the Transport package
Then that's definitely the problem, you should read this: https://docs.unity3d.com/Packages/com.unity.rendering.hybrid@0.11/manual/requirements-and-compatibility.html and the getting started page as well to set it up
I'd be more inclined to think it's MLAPI tbh
Maybe it's even built on top of Transport???
Yeah
I was wondering what is their first-party solution, they don't had one such thing for a long time ๐ค then concluded the same thing, they prob consider the MLAPI ready ? (didn't follow that much to tell)
Yeah it is MLAPI
Yeah this one is a fact, that's what they told during the stream
didnt realise it was far enough along with integration for them to make a full scale demo like that
Then why'd you say they were making a custom network layer? ๐
I meant on top of the Transport package
Thanks๐
But that would have been dumb to add another solution in the bowl
Yeah, but what's to stop MLAPI being built on top of Transport?
Hey, I'm still stuck on skinned mesh conversion. Anyone has experienced this before and can help me? I lose both the rotation and the scale of the GOs transform during conversion
Happens with both blend files and fbx
@fluid kiln need to use a compatible shader, theres vertex and compute shadergraph examples in the animation samples
Well well, thank you
Is marking entities ALOT a good idea ? Like... items are entities in my case. They are pretty logic heavy. So i mark them with stuff like "Equiped{ wearer }" or "PickedUp{}" or "Dropped{}"... so there systems that operate on those entities like : Entities.ForEach(Item item, equiped eq, onEquipedSpawnEnemy oese){} is this too much marking ? Or is it flexible and fine to use marking that intensive ?
Some marker only stay one frame... for example theres also a "OnEquip" marker... which i delete after one frame. Only to react with some system to execute onequip logic
Might want to make an event system separate from the entities you operate on.
The bigger the entities, the less can fit in a chunk, and more memory needs to be moved around every time you change its archetype.
There have been some discussions on the DOTS forums on the topic.
@dark cypress Alright, thanks ! Lets say the performance isnt that important for me... are there any downsides of that intensive marking approach ?
No, not really. It's all about micro-optimizations.
I've also heard Unity will optimize adding and removing tag components(data-less) to be very fast, so might want to design keeping that in mind.
It doesn't need to optimize data less tags because they don't need a chunk associated - isn't that the case?
Like they take up next to 0 in the chunk
I was reading this last night in the dots basics guide
Ok thanks ^^ I also see no downsides of that design yet ( well performance, but it doesnt matter in my case ). It should be flexible to add new features by adding new components to the items easily... atleast it looks like this, hopefully thats right xD
@sturdy rune The entity still needs to be moved to a different chunk(and a chunk created if it's a new Archetype) on a system change.
Yeah, which is why I've also seen a Unity dev recommend to keep entities granular (separate big entities into multiple), so that there are less possible combinations of components.
Weird question, what's the smallest we can make a Icomponentdata?
I'm guessing 8 bytes (the size of byte)?
Sorry I mean what's the smallest we could make a IBufferElement?
OR the largest we could make a IComponentData?
When I connect a second client in NetCode, I get exceptions form the NetCode package querying for singletons of NetworkIdComponent. Has anyone encountered this before?
What the hell ๐ฒ yeah you're supposed to have only one per client
One per client? hmmm
I have 2 on my Client0 when Client1 logs in
It's the strangest thing too, I searched my code, nowhere do I create a NetworkIdCompoennt ๐ค
Yeah that codegen by the netcode package
I'll refresh it
Yeah I mean, never me manually, and I expect that NetCode is supposed to work ^^
yeah I see. I'm wondering how it could happen ๐ค
Maybe my connection code is not right
I don't see how my code could create more network ids tho :/
Entities.WithNone<NetworkStreamInGame>().ForEach((Entity ent, ref NetworkIdComponent id) =>
{
ecb.AddComponent<NetworkStreamInGame>(ent);
var req = ecb.CreateEntity();
ecb.AddComponent<ConnectedRPC>(req);
ecb.AddComponent(req, new SendRpcCommandRequestComponent { TargetConnection = ent });
}).Schedule();
Entities.WithNone<SendRpcCommandRequestComponent>().ForEach((Entity reqEnt, ref ConnectedRPC req, ref ReceiveRpcCommandRequestComponent reqSrc) =>
{
int networkId = GetComponent<NetworkIdComponent>(reqSrc.SourceConnection).Value;
if (!connectedIds.Contains(networkId))
{
connectedIds.Add(networkId);
ecb.AddComponent<NetworkStreamInGame>(reqSrc.SourceConnection);
var player = ecb.Instantiate(playerPrefab);
ecb.AddComponent(player, new GhostOwnerComponent() { NetworkId = networkId });
ecb.AddBuffer<PlayerInput>(player);
ecb.SetComponent(reqSrc.SourceConnection, new CommandTargetComponent { targetEntity = player });
}
ecb.DestroyEntity(reqEnt);
}).Schedule();
Yeah you're not supposed to handle that yourself, just use it to ID the client (who is who)
Exactly
refreshing the codegen did not help ?
Maybe the newer version of netcode handles connecting different, I think mine is from like 0.4
No it didn't :/
Last time i played with it, I was in 0.6 I guess. WHich one you upgraded to ?
If my code above rings an alarm, let me know I'D appreciate it, the most recent, 0.6
I'll go look at the cube sample again
Where are your clients from ? build and/or editor ?
Editor running server/client, and 1 built client
Yeah I do the same and never happened to me
If I try with a thin client, I don't get errors but the players are never spawned
Mhh
ANd do you try to spawn multiple prefabs per client ? (Looks like no)
No just the player prefab
uhm
I'd expect to see 2 on the server world
but not client0
did you launched the build first, the played the editor, stopped it, and played again ? (would mean you don't destroy entites when losing connections)
When I do that, I get the same result as when I run a thin client. No error, but no players
ok. If you didnt modify default, only editor can be server anyway
Yeah I checked my build is not server... it's so strange, I built NetCode before the subscene conversion but I never managed to make it work with it
when you click on the 2 entities, they are have different values or the same ?
Maybe it has to do with my subscene conversion?
I used subscenes, works ok
1 and 2
well that all good then
only thing weird is why you see both if you filtered the entity debugguer window to ClientWorld0 ๐คทโโ๏ธ should see only 1 here
I see some differences in the cube sample, I'll go ahead and make some changes
yeah not sure your target component should be empty in last screenshot
yeah do the update, especially the second block of code you shared
In last version they use a GoInGameRequest instead of ConnectedRPC, codegen may expect this name
GoInGameRequest is a used defined component but maybe so ๐ฎ
you mean user defined ? yeah you're right shouldnt matter
That's strange. I don't see what's wrong. I won't add to the confusion. Maybe yeah it's just you have code not up-to-date
I'm sure it was my second block of code
Seems to work now, I'll try with a build
I should probably build from my build configs rather than the build settings...
But now I'm seeing this
Yep. don't use legacy build settings
Which build components are the pipelines
Awesome thank you very much
Love that big warning I've never seen but that could've been useful 5 months ago ๐
The warning says that this component is not used by the pipeline. Will my build still be a client?
I'll try it out
It should. But if not, you can add the scripting define yourself as part of the build pipeline, it should just be UNITY_CLIENT
Checks out, now I'm getting Trying to render a batch from the Hybrid Renderer V2 with SRP Batcher OFF. This is not supported. Please turn SRP Batcher ON to use the Hybrid Renderer V2.
But it is?
https://forum.unity.com/threads/how-to-please-turn-srp-batcher-on-to-use-the-hybrid-renderer-v2.1067003/ This reports the same error as a false-positive
DO I have to define ENABLE_HYBRID_RENDERER_V2 in the build settings too?
Uhhh