#archived-dots
1 messages ยท Page 209 of 1
again unsure how netcode and ghosts work but could you make your child abilities 'accessable'?
wdym by that
in my netcode that just means giving them a unique id
so when sending messages i can lookup the target entity by id
i think it netcode its the 'ghost' thing
oh yeah, I don't think so because they aren't ghosts
Theyre ghost child
I'll try to look into what a ghost child does
Doc, is sparce
does it not support children being ghosts?
Not afaik might be wrong
yea thats annoying
Well actually
hmmm
I never thought of have other entities than the characters be ghosts
But then wouldn't that dramatically increase the number of ghosts
i guess
not sure what the cost of ghosts in netcode is
for me 'networkable' entities are very cheap
just a ID really
and data is only ever synced when there is a change
and even then theres a ton of options to control the syncing
i cant imagine ghosts being too expensive
Me neither but I remember reading somewhere like max 80 ghosts or smt
Maybe i'm crazy
There is no hard limit that I'm aware of
I think I jhust have to configure them correctly
Like how do I disable transform sync
Since they're abilities
Any idea how I can handle my ability referencing Script?
A character has x abilities, that are children to it
How do I refernce these abilities from the server/client
I thought of an ID component
But now it kindof makes sense to make them ghosts
Hmm
For some reason I had the preconception that ghost == player/npc
I wouldn't make each ability it's own ghost
I have to, because they have important components like cooldown etc
How many of those will you have and how are they linked with the player?
They can still be their own entity
Ghost != entity
My bad
haha
I recently started a new project and for some reason my system is never created when I go into play mode. Any ideas??? It inherits from SystemBase and contains only a Debug.Log in OnCreate();
A character might have anywhere between 1 and 30 abilities
So far they,re only linked through children
Hierarchy
You could store a lookup table on your player that maps ability type to idx in your children buffer
Check the entity debugger if it's there
Oh okay I could do that
Buuuut It's rather hard to judge without knowing all your requirements
So another fun idea ๐
A component with 30 filelds of Entities? each of them the ability entities
That's the thing, it's not ๐ Also checked in Inactive Systems
Naah I don't like that, I want it to be dynamic ^^
tho i have no idea how netcode handles syncing of entities references
WHy not make them ghosts?
Since the only thing they might sync is the remaining cooldown
Do you know if children entities can use [Ghostfield] ?
Yea they do
Okay so making them ghosts would be redundant
My setup looks like this: Character (ghost) holds a reference to AbilityCollection (ghost) which holds the abilities which aren't ghosts
So I can switch the abilities during runtime easily
Can you explain GhostField? im interested, that just marks the field to be 'sycned'?
Yeah basically
Ye
nice
How do you reference your abilities across the server?
My AbilityCollection holds a DynamicBuffer of abilities
I do not have a lot of them so I just iterate over the buffer
To find the matching one
Okay got you
I might try to ghost them since being able to reference by entitiy would make my life so much easier
And if it's too costly, I'll find another solution
Ugh but now I have to instantiate them differently
Your abilities?
Yeah
If they are childs of a ghost the reference is automatically resolved when instantiating
Just like the normal instantiate
I haven't had a need for ghost relationships like that so far
It's touchy
I like having them under one ghost so I can be sure that the reference to the children is always valid
Yeah me too I don't want to shake that too much
Messing with my Character<->AbilityCollection referencing was stressful enough lol
I'm curious how you handle casting these abilities if you'd like to enlighten me further
What do you mean with casting?
For example, I like to add components so I systems can pick it up. So far my ability casting pipeline is: Player sends RPC to cast ability - Server checks if cast valid - Server Casts Ability - Server sends RPC to client to tell it the cast was succesful
But during the cast, I need to add the component OnCooldown to the ability on both the client and server
I'd ghostfield the remainingDuration
Little optimization, ghostfield the tick instead of the duration
Yeah you're right that's the right way
That way it doesn't change every tick
Noted thank you
It's really messy and no guarantee of synchornization
But how do you handle that in systems
Yo umust have a lot of systems with if() return
Yes
Basically every prediction system I have
I do not have abilities in that sense btw
I call abilities/actions my character stuff like moving/shooting/sprinting
Etc
Which I inherited from the FPS sample
Yeah no worries I can apply these concepts to my thingy
I don't think those rpcs work very well with prediction
This was actually pretty enlightening, I might go the way of not adding / removing coponents too
You most likely want to include that into your input struct
I tried to have "button" type fields in my inpuit
But sometimes it felt like the buttons were lost
They are if you sample them the wrong way, let me check if I can find the forum thread
๐ค
Hmm can't find it
You basically have to use "button |= Input.GetKey" instead of GetKeyDown and reset the state when you start sampling for a new tick
Ye the input is sampled every tick but only send once the tick has been fully predicted on the client
Time to do some good old refactoring
So maybe I could have an int field with abilityCast or something like that
Or if I find a way to sync the ability buffers
AbilityIndex would be pretty cool to use instead
Any way to guarantee dynamic buffer order?
Indeed, or if you can hard code the ability type the enum to send
DynamicBuffer order should be guaranteed
Even if I add to it during runtime
Well then it won't be synced and it depends on your add logic
Are you talking about adding the buffer during runtime or adding to the buffer?
Like a character learn a new ability during ganeplay
Hmm
I guess you would actually need ghosts abilities for that
Since as far as I know you cannot add new components to sync to an already existing ghost
Could you just use a rpc to sync that?
wait you cant add components to a existing ghost and get them to sync?
Not that I am aware, no
hmmm actually thats exactly how my netcode currently works too ๐
In 0.5 idk how it is in other version netcode create a static ghost archetype (not an actual entities archetype)
That you can't modify
Well you can add to them
interesting
Yea
yea, same for my stuff ๐ its not hard to add a new component to sync, just i havnt made it automatic yet.
I imagine its the same for Unity, they just havnt added that feature yet
When is your stuff going public btw?
probably still awhile, Im almost done refactoring into a package
:o
but i want to build a ton more samples and docs and stuff
and discussions like this make me relise theres still a few holes
and im debating getting the modding package out first instead of netcode
It doesn't have to be feature complete for 0.1 haha
even tho my netcode has more stuff, modding is simpler
haha yea, thats what i tell myself
Conpletionism syndrome
yea
and finally i want to figure out automated tests
this package refator broke a bit, so would be real nice to have tests to confirm bits are always working as expected
As a github integration?
maybe
i actally use azure devops mainly, so would probably use their piplines to run things
but first just getting tests i can run manually
You gotta get that new test coverage package
anyone know if there is any downside to using ThreadIndex for the EntityCommandBuffer.Parallel index in cases where there is no index provided (e.g. entityInQueryIndex)?
It's addicting seeing the coverage going up everytime you add a new unit test
Ye there's a 1.0 version https://docs.unity3d.com/Packages/com.unity.testtools.codecoverage@1.0/manual/index.html
๐ google must have sent me to the old one
Idk why unity doesn't fix their google integration regarding that
Always hit the old versions
im still not even sure whats the right way to write tests.
Those unit tests would be ok testing parts (units)
But with something like netcode i want to test it as a whole somehow
I always like hearing what stellaris does, they run a massive AI vs AI networked match each night ๐
That's a lot of custom stuff but that's how my input storing looks like ``` private ClientSimulationSystemGroup m_clientSimulationSystemGroup;
private EntityQuery m_commandToSampleIntoQuery;
protected override void OnCreate( )
{
m_commandToSampleIntoQuery = GetEntityQuery( typeof( CommandToSampleInto<T> ) );
m_clientSimulationSystemGroup = World.GetExistingSystem<ClientSimulationSystemGroup>( );
RequireForUpdate( GetEntityQuery( typeof( T ), typeof(DoPredict ) ) );
}
protected override void OnUpdate( )
{
var commandTarget = GetEntityQuery( typeof( T ), typeof(DoPredict) ).GetSingletonEntity( );
var commandToSampleInto = m_commandToSampleIntoQuery.GetSingleton<CommandToSampleInto<T>>( );
var targetTick = m_clientSimulationSystemGroup.ServerTick;
if (commandToSampleInto.Value.Tick != targetTick)
{
var commands = EntityManager.GetBuffer<T>( commandTarget );
commands.GetDataAtTick( targetTick - 1, out var lastFrameCommand );
commandToSampleInto.Value.Reset( lastFrameCommand, targetTick );
}
m_commandToSampleIntoQuery.SetSingleton( commandToSampleInto );
}```
space
You probably want to check out how the guys from unity's netcode did that
They also run client/server worlds in their unit tests
Custom component
Thanks ๐
lol
lmao for comparison this is my input system
{
PlayerInput input = frameInput;
input.Tick = clientSimulationSystemGroup.ServerTick;
Entities.WithAll<LocalPlayer>().ForEach((DynamicBuffer<PlayerInput> buffer) =>
{
buffer.AddCommandData(input);
}).Schedule();
}```
That code is just for preparing the command/resetting the data. Storing is also reasonably simple on my side: ``` var commandTarget = GetEntityQuery( typeof( T ), typeof(DoPredict) ).GetSingletonEntity( );
var commands = EntityManager.GetBuffer<T>( commandTarget );
commands.AddCommandData( m_commandToSampleIntoQuery.GetSingleton<CommandToSampleInto<T>>( ).Value );```
What type of game are you guys building?
Every snippet you've shared me Script have so many generics
I don't know what the hell is going on in there
hahaha
Trying my hand at a top-down rpg just for fun
Top-down shooter
nice
INdeed, the reason for that is that it's part of my framework lol
both will be awesome in DOTS
Yeah dude I see so many features with DOTS that would make me cringe in OOP
It's a whole new world quite literally
yea sooo good
Indeed, but it's still a very long way
i really want to get working on my game but messing with tech/tools
Hopeing for a Voxel Space ship rts
me waiting for navmesh, terrain, input, ui
Navmesh is pretty fucking critical for me to do antyhing but I cba figuring it out until the official package is released
@fluid kiln Have you seen Dots-Nav for navigation?
ive also converted some of A* PathfindingProject to be dots compatabile
I don't like to go too low-level, I heard you had to still calculate the path yourself
I'd rather wait for an api that lets me GoToDestination or something like that lol
i wouldnt say caculate... more like follow
Care pointing me to that Dots-nav then? When I check the package doc I can't find much on how to use it
yea i never use those APIs anyway, always wanting a bit more control about how the 'thing' moves
the community is starting to build up cool stuff
i dont think it will move your entities
but a follow path component is pretty easy
pog?
๐ like very great
i dont think you can
the entity name only exsits in Editor
and only in some cases
ummm not really
just store the entity referece
and use a entity query to find that
whats your usecase?
WEll... its complicated. ANother question, Is a unsafe-hashmap shown in the entity inspector ?
Its items
If not... i have a damn bug somewhere
no i dont think so
a dynamic buffer will be
but i expect that many of the native/unsafe collections dont have inspectors yet
@ocean tundra Thanks, tested it you are right ^^
Damn... i worried that it doesnt set the component right because it was just... empty
But once i loop over it, its filled so its fine
yea inspectors is still missing some stuff
kinda annoying
i dont know if theres a way to build our own yet
I would love to get some of my bit packed components understandable UIs
so if you figure it out let me know ๐
can component buffers store pointers to regular Mono objects?
or will they only accept pure data structs?
can a IBufferElement be a class?
my assumption would be no as you could just stuff a list in a class component
im getting antsy for the next dots release. I need more features ๐ฉ
thanks
haha yea i want more features too
anything confirmed on whats in 0.18?
working ISystemBase is the most of heard
just pure guesses, even forum posting by devs seems to have slowed but that could be my perception
can I inherit from my own IComponentData structs?
yea
what have you been doing ๐
thats like the main thing todo with ECS
oh ๐ reread that
no i dont think you can have inheritance of structs
ooooh
C# structs don't support inheritance
You can include a struct as part of another struct, via composition.
If you have struct type A that ONLY contains a single instance of struct type B, you can use NativeArray's Reinterpret function to view an array of A as an array of B.
You can also have interfaces that inherit from IComponentData so you can have structs with specific Methods or Properties.
ISharedComponentData, and the system state variations all do this, so additional constraints can be put on them in addition to being valid IComponentData.
thanks
Do you where I can find the information that tells me when I begin sampling for a new tick?
Here you reset when the target tick is different than the last input's tick?
if (commandToSampleInto.Value.Tick != targetTick)
Oooh I think I get it. Something like this:
{
var targetTick = clientSimulationSystemGroup.ServerTick;
//Only sample if tick has changed
if(input.Tick != targetTick)
{
var inputBuffer = GetBuffer<PlayerInput>(GetSingletonEntity<LocalPlayer>());
inputBuffer.AddCommandData(input);
input = default;
input.Tick = targetTick;
}
}```
That's brilliant
input events?
Yeah I use the new input system
It's just awkward cause I have no way to distinguish between UI and world when I use the mouse :/
There must be a way I don,t know about
yea that was a issue AGES ago when i used it
had to have a game object reference to my UI MB
and that was using the new UI components which had some sort of ismouseover
but the Y was flipped from what input gave ๐ so i had to flip it first
was all really annoying
yea it was definitly better
does it give you a nice input struct you can use now? or do you map your own?
I have to map it cause it's not really DOTS compatible yet
yea figured ๐
It's kinda hard to design the input for a top down game tho
Mine looks like this so far
{
public uint Tick { get; set; }
public float3 mousePosition;
public Entity hoveredEntity;
public bool selected;
public bool interacted;
}```
I convert the mouse position to world position on the client
The say the player right clicks to move, I send the mouse position and "interacted"
yea i would convert it too for my older rts prototype
But IF hoveredEntity is not null, then attack that entity instead
I find it a bit unstable? idk
but i never synced that with server
instead, i broke it up into commands (rpcs)
The recommended way with netcode is to send input
But I remember we talked about this before :p
so when i clicked on something, i would take the world pos of mouse, find the entity selected, and send a command with that entity that i selected it
Yeah I gotchu
yea they want the raw input cause they can simulate users or something right?
It makes it 99% server safe (?) (only breach could be corrupted input, so you gotta clean it), and also allows for ghost prediction (I'm not sure if you can do that through commands, im not too knowledgeable)
yea
my way is all commands, client takes input, breaks it down into current command (selected actually isnt even synced) eg a move units command
and server side i have to have checks like Does unit exsit, is it my unit, is target pos valid ect
oh snap... I keep forgetting 0.17 got delayed
they didn't bother updating the change log date though
https://docs.unity3d.com/Packages/com.unity.entities@0.17/changelog/CHANGELOG.html: md [0.17.0] - 2020-11-13
hi all, has anyone come across a solution for voice communication with ecs ?
can Animation Jobs be burst compiled ?
Since DSPGraph seems to be in a very early state I doubt it.
I had a fairly easy time integrating Dissonance
oh good to know ๐ did you use netcode though ?
Using steam P2P when possible, if that fails Dissonance automatically relays the packages through the server
tried replicating an example script but in my case it doesn't like the exact line i copied to my script
oh nvm , i have the imports all mixed up
Hi, I'm new to unity and want to make a game with lots of "boids" (objects that follow the same rules). I started optimazing it with the GPU isntancing approach (special spawner for my gameobjs). After some research I found that sth with DOTS might be even better. Is it possible to marry the GPU instancing approach and DOTS or would GPU instancing be redundant if I use DOTS?
You could use Jobs for the logic and keep GPU instancing for the meshes. Not sure if DOTS is faster right now
(especially on the rendering side)
There is an official example where they implemented Boids, maybe you could compare with your solution
If you want to release soon, I'd say keep gameobjects + GPU inst (+ jobify some parts if needed)
If you bet on the future, DOTS will be awesome in a few years
Thank you for the fast answer! Will definitely look that example up
All the repo is a must to explore
Be aware though, that as DOTS is not ready, they sometimes cheat. For example in the Boids demo, the fish are not animated, it's a vertex displacement shader. Tricks like that
Consider only parts like ECS for the data layout, Jobs for multithreading, and such...
Okay i will google my way through it ^^' thank you so much for your help so far, i definitely have a better place to start now!
Oh if you're starting, be sure to check pinned messages inthis channel
could save you more time than google searches ๐
and check the DOTS dedicated forum from time to time ๐
I will thank you:D
@karmic basin didn't they say dots should be "ready" by 2022?
is CreateEntity(ComponentType[]) or CreateEntity(EntityArchetype) better to use?
the former is going to determine the archetype from your component types .the latter has the archetype already so the latter should be faster
@stable sentinel
Currently working on procedural world generation in DOTS as a performance comparison to my old implementation. Have chunks generating but the chunks have no way to communicate with each other, so I can't determine where I don't need to draw a mesh on the borders. The idea was to treat chunks as subscenes.
This leads to a lot of unnecessary drawing. Has anybody got a working implementation of this? Or any suggestions on how to solve?
From some reading I've done this seems to be a fairly common issue (looking at this repo currently but it has the same problem https://github.com/sarkahn/dots-blockworld/)
@sage mulch what do you mean by that? if you have the chunk index, don't you always know what chunks are bordering?
Sark actually follows this channel, you'll be able to talk with him about that :)
@hollow sorrel Thank you for the reply. Should probably make it clear that I'm somewhat new to DOTS so I may explain something poorly.
In my original implementation (non-DOTS) I store the chunks (and their data for what type of block is at each grid coordinate) in an array that can be accessed by other chunks. When I'm drawing the mesh, I am able to query neighboring blocks, and if they aren't part of the chunk we're currently working with then I can refer to this chunk array, find the desired chunk, get into the grid and determine if its transparent or not. that's the gist of it at least.
With my DOTS implementation, its basically the same but I don't have access to that chunk array because I treat each chunk as an entity, and I can't think of a way to structure the components/corresponding systems so that it knows which neighboring chunks to query for block data, without losing the advantages of DOTS in the first place. So, while I may have the chunk index, I'm not exactly sure how I can use that to retrieve the block data from a neighboring chunk entity.
Oh excellent, thanks so much. Is he just @ sark? (Don't want to ping the wrong person by accident lol
Yeah it's him. Let's not ping him. He stops by quite often anyway
What I did on my last run was I created a "World" structure that I would pass into jobs https://github.com/sarkahn/dots-blockworld/blob/version2/Assets/BlockGame/Runtime/VoxelWorld/VoxelWorld.cs
It's a bit convoluted but the idea is it contains everything needed to read/write and create new chunks. So a pool of pre-made chunk entities, and a NativehashMap<int2,entity> that refers to each chunk "region", and all the BufferFromEntity/ComponentDataFromEntities along with helper functions that utilize all that for "convenient" access to any block in the world
It ended up creating a dependency nightmare which is why I ended up giving up on it. But it was working
Apologies for the ping, that was me. I thought if it didn't turn blue when I typed it it wouldn't ping you ๐ข
cannot convert from 'Unity.Mathematics.float3' to 'Unity.Physics.BoxGeometry
Thanks for the reply though, I will be reading that during my break today hahah
Appreciate the help!
entityManager.SetComponentData(myEntity, new PhysicsCollider { Value = Unity.Physics.BoxCollider.Create(float3.zero, new float3(1, 1f, 1f))});
I checked the Create function and it asks for float3
No worries, it's completely fine
Guys, anyone using addressables with dots?
Would you say the performance improvements made the effort worthwhile?
If there were any improvements
I have only those
BoxCollider.Create(new BoxGeometry { Orientation = quaternion.identity, Size = new float3(1.0f, 1.0f, 1.0f) }); ?
oh haha
it's just that if you google boxcolliders
there is an example
pointing to an older doc
but I guess if I actually read the error I would have figured it out
at the top of the official doc there is a dropdown to select your version of the package
- a blue "latest version" button
If I have multiple NativeArray<T> which all point to the same memory and I call dispose on one, does it wipe out the memory and invalidate all that point to it or does it just remove that specific point to the memory and decrement the reference count?
@toxic crest yes it invalidates all the others
Do I need to do anything when I'm done with one of the copies but want to keep the others valid or do I just let it fall out of scope and Unity handles the rest?
I might be wording that oddly.
What I mean is, do I need to do anything if I'm done with one but not done with the others?
no you'd need to manage when to dispose yourself
unity doesn't check if multiple nativearrays are pointing to the same memory
Thats what I was hoping. Thank you
architecture wise, decent rule of thumb - if it instantiated the array, then it should take care of disposing the array
so if you're passing same nativearray to other classes then they shouldn't have to worry about disposing, only the one that made it does
You cant use a SharedComponent type in a Entities Foreach With burst!!??
Or is this one of those fun ordering issues
my shared component is still a struct
You must set the value of a shared component on the main thread using either theย EntityManagerย or anย EntityCommandBuffer. When you change a shared component value, the affected entity is moved to a different chunk. If a chunk already exists with the same values, and has enough room, the entity is moved to that chunk. Otherwise, a new chunk is allocated. Changing a shared component value is a structural change that potentially creates a sync-point in your application.
yup
not changing at all
just trying to read in a foreach
I ended up with using GetAllUniqueSharedComponentData, then sceduling the job more times (1 per unique shared component)
it will probably be faster this way ๐
cant even use a SharedComponent in a ECB ๐ฆ
yea from a job with burst tho?
No
anyone knows a position grid implementation done for dots ? im using ecs-phyics and want to apply collective forces on large amounts of bodies using a wind simulation
its very easy to make one
doesn't physics already uses something like this ?
i did try search for grid keyword in the source but nothing seemed to pop up
what do they use to avoid all VS all collision checking i wonder
Nothing that they expose to users
i dont know if theres one in physics
dots-physics ?
They do one in the official physics sample but IIRC it's trigger based, not grid based
But yeah you can do your own spatial partitioning solution
They do one in the official physics sample
What I meant "they do" is some kind of vortex/tornado that apply forces to RB's in the zone, and IIRC they handle the all-VS-all collisions check
Is it possible to know if code is compiled by burst or vanilla compiler?
I want to throw exceptions or mb log if I use a function not in jobs
E.g.
#if !BURST
Debug.LogError("Bad")
#endif
I guess ... inside the burst inspector?
There you can see, which scripts are compiled by burst, afaik.
If you run the code right at the beginning of the game, you have to enable "synchronus compilation" first - because otherwise it will asynchronously compile for burst, meaning, it will run on "vanilla compiler" (I guess, C# Rosslin Compiler but IDK).
A check within the burst code would be really handy - but as this is all on the C++ side of things, or Assembly, I guess, I think the only way to view it, is in the burst inspector.
You can use: ``` bool isBurst = true;
IsNotBurst( ref isBurst );
[BurstDiscard]
private static void IsNotBurst( ref bool value )
{
value = false;
}
Sorry about the formatting
lol
Usually I define this flag manually and turn it on/off for debugging. I guess there should be used something like that internally
You can use Debug.LogError though ? Why the hassle ?
Didn't remember if I can. But there are other use cases for this
If it is a job, it wouldn't show the error log, no matter if compiled with burst or not (atleast, it was like this when I worked with it, that was one year ago)
They fixed that, you can now use the Debug methods again
Thats pretty dope and will make things much, much easier when I get back to the project in ~2 years
i hope bolt gets dots support soon
visual scripting would make jobs/ecs a lot easier to work with
someone remind what's the attribute of disposing a native collection on completion?
WithDisposeOnCompletion(myNativeArray) ?
normal jobs
:IJob ?
yep
[DeallocateOnJobCompletion] ?
When will unity release a blog post on dots?
where can i find this ?
I'm really struggling with reducing the main thread cost of my systems. I'm exploring caching the ComponentTypeHandle's - has anyone else tried this? Also wondering what's the best way to know when they become invalid
(caching the handles makes no discernible difference but still curious about how you know when - using the global version if the type didn't seem to work)
lemme check
Used in this unity scene EntityComponentSystemSamples/UnityPhysicsSamples/Assets/Demos/2. Setup/2d. Events/2d1. Triggers/2d1c. Triggers - Force Field.unity
IIRC they implemented custom trigger events through a buffer, to keep track of entites in onEnter onStay & onExit states, as I guess it's not ready with dots. Then it's pretty much what you'd expect
im looking at Broadphase now and it looks like the data is stored in a tree structure Nodes
isn't it internal stuff ?
nothing is internal in an open source project lol
oh so you wanna learn how they do it to replicate in your own code ?
first i would have to understand what is going on there, and i would like to schedule grid based forces on the physics world without redoing / replicating too much stuff
or rather scan the tree and find the appropriate grid cell from there ๐ค
You can study the Boids sample too
they did spatial partitioning
though it would be old now, and not using the Broadphase
I am struggling to understand write groups. Just learning DOTS
When you enable write group filtering in a query, the query adds all components in a write group of a writable component to the None list of the query unless you explicitly add them to the All or Any lists. As a result, the query only selects an entity if it explicitly requires every component on that entity from a particular write group. If an entity has one or more additional components from that write group, the query rejects it.
so if you add the component b to a write group of say, component a
the query will exclude that entity with component a as if the entity had component a and b, as if it was a "with none(component b)" query ?
so any query looking for query a, will skip entity with component a unless it also has component b
If B has write group on A
A system will only execute if the entity has A and has B
Does anyone know if there's a performance difference between having multiple ForEach in a system or instead multiple systems?
I believe its faster
having many foreachs in one system
as you dont have the overhead of a whole new system
BUT you should probably manage the foreach Dependency yourself, as by default all Foreach's will be dependant on the one before
@deft stump Safety checks and stuff on?
4 float3's and 4 floats
Why are you disposing them?
Could you reuse the container for next frame/run?
Yea
I normally keep all my containers around for as long as I can
Probably left over from old unity
And dispose in ondestory
What else are you doing?
Must be something else
Hybrid objects have a leak
Somewhere
@ocean tundra nope. Im not using Entities.
Just normal ijob
Hello, do you know if there is any performance benefits from using entities and the hybrid renderer only for static environment objects, in an otherwise standard Monobehaviour project ?
Should this "Auto load scene" work in build?
yes
๐ค the ConvertToEntity checkbox should be auto ticked because of the subscene though. That's strange Nevermind, that's the case for children, not the scene itself, my bad
whoooa, i tried to add convert to entity to subscene And something really strange began to happen. Tones of errors, empty new gameobjects in scene after exiting play mode.
my component displays a little more info on what scene is opened or not
& i can load entities in the editor from this component also
You're not on latest versions ?
Anyway, saving your subscene (eventually closing it?) should serialize it to disk and yeah it's supposed to autoload on a build
Just to be sure, new build workflow ? not the legacy one ?
Soooo... i have written a system which takes about 13-14 ms to execute each frame... is this considered "slow" ?
that's 70+ frames/s
but still yeah I'd consider it slow
depends on how many entities, what workload from your other systems
could probs improve perfs yeah
Thanks ! That system is a bit ugly... i basically acess mono components in there ( Animator... ) to transfer my data from the components into that animation states... well, then i need to take a look at what i could possible improve
If you did all you could do, don't get crazy and review later
If you're working with mesh data, I guess that's expected to be heavy
๐คทโโ๏ธ so yeah depends a lot on what this system is doing
Hmm... is it possible to track the performance of single Entities.ForEach operations ?
Instead of the whole system ?
2020.3.1f1 entities 0.17
with build configuration one?
Yes with a profiler marker
@karmic basin Any tutorials on that one ? ^^ Or any examples ?
@karmic basin i don't use new build workflow. Today i have tried to find some docs, but only found few forum messages
With DOTS you HAVE TO
Thanks a lot ^^
where can i read about it?
Like first page of the manual
O_o
Uhmm... another question... im using those "Object Components" as some bridge between gameobjects and ecs. Is there already some way to let a Entities.ForEach with them run scheduled ? Normally the acess to Object Components was main thread only
Not sure. I would capture relevant data on main thread and pass it to jobs in allowed collections
i see. I was skipping this every time because whole page named ProjectSetup
thank you๐
^^ + they only detailed this on 0.17
Took me a few days to understand it was a problem, because building from the menu looks like it kinda works
yes!
So at first I duidn't understand subscenes workflow at all, when the basics are simple
@stone osprey what k said but also 13ms is very slow for 300 matches even main thread, would prob figure out the root cause before hiding the cost with other threads
@hollow sorrel Thanks, im gonna look into it, its once of my only systems that heavily interact with unitys Animator and AnimationClips. Probably mess up somewhere
I do a lot of lookups in there each iteration for example to override animation controllers
// Override animations
Entities.ForEach((ref Animation anim, in AnimatorOverrideController animator) => {
var animationState = anim.state.ToString();
// Get animation from database
var contentStorage = database.GetContentStorage(anim.clipID);
var replacementClip = contentStorage.Get<AnimationContent>();
// Receive a list of all overidden animations
var overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
animator.GetOverrides(overrides);
// Check if replacement already happened for prevent it from doing this every frame
var clipToReplace = animator.animationClips.FirstOrDefault(clip => clip.name.ToLower().Contains(animationState));
if (overrides.Exists(pair => pair.Key.Equals(clipToReplace) && pair.Value != null && pair.Value.name == replacementClip.ClipName)) return;
// Replace the animation of the certain state with out new animation we wanna play
if (clipToReplace != null) {
var animatorr = animator;
replacementClip.Clip.LoadAssetAsyncIfValid<AnimationClip>(handle => animatorr[clipToReplace.name] = handle.Result);
}
}).WithoutBurst().Run();
For example this here
arrrgh, every time feel pain installing preview package
Right top you can see the alloc of the system... i bet this is too much garbage created each frame, right ?
thats a lotta allocs
the overrides list you can cache outside the foreach, and instead of using linq firstordefault a regular for loop will be faster
then you still have a whole bunch of string allocs but not sure how you can get rid of that, i dont use unity animator
if you can use id's instead of strings that'd be better
Thanks im gonna try that ^^ Yeah... im using FixedString32 but well... the unity mono stuff uses regular strings, so i need to convert the fixedString32 to its string form which also causes massive gc allocs. The problem here is, neither string nor FixedString32 provides any method to compare each other without any allocation happening :/
yea fixedstring prob not gonna help
but clips should have an unique id i think, if you could use those for comparison instead of name thatd be nice but not sure if possible here
@hollow sorrel I really should do that :/ Its just so much nicer to use strings because its more readable xD
Besides that... Any idea how i could implement a FixedString32 equals method which compares itself to a string ?
Without converting the fixedstring32 of course ๐
I assume that causes like 90% of my allocs right there
Pretty sure theres a clipname to hash function for animation
@safe lintel I need to look into this ^^ Nevertheless a better equals for the FixedStrings would be great... something that uses pointers without allocating a new string every time
What the hell... my optimization approaches are not working at all ๐ฎ
well you could create a FixedString32 from the given string once and use that one for comparisons. Comparing FixedStrings is cheap and fast
Thats probably a smart idea... does this allocate anything ?
In general you could try to keep the usage of strings within ECS to a minimum and only use them when interacting with your "traditional" OOP layer for stuff that is not yet ECS native
it only allocates the length of the string on the stack in form of a struct
On the stack only ? That sounds fine ^^
That shouldnt count as a gc alloc call in the profiler, right ?
you can always try and measure ๐ especially with performance related metrics, measuring is most of the time faster than guessing
Im still a noob in terms of profiling... For example this here :
// Play animations
Entities.ForEach((ref Animation anim, in Animator animator) => {
var clipName = animator.GetCurrentAnimatorClipInfo(0)[0].clip.name;
// Set state and override animation to the one from our animation component, for triggering transistions
foreach (var trigger in anim.triggers)
animator.SetFloat(trigger.Key.ToString(), trigger.Value);
anim.clipName = clipName;
}).WithoutBurst().Run();
A little system i wrote... it basically sets a variable inside the animator to play an animation
And the profiler tells me that it causes garbage
About 400Bytes
For one single entity ๐ฎ
And i have no clue why
Theres no allocation going on... atleast i see none
toString() allocates
no idea what SetFloat does internally, haven't used that for some time, but I guess some string comparisons and allocations as well
Hmmm... is there any way to convert a FixedString32 to an string without allocation ? I assume not, right ?
Thats a dumb question, of course theres always an allocation
I mean if theres a smarter way
Or any to prevent this
there is not
as far as I know you have to allocate... I do not think there is a way to reuse the memory of fixedstrings for string even if the memory is on the heap
Oh thats great :/ Damn... that makes it awfull for many entities
comparing fixedstring to a string should be doable tho, dunno why thats not built in already
it is, but it uses ToString().Equals(other)
Yep it is... i already wrote a extension method which does not allocate ^^
Simply loops over its chars/bytes and compares them
:+1:
Probably i should use a class instead to store strings. This way i wouldnt be forced to conver them each frame
But then this cant make use of burst...
But that doesnt matter because its running on the main anyways
is this system only about driving animation triggers ?
does this need to happen every single frame for every single animation ?
Cant explain everything but it works hand in hand with the networking... i receive packets from the server which manages the animation states and i write it into the ecs for triggering the translations
hmmm
actually not
can you separate the part of making the decision of which animation on which entity to progress and the actual setting of the value? the first part can probably be done completely without any OOP part, only when actually updating the animation is it important to interact with the real animation system. At least that's my guess from your code sample
Yes, that should be possible ^^ i store the "state" inside the Animation struct. I only use that to tell the animator it should which conditions are true. But Those do actually rarely change. So i could mark them somehow to trigger those iterations when they are really needed
This alloc thing is weird
I call this method in one of my iterations :
With those comments in there... guess how much it allocates per frame ?
240 Bytes
And it doesnt make sense at all, why should this here allocate bytes ?
what is the allocation per call ?
The profiler wont tell me that... atleast i havent found any way to acess those details
try enabling deep profile
But well, i have one entity which matches the loop. And in that entities.foreach iteration i call that method once. So i assume that its 240Bytes per call. Which kinda fits the 0.9MB i get for hundreds of entities
Im gonna do that ^^ one moment
or you could add profiler markers into the function
The lambda job 3 is my iteration above which calls that GetClipByName method
Without GetClipByName its allocation is... zero
But well, my method is pretty empty besides that loop :p im also gonna add some profiler markers in there for the next debug
how does the bracket operator look like for the AnimatorOverrideController ?
I thought the same... but im not using the bracket operator for AnimatorOverrideController, im using it on .animationClips which is a "AnimationClip[]" array
Heres the profiling for the GetClipByName method
And well... 240 Bytes allocated within one call
Oh wait
Is this the problem here ?
in your first screen the get animation clips access on the animator seems to be the offender
I see, i see... the ".get_animationClips()", right ?
I try... its not mine ^^ Its from unity itself
k then I can find it myself ๐
This makes it even worse
Actually i only acess the array... why should it even call those weird ".get_animationClips()" methods ? Where they ? .o
looks like a copy of the internal list
so every time you access animator.animationClips, it returns a copy of the internal list as an array
Well, that explains the massive gc alloc going on there
I actually wonder why they implemented it like this
๐คทโโ๏ธ who knows, I haven't worked with animations for years
Thanks for helping me ^^ i think im gonna try to cache this somehow to prevent that copy every time. I hate that animation system so much :p
probably to make sure that there is no way you can edit the clips without going through some sort of API on the controller
if the data never changes, create a lookup for it once on creation of the system (or wherever needed)
so unless you add/remove clips to animators, this data should be constant
can it be that order of systems are different in editor and build? (Those systems that have no order attributes)
but there can be an issues that i can't understand just by playing build
i also wouldnt be supprised if il2cpp had a different order too
and while i don't know exact build system order i can't assume what cause issue
if your code has any dependancies between systems you should add order attributes
but otherwise order shouldnt effect your code
maybe youve missed a dependancy?
yes, but i want to minimize order usage
and there can be dependencies you are not thinking about
until it thrown an error
sounds weird to me
if the order matters then you need the order attributes
but ideally your code should work reguardless of order
and the worst that happens is the processing is broken up over frames instead all the same frame
Yes, but we use editor mostly to see how things works without do full build every time. So if things go different in editor and in build then editor idea is little broken. Maybe i'm not understand something
๐
i would look elsewhere for the cause of the error, rather then thinking it might be ordering
unless you know 100% that system X will throw if before system Y, and in that case you should have a order attribute
I already have fixed my issue and it's gone after i write order atttributes) In editor no changes happend, but build now works correctly
nice
i'm afraid about my future ๐
maybe there are more hidden order bugs in my project
i dont think ordering has much performance cost btw, its something done on start so not something to worry about
there is no performance cost, it's just system instantiation ordering
if you are afraid about ordering bugs, you might need more world tests in built players :>
in general all dependencies are logical consequence of some read/write collision or explicit defines, so there shouldn't be some hidden dependencies you do not know about
So i heavily optimized my gc alloc code... Basically via caching ( Did you know that even Object.name allocs ? Who the hell designed this ? ). One issue left... FixedString32.toString(); is there no way to get a temporary string from it ? Is it probably possible by writing an own extension ?
Wow... that cache system is the ugliest one i ever wrote... there multiple dictionary lookups in each entities.foreach iteration just to prevent the convertation from FixedString32 to string... or to prevent .name lookups... so damn ugly
why so many strings?
can you replace them with a enum
or numbers?
or even use the string hash code?
if you find a way to lemme know, i've tried also and it seems a .net string will always be an allocation no matter what because it's managed memory
pretty much impossible to have an unmanaged string because it'd no longer be a string (not including different types)
hmm well if the string names are unique what about using a checksum like hash ๐ค it doesn't exactly solve the problem of char* to string allocation in C#. But it's pretty much something I ended up doing for "nameable" ids
has anyone experienced an issue with hybrid renderer v2 where the screen goes black with certain camera positions?
hdrp v2 define added
it's been working most of the time, very odd, particular camera angles
hmm in frame debugger I can see the step
post processing hmm
your using post processing too?
yeah I guess I need to try turning all the effects off
oof turned them all off and no change... perhaps a default one is causing problems ๐
turn off post processing completly?
yeah I just did
black and white scene now but at least I can see something ๐
the culprit is somewhere in here ๐
i had soo many issues with hybrid renderer
was using it with URP + shader graph shader
was awerful
cant wait till the update it so it works
๐
oh man it's still pretty buggy
but it's getting there ๐
the culprit was bloom
I don't get it though, there is bloom in the default settings, and then I have a global volume override, but they don't seem like the same thing...
turn off override, it calls back to default, fine
turn off default, scene changes, even though I have the override enabled
hmmmmm
I must be misunderstanding how this works
I don't know how bloom makes the entire screen turn black though ๐
stop NaN's on camera fixed it
Hmmm... Lets say i have an iteration which looks kinda like this...
Entities.ForEach(...) => {
.
.
.
if(someCondition) return;
SomeClass.InvokeCallback(() => {});
});
Would this execute gc alloc each iteration ? As far as i know lambdas require a gc alloc... I would also like to know if it would alloc the lambda each iteration, or just when the condition is met... any ideas ?
The lambda has no capture variables so the new action will be cached statically and reused each time.
that's cool, had to look at SharpLab to see what the compiler would do lol
I'm confused. Why can't I set an Entity variable to null?
What should I use in its stead?
Because entity is a value type and not managed (or a ptr most likely in your case). Use Entity.Null instead
oh, ty
I was already starting on making 2ndary vars bool myEntity exists;
lol
typo psudocode
Another dumb question, what is the standard way of linking entities in my scene to be used in scripts?
I think I could make a script to assign this to a singleton's public static entity SpecificEntity;
But every single Entity would require a custom script
I'm not going to endlessly ask questions.
These two would be good for an hour
Wow, funnily enough, this is the standard way of doing stuff!
using Unity.Entities;
[GenerateAuthoringComponent]
public struct Enemy : IComponentData
{
public Entity currentTarget;
}
So like then you assign it to the singleton. I suppose what I will do is have an Entity variable and an index variable to know what Entity it is to feed into the right singleton value. It is crazy you can't just assign it into a Monobehavior.
They way they're doing it seems pretty dumb: They should probably fix that so you can drag and drop ENTITY stuff into monobehavior that declare public ENTITY myEntity;
As it is now, when I declare a: public Entity myEntity in a monobehavior, UNITY doesn't let me drag and drop anything into that slot. I add public int i; and it lets me drag, so its definitely not liking autopopulating Entity on monobehavior.
Entity has no edit time representation
Well it could
Simply link scene index to what the translation becomes
Super simple
You're meant to build traditional gameobjects/prefabs in the editor then use converison to change them into entities
Yes, I know, but if the gameobject to change into entity is in the scene, it could have an index
Which translates to the entity
Its not even tough to think about
Welp, I'll just accept the DOTS programmers made a UI error. I've worked with bad UIs in the past like Starcraft2 mapeditor
Maybe they can fix it later.
Interesting way of looking at it, good luck brother
Thanks bro. I probably should be working at Unity, lol
Ok, seeing how basic functionality is missing, I have to ask: Have they added a Debug.Log facsimile in DOTS, or is this article still relevant: https://forum.unity.com/threads/as-debug-log-is-a-problem-in-job-i-made-this-simple-trick.860464/
You've been able to use Debug.Log in bursted jobs for a few versions now
Look at burst function pointers too
https://docs.unity3d.com/Packages/com.unity.burst@1.5/manual/docs/AdvancedUsages.html#function-pointers
@slim nebula Thanks ! but what if i use variables inside ? Then it should use gc allocs right ? I
@ocean tundra Thanks im gonna look into this ^^
yup. then it reallocates every time
@slim nebula Thanks... that explains my damn gc alloc calls... the profiler couldnt find the exact position so i needed to guess. Guess i need to find a cheaper way
the capture variables compile as member variables on a class. If you're using the lambda class on multiple threads, you need multiple instances of the captured variables, hence multiple versions of the lambda class
since the language doesn't know if you're using multithreading it just always does it
In my case i dont use multithreading ^^ it actually runs on the main, the example above was just simplified ๐
then just use a static function in your system, and set member variables to replicate the captures
I think a good alternative is to dispatch commands into a queue for executing those callbacks else where
@slim nebula Member variables ? You mean params ?
if the thing you're passing the lambda has X params and you need to capure more variables (Y) to use inside the function body, then you can create static member variables for Y, and the parameters (X) still get passed in the function prototype normally.
but the function prototype matches the caller requirements, if you need more variables you use a class variable
w/e there's many ways to work around the issue. whatever works for ya hehe
I Thanks, im gonna try a bit around ^^
I've been reading up on Utility AI/IAUS and thought that from the outside - DOTS would make a good choice for a prototype. Many NPC entities need to consider and score many things in parallel - but when it comes to implementation I have some questions with the ECS style model. If for example, one of my AI considerations is - "distance to nearest tree is less than 50 units" - how might I go about calculating this or rolling this up into component data? Should every NPC have a list of all the trees within a radius of them that is constantly updating? Is that too much data to store? If there are trees instead as entities and I just want to do some basic distance math - can I query for tree entities while I'm working on a different entity? (e.g. in an NPC entity foreach, can I then query all of the tree entities to get an updated list of nearby objects?) Kinda just thinking out loud here but if anyone has any thoughts I'd appreciate it ๐
at a high level, yes you can do all those things
more specifically ECS is a way to store data and a framework that compiles into native code that operates on that data. you still need to structure and organize your data (index/hashmap/whatever) depending on your requirements. I think there are many ways to approach what you're planning
Re "In an entity ForEach I can query for x" You cant run a query/ForEach inside another
@turbid sundial Have you taken a look at unitys AI Planner
That's good to know - what might be a good way to determine "nearest tree", if that needs to be constantly updated
its on hold now but was looking good
I have yeah, I'm just experimenting at the moment - trying lots of things
could dig into its code to see how it did things
Tangentially related - if I were to build a procedural world with trees - but I want to cut down a tree, travel a thousand miles - then come back and make sure that tree is still cut. Initially my mind goes to instead instantiating the trees procedurally and having a list of "cut" trees, and preventing them from being instantiated if they were in that list - but 1) that doesnt seem like it would scale well into late-game and 2) it doesn't take into account trees that a player might plant themselves
Arent you actually storing each chunk ? Well actually only those chunks which were modified ? Atleast thats how minecraft does it... player travels trough the world, chunks wont get saved... player placed a block or modified the chunk, modified blocks are getting saved into its own textfile.
Those are based on seeds, that means when the player comes back some day, the chunk generates the same chunk based on the seed. Then it removes/adds blocks based on the added/removed log from the chunk file
Yeah chunking them like that would definitely be more scaleable - I guess ultimately there will always be a limit though
that's a good point though, thanks
Confused on DOTS.forEach. What is the syntax to read three variables? Entity myEntity; int index1; int index2;
๐
all in the docs
basicly you cant attach raw types (int) to a entity
you need to make a struct containing your data, attach that, then you query for that
using ref (for read write) or in (for read only)
there are also some special values you can get which are indexes
maybe you were trying to get those?
Of course I had a struct but it wouldn't let me post it here. I let me see if I can link the problem: https://old.reddit.com/r/Unity3D/comments/mfxqf6/confused_on_dotsforeach_what_is_the_syntax_to/
1 vote and 0 comments so far on Reddit
so replace your ???? with
in DEntity data
You access (ask for) the struct not the individual fields @remote crater
and if you want THIS entity then your first paramater will be Entity
So: .ForEach((ref Entity entity, in DEntity data) =>
One final question and I assure you I'll stop asking questions for many hours: How do I access index1 to print? UnityEngine.Debug.Log(data.index1.ToString() ); //gives an error on run: Burst error BC1016: The managed function int.ToString(int* this) is not supported
dont tostring?
Dif error
or use string interploating or whatever its called
the $"{variable} text {nextvariable}" syntax
yup
Shoot I said I wouldn't ask another question, but I guess its clarification on the same!
๐
Thanks everyone, you rule.
Hey if I make a bunch of money on my game, and you remember me and you see me or email me, I'll send a brown manilla envelope in the mail.
haha
๐
Hi! I understand correctly, if value type parameters are captured, then there will be no allocations though, right?
iirc value types get boxed for lambda captures, which makes sense since the lambda updates the values if read outside the lambda afterwards.
so no, still would allocate a new lambda object each time it's used
If you just use a normal function instead of a lambda, and store what was previously a capture variable instead in a class member variable.
the problem stems from multithreading. if these callbacks are all running at the same time with different captured values, then you need to cache those values somewhere for your function to use.
you could create an array of classes in a static list so it's not allocating 100 each frame, but 100 up front and reusing them or something like that
I dunno there's many ways around it
a lambda function is just a new class with a function matching the lambda prototype, and boxed member variables for each capture. you could code this out the long way and adjust from there to reduce allocations
ยฏ_(ใ)_/ยฏ
I dunno if I"m helping
I think it depends on the specifics of the problem
Thanks for the explanation, helped a lot ๐
https://i.imgur.com/8bCq3yR.png
MSPaint graphics style. This is a procedural streaming system. Blue circle is where the player currently is, as he travels left - the chunks obviously change (standard procgen stuff). In my DOTS design, when the player moves a set amount - I create a new array with all the positions, create chunks that don't exist yet, and keep chunks that already exist and should still exist after the update. However I'm not entirely sure what to do with the cleanup chunks (now in red). One thought I had was, before doing any updates - apply a DeleteTag component to all the chunks that exist - then as we go through and find ones that exist and should still exist, take that component off. I worry that this touches too much though? Any other good ideas?
probably better to keep lists of your chunk entities
and not use tags
as each tag add/remove is a structural change
but then it kinda depends on how big each chunk is as the bigger they are the less they move in/out of range so less changes
could go with dynamic buffer of neightbours? when all neighbours are remvoed you can delete it?
i was meaning seprate native lists within a system
actually
this is your v0.1 right? as in just starting?
i would stick with tags, and add/remove whenever needed
when your further along and needing to optmize theres a change that Unity will have optmized tags by then, OR you could do any of 100 other things ๐
so im also planning some chunk stuff, my plan was to have a single component storing every directions neighbour
and use Entity.Null to tell if they exist or not
suddenly the DisposeSentile.Create()s in unity physics are taking 25ms ๐ wtf did I change ๐
yeah burst is on lol
I was running at 60fps no problem yesterday, now 20
it's all physics dispose sentinels
but I don't know why now lol
turn off safty checks?
I did that with no effect which is odd cause DisposeSentinels are safety system. But more to the point, I haven't had this issue with safety checks on before
close reopen?
I need to go through source control and look at every change in yesterday's check in lol
I restarted PC ๐
clean librarys folder?
@ocean tundra lists of the chunk entities is what I have - but the entities that are already instantiated but no longer in range need to be cleaned up - which is why I was thinking add the "Deletable" tag to all of them, and remove the tag if it is still needed
Maybe that's a weird way to think about it though
Ultimately the entities that are no longer in range need to be removed somehow
na it will work quite well
you could use the EntityManager EntityQuery opperations
they are the fastest
Hi, playing around with some code rn. How would an Entity field in a struct work? Is that a reference to an Entity? And would having that reference be a bad thing in ECS?
I found this on the docs but was curious if anyone could tell me if it was bad to do or not:
Also curious which of these types it would fall under:
It is the last dot point, a struct containing unmanaged blittable fields
and yes you can store references to entities in your components
it is like a reference in the sense that you can use it to lookup an entity, but it is not a reference type
it is stable in the sense that an entity will never change it's Id or Version, and it is unique.
@sage mulch
Thanks!
Ah this was where I was confused
Sooo... Im trying to write a deserializer for my packets to convert the content into structs for attaching those to entities.
IList<object> FromPacket(Packet pk);
As you can see im running into a problem... Boxing, but the returned list needs to store objects because the packet can contain multiple different structs. Any smart idea how i could return a list of different structs without boxing them ?
IList<struct> ? ๐
Allocate ptrs with your data so you return the list of ptrs instead of the boxed references?
That would be pretty smart, totally forgot that c# has pointers ^^
You could also do that with one ptr tho idk what's easier to do but one should be more performant
TO be honest dots feels more like C++ than C#
:D im gonna try around a bit till i have something working... Yeah, atleast when you go into detail ^^
Besides that... lets say i have a List<IComponentData> and i insert a Player : IComponentData{ FixedString32 username }... does this box ? The struct implements the interface so i would assume not... or am i wrong ?
if you access structs through interfaces, they are always references and therefore boxing occurs. If you do not want them to be boxed, use the actual types directly
Damn... Ah fuck it, ill just go with pointers. Who doesnt love pointers ?
if you don't like the boxing, maybe your approach is flawed and you need to look for another approach, depending on the reason for why you do not want boxing to occur
Well it causes gc allocs during the frame which is kinda bad for the performance.
then why do you need the interfaces to access the data ?
I dont ^^ But as i said before... i deserialize a packet here and it needs to returns a list somehow to attach the deserialized structs to the entity
I just thought a List<Interface> would avoid boxing
using a list in general will allocate for whatever you throw in there. If you know your types and you only want to pass them to the caller, use the low lvl variations for your structs like Unity.Collections.NativeList or something similar
And i dont know the types... its some sort of generic packet. Some kind of build instruction for entities on the client :/ So i cant use a specialised list like List<Player>
well, then you might be stuck with pointers or try to disassemble the packet reading into something less "generic", as you always have a finite set of types that can actually appear and for which it might be possible to create specialized structures/caches
unless ofc you have no control over what the other side can potentially send you
@karmic pilot Alright, thanks ^^
Besides that... is it normal that an ECB allocates memory ?
Well the creation of the command buffer
Is there any way to cache this ?
Or is there any way to check if a command buffer is still valid ? I remember that i often received errors that told me i should create each frame a new command buffer
Did you profile this in a build? Or at least with all safety checks disabled? Because DOTS does a lot of things differntly when enabling safety checks. For example using a standard List instead of NativeList to store command buffers
Does anybody know a good trick to copy an entity into an archetype? I want to create a copy of an entity which only contains the components in a specific archetype. I could use a ForEach with all components as in parameters and then attach them to a new entity via ECB. The problem is this reaches the component limit quickly and does not handle optional components
@pulsar jay Havent profiled it yet.. but i think i should, thanks ^^
Does anyone know if i really need to call .CreateCommandBuffer each frame ? Is there some way to cache this ?
If you follow the CreateCommandBuffer call you can see what happens
It will just get added to the pendingBuffers list
Which gets executed (flushed) and then cleared in OnUpdate:
protected override void OnUpdate()
{
FlushPendingBuffers(true);
m_PendingBuffers.Clear();
}```
Hmmm... so that means we could actually reuse one command buffer ? We would just need to add it to pendingBuffers manually ?
Thats not what I wnated to say here ๐ฌ
It might probably work but it is definitely not intended
It is intended to just be called each frame
As the command buffer is a struct it should not allocate memory on the heap (at least without safety stuff enabled)
Well... the problem is that im playing around with reflection because i cant acess the internal methods ( yes i tried using those fancy asmrefs )... and creating a new ECB each frame kinda breaks my reflection calls. I convert the methodinfo to a delegate to prevent unnesecary gc allocs. And when the command buffer changes each frame, i need to convert it each frame... so i actually want that i can use the same damn CommandBuffer :/
Ok I see the problem now
But the methodInfo is created from the type (which does not change) so you could cache the method info and then just invoke it on the newly created command buffer each frame?
Yeah i also thought like this... and it works, but... it causes a massive amount of gc allocs. Because we can only pass a new[]{ entity, cmp } into it. This creates allocs and .Invoke(); also causes gc allocs. Thats why i went with the delegates instead :/
So i either accept the massive gc allocs... or i find a way to reuse the same damn ECB
Damn im gonna start a petition to force unity to just make all their internal methods public. This would make development much easier
You can already ready all the DOTS code because its in packages but it would at least allow forking
I would second this. Just recently had the same problem with running into a lot of dead ends with addressables as everything is internal ๐ซ
Oh btw @stone osprey maybe you can use NativeStream instead of a List of ptrs
@pulsar jay Oh damn.. im also using adressables but i didnt had any issues yet... but im using a hybrid system where i just use the ecs for the data... go's are used for rendering in my case ^^ @north bay Hmmm... thanks, im gonna look into them !
I think im gonna look for a way to reuse command buffers... They even have a dispose method, so i bet theres someway to do that
Is boxing/unboxing shown in the profiler ? Or is it just "known" as gc alloc in there ?
How do you handle referenced entities that might have been destroyed? I have a lot of stuff like this: var targetLTW = GetComponent<LocalToWorld>(targets[0]); where it will throw an error if the target has been destroyed. Do I have to check if the entity is still valid in any system that accesses the target buffer or is there a better way?
I run a HasComponent() first. That should prevent this if im right
Can you clean the targets array up in some way?
For example I have a DestroySystem which runs after the EndSimulationSystemCommandBuffer but in the SimulationSystemGroup to destroy all entities flagged with a DestroyComponent.
This makes it so that all entity references are valid when CommandBuffers play the changes back (that was a huge pain for me before introducing that system).
But this also allows me to run a system after that DestroySystem which would clean references up and set them to Entity.Null.
I tried this some time ago and it didnt work as expected (the cleaned up targets where still found by later systems). I did not really understand the dependency management back then though. I guess I would have to make the other systems depend (call complete) on the clean up system (or run the clean up system before a sync point)
Quick question... does unboxing also create gc alloc calls and result in garbage ?
gc allocation usually happens when you convert the value type to a reference as you then need the indirection. unboxing is retrieving the value and should not allocate additionally (ofc there is now a copy of the unboxed value on the stack/register/wherever the value is used)
In general to better understand boxing/unboxing in C#, especially when it occurs, microsoft has a really good article on it in their docs on .NET
@stone osprey As nasty as it is, codegenerating a huge amount of code to advoid boxing is pretty easy ๐
hmm but i see you want it into a list, It it a list of ANY components, or 1 component?
my networking syncs all the 'same' data together in the same packet (meaning i probably have too many packets right now :P)
but allows me to simplfy some code around handeling the packet as i know all data will be the same type/sizes
one of my earlyier tests had me generating a struct that contained a native list for EVERY networkable component type (so there were like 20 lists in that one struct)
Any thoughts on how to get a singleton entity inside a monobehavior? It seems GetEntityQuery is not available inside monobehaviors so
World.DefaultInit.......EntityManger.Get(Or Create??)EntityQeuery
depend on if your using many worlds
or just the default
i use that to Create Entities from my Networking lobby
BUT my networking lobby script is added to a gameobject with convert and inject
so when reading/updating (using querys to change menu state) i have that in a system instead
I'm just not at all happy with the character controller in the physics samples so I'm trying to have a lot of data for characters in ecs but the movement needs to be on a gameobject
if your doing alot of hybrid you should probably have all the stuff in systems/ecs and use gameobjects as 'Views'
as otherwise what is the 'truth' for your world ๐
like is ECS data right
Is MB?
Or is it a mix, for players the truth is MB, for AI its ECS
ect
I mostly need to access the character controller's .move function
that can get pretty confusing
Because with ECS there is actually not a simple way to move an object with collision without rigidbodies
ah i guess not if your mixing physics
You would actually have to write all the collision code yourself - I don't even have unity physics (dots) installed right now
well you could call CC.Move from a system
using without burst and run()
but you would also need to find a way to send all the collision events though into ECS data
not too sure on the best way to mix legacy MB/Physics and ECS
I'm not sure if the character controller converts to an entity well. They have a really, really crappy ECS character controller in use cases examples but it was clearly just written to show off that it works it's impossible to understand or work with
im guessing the DOTS shooter CC is even more complex ๐
I mean unity devs are still wrongfully obsessed with rigidbodies. I have no idea why they haven't figured out yet that most games dont use rigidbodies for their main characters
honestly no clue, I dont usualy make character type games
normaly focused on RTS type ones
and definitly dont have RB's on them
well untill they die ๐ then it can be fun watching them all fall
Anyways this works - thanks for the advise
SysInputGathering inputSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<SysInputGathering>();
Entity ent = inputSystem.m_HumanoidInputQuery.GetSingletonEntity();
if you do World.DefaultGameObjectInjectionWorld.EntityMangaer there should be some sort of get entity query method
so you dont need to get a system first
but depends on if you want that system for other things
probably a good idea to have a 'bridge' system that most of your MB stuff uses to communicate into ECS