#archived-dots
1 messages ยท Page 34 of 1
How do you handle writing to same index twice? @viral sonnet
WorldUpdateAllocator is also cleared automatically, right?
That's why you need to recreate it each frame
same index in 1 frame doesn't work.
i tried making a persistent NativeStream but it doesn't make much sense
Does the WorldUpdateAllocator automatically clear? And can it be used in a job?
so If I have two systems producing damage events that can't work with nativestream
So it's basically like a better tempjob
yeah, you'd need 2 streams
That's what I thought
or you make sure with some form of index that it's only written once. but i don't see the point really
i also had the same problem, not really with damage but spells that are fired which can come from the caster, effects or triggers. i need 3 streams, well in my case custom parallel lists.
I made a custom parallel blocklist implementation similar to the one dreaming has, for this reason
This is cool, thanks for sharing the code!
Couple of questions. It looks like you are iterating the target types and copying from the source to the target. Do you assume that the source has all of the components that the target has? And this doesn't work with dynamic buffers, right?
i've used his blocklist too in the beginning. now i'm using https://github.com/enzi/Entities.Exposed/blob/main/Collections/ParallelList/ParallelList.cs
I set archetype before doing any of that
exactly same, so yeah
they have all same components
ah got it
oh right @rustic rain what i wanted to ask. for the method you posted earlier you need to have the correct entity already and not a deferred entiry from ecb, right?
yeah, it's structural changes method
doesn't look like it would scale that well
@viral sonnet why the switch from a block list to list? Isn't block based list better?
What's the intended way to fetch system state entities? GetSingleton or use the systemhandle
using system handle seems more robust
to prevent allocation time
but you get more allocations if your list grows?
That'd make the system run even if it doesn't exist though, unless you also require the singleton in oncreate
But it should be created by the system in on create, no?
I never really do that ๐คท but it's certainly possible I guess
I'll try both and see what I like more
i set the capacity so the resizes are minimal. also, reading and merging to 1 list is exceptionally fast
that's why i dropped the blocklist. reading and merging was so slow
Still kind of weird that if you stick state in a component it kind of breaks encapsulation, unless you also somewhat manage that state in the component itself, which isn't really in the spirit of dots
I see, but to be fair with a block list you could just set the block size to your capacity and experience the same performance
sure but it's not persistent so the alloc time will eat into the frame budget
persistent?
i've written it for a very specific reason. a parallel job writes data and then, due to race conditions, the data needs to be read in a single threaded job. the parallelList is best of both worlds for writing and then reading
the parallel block list is created/alloced on every frame. the parallelList is persistent over several frames.
that's good then! ๐
i asked dreaming if he could make his list persistent but he didn't want to
the way it was setup is was quite annoying to rewrite
and as i meantioned before, the biggest problem i had wasn't with the writing but then reading. if you read in parallel, perfect. if you need to merge though, quite meh ๐
so much about high performance code is writing the right data containers that are perfect for the job
with burst i never had once a case where just instructions/arithmetics were a bottleneck. it's always data and data access
InstantiateInto
I've seen the same, it shows how good dots is and how it's pushing at the limits of the hardware, memory access is the bottle neck
Although I'm guessing that memory access is also already optimized in burst, I've never checked though
An ugly workaround would be to reinterpret the state struct to another private one that the system can access that has all the system specific methods
I'll just manage the state in the component, I don't really care whether or not it's dots conform ๐คท
It would still be exposed to other systems tho?
To an extent sure. But if the methods are named and commented properly it makes it more clear what's going on instead of just have a single list in there
just a few days ago i found a regression in one of my jobs. the job iterated on actors and processed combat events. for actors that only had a source event and no target event i had new timings of 2.5ms instead of 1.5ms. turned out when i rewrote my stat system i also acquired a stat byte* and read the health when it wasn't neccesary. well, i moved the data access and again down to 1.5ms. so, just that. reading a health value from a byte stream that's located in an IComp. (really inside the chunk, not outside so can't get any faster really.)
mhm, I don't think this is anti dots necessarily
afaik you aren't supposed to have non-pure methods on your data containers in pure dots
if they are simple its fine
Depends on who you ask
just to improve the interface
I'm sure mindstyler would disagree
well in that case, it should not be allowed to have any fields inside either, because those are just abstractions over the underlying bits
Well no, since it's only data
just make all components empty, with an excplicit size lol
The point of DOTS is to separate state and behaviour

an integer is just a type of data
Besides, I don't really care. I'll put methods in places if I think it makes sense
Unity breaks this convention in their code as well fyi
I know, I'm on your side, just showing how absurd it would be if one followed that view dogmatically.
mindstyler has analyzers that throw compile errors if they put a method in an icomponentdata
basically an int field can be seen as a method that takes the underlying data and reinterprets it as an int
That doesn't change the data though, so it's fine
According to the data oriented design book, if I recall and to be pedantic, everything in dots is kind of data including systems
So system in component is allowed, nice ๐
Yeah it's definitely a design thing
Unity recommends no methods though, but again, they also ignore that same advice
when a method is reused a bunch of times and code duplications starts to happen it's much better to put a method in a comp it is related to. (if it is)
could also go to a static method but for readability it's much clearer
Some people will die on the hill that that method should then be static
You just cheat and put all the methods in extensions
haha
Everyone happy
yeah extensions are much nicer
the biggest problem is how to make a dev aware that the method exists
Yeah I think at the end of the day everyone has to figure out what works for them / their team, a lot of it is too pedantic imo
in teams i often had a problem where methods were written multiple times just because a dev wasn't aware of some dumb namespace
i mean, how should he?
I'm also very good at this and I'm not even developing in a team
a lot is way too pedantic. namespace discussions alone. god damnit i nearly went mad sometime
like WHY in gods name do you care so much about how a namespace is called.
and why do we need 30 of them
Hey in the startup where I work people accept PRs even if the tests fail
lol how does that happen? ๐
They click the red button that says "accept anyways" or whatever it's called on git ๐
We accept prs when tests fail but you can't merge with a failed test
Oh, I meant merging
Hard prevented
I am the only admin
Well yes, I meant in my case
But yeah that's dumb because if they're failing tests then once merged everyone will fail tests
exactly
At which point just delete your tests
anyone figured this component?
RenderMeshArray
and then tickets take 5 times as long because everyone needs to fix the test and they have no idea whats going on
don't test. EZ
From memory issue it's just used to pass meshes to batch renderer
I don't think you do get meshes out of it
I need meshes out ofit
btw. entity graphics has a huge regression with performance. if anyone's wondering, will be fixed in upcoming 2022.2 beta
or I need to be able to define RenderTexture to batch renderer
That's not where they're stored
related to the new batch renderer
but description literally says it is
also
I checked manually all entities
they do contain their mesh in this component
Then use that component
but I can't figure a way to get index
sometimes correct index as is, sometimes it's index-2
I'm just confused
one example
the other example
red line is correct mesh
both at index one, but MMI value is different
๐ฅด
RenderMeshArray is not used at rendering time, it is used for loading baked entities.
If you would let me finish
Huh, you can't RequireForUpdate a system component?
You probably want to read this
Material mesh info usually does not point to the mesh in the array
It points to the mesh in the brg
๐ฅด
already registered I guess
And the whole thing is unmanaged
You can change what you render by simply changing index
no no no
The array is ignored once loaded
it's for selection system
I know
I need to render things now
I'm just explaining the system
I thought the docs explained it pretty well
See if the Entities graphic system has a method to get mesh
It's all there in the docs
Are system entities somehow different so they don't match a query?
system entities are just SystemState
all dropped in same archetype
Yeah, but they interact differently with entity queries
๐ค
It seems you need to set an option on the query to find system entities
So similar to prefabs, I just didn't see any documentation on it
Btw, if I create a random entityquery somewhere, I don't seem to get any leak detection errors, even if I don't dispose it
Yeah, I just saw that
I wasn't sure if creating them using World also auto disposes them
so that's why
Actually you can RequireForUpdate(EntityQuery) is your option there if you have EntityQueryOptions.IncludesSystems.. And RequireForUpdate<T> will soon include it too, similiar to how GetSingleton works :3
Yeah I know, I just wasn't aware that the queries don't match them by default without the option set
Queries created by GetEntityQuery or EntityQueryBuilder.Build(SystemBase or SystemState) will be disposed with the system. Queries from EntityManager.CreateEntityQuery or EntityQueryBuilder.Build(EntityManager) will be disposed with the World.
What happens if I write an extension method that uses the QueryBuilder api? Will the code-gen fail?
Depends on what you do with it I think it does cover the case of `SystemAPI.QueryBuilder().WithAll<SomeComponent>().Build().MyExtensionMethod() 
EntityQueryBuilder is not codegen
I think...
Not unless you use the SystemAPI version
^^^^ indeed (SystemAPI.QueryBuilder is, Unity.Entities.EntityQueryBuilder is not) :3
I'm talking about the code gen version of course ๐
I meant more of an extension method for SystemState, e.g. RequireSystemComponentForUpdate, that uses QueryBuilder inside that method
SystemAPI.QueryBuilder needs .RequiredForUpdate()!
SystemAPI support in utility methods is not yet a thing :3
btw RequireSystemComponentForUpdate<T> is just RequireForUpdate<T> soon tm ๐
Does anyone else have use for an OnFirstTimeStartRunning? I have having to check in OnStartRunning if this is the first run or not
I'll need to do that on all queries though if I have multiple in the system
wouldn't that create a lot of overhead?
That's all require for update is doing
The one important difference is if the system wouldn't run then you are adding overhead of dependency calls
But the point is more for systems that would be running nearly every frame anyway
But maybe not the whole system
The docs around system components and system handles weren't ready for the experimental release but we're aiming for it to be in one of the upcoming releases before the final 1.0 so there should be time for feedback.
btw is there anything planned for some kind of serialization / save system for ECS? (before I write my own)
or use mine in a few weeks! ๐
Ah cool, are you nearing a state you are happy with?
It looked really promising last time I saw it
is managed component support kinda reduced in 1.0?
Awesome, looking forward to it! ๐
Yes and no, ConvertToEntity is gone so authoring is really hard, but to access managed stuff SystemAPI.ManagedAPI will be there as the Managed version of SystemAPI ๐
and what is the best method to get entities from MB and to spawn entities from MB for now?
Ideally you should ask yourself first - Why are you accessing Entities in MB? Ideally you should use Systems to control your MB's from ECS data.
If you looked at all the options and decided to for some reason to stick to your opinion, then World.DefaultInjectionWorldSomethingSomething gives you the world, where you can get the entitymanager to access and edit your data.
I want to spawn building ghost from UI - to be precise from button clicked event
and I'm using UI Toolkit if it helps
UIToolkit should totally still work in systems. Someone in here can explain how, as I've seen people already doing it :3
The gist is you need a managed reference (one thing you can do for that is in your MB Awake function do: var e = World.DefaultInjectionBlahBlah.EntityManager.CreateEntity() and then World.DefaultInjectionBlahBlah.EntityManager.AddComponentObject(this).
Then var e = SystemAPI.GetSingletonEntity<MyMonoBehavoiur>()
Yeah just grab all your stuff from the baked components and then its pretty much like a monobehaviour (e.g. set stuff on the ui document, etc)
ok thanks for advice, I think I just drop foreach and do singleton instead, the problem was I can't make event lambdas inside Entities.ForEach
Ideally you should avoid using Entities.ForEach :3
oh I can't SystemAPI.GetSingleton() on managed components
nvm, I can get it's entity
wow I can't even get managed component
And that's why SystemAPI.ManagedAPI is a thing comming soon tm :3 (for now use the fact that SystemAPI.GetSingletonEntity<T> does work ๐)
but so what I can get entity if I can't get component from it?
I mean, how to use this fact XD
So you get the entity and then use EntityManager.GetComponentObject ๐
EntityManager has mostly everything you need to both access, and change components, SystemAPI will just often be slightly faster, cause it can cache stuff (check source generated output to see it in affect) but nothing wrong in using EntityManager sometimes ๐
thank ๐ completely forgot I can use EM ๐
@proud jackal thanks everything works now ๐
Yay! I'm glad :3
why can I not resize buffer in Baker?
huh? you mean setting the capacity?
yes when I try this, it would throw bunch of strange errors in my subscene
var buildingBuffer = AddBuffer<TileBuilding>();
buildingBuffer.Resize(sizeSQ, NativeArrayOptions.UninitializedMemory);
and additionally it seems that accessing buffer by:
var tiles = ecb.SetBuffer<TileBuilding>(mapEntity);
var tile = tiles[id];
tile.building = entity;
tiles[id] = tile;
is breaking whole buffer
resizing isn't supported in a baker. only at runtime. if you want a certain size, set the [InternalBufferCapacity(n)] of the IBufferElement struct
size of buffer depends on another component value so cant use [InternalBufferCapacity(n)] and I'm using it with value of 0 as it's a huge buffer
but then why accessing causes it to reset/break?
most likely the memory space is not setup
can you init the capacity at runtime when instantiated?
buildingBuffer.Resize(sizeSQ, NativeArrayOptions.ClearMemory);
I'm doing this in initializing system now
what is equivalent of RequireForUpdate<>() in ISystem for singletons?
most things are accessed through state state.RequireForUpdate<T>();
you can also use SystemAPI.GetSingletonRW<T>(); which sets a RW dependency for the scheduled job, not the Update call though
or without the RW, whatever you need
but still this doesn't work
thanks! โค๏ธ
You need to append to the returned buffer. There isn't anything in it yet
What you are doing looks more like you should be getting a typehandle on the buffer on the entity, and then just modifying it instead of using an ECB
strange, inspector shows that buffer has sizeSQ elements
https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/components-buffer-command-buffer.html shows it is for modifying
Huh, interesting. I always thought it was for replacing the entire buffer with a new one
Is there a reason you want to do it with an ECB?
Tbh, looking at the source for SetBuffer, it very much looks like it returns an empty buffer
oh maybe you're right
I can't see it reading the buffer from the entity anywhere
I wonder, how to use ECB to change DB, should I do a Lookup and then SetBuffer() to override it at certain BufferSystem?
Why do you want to use an ECB? Why not just directly set the contents of the buffer?
Hi, I got this. Is there any solutions?
You can try attaching a debugger to the editor
Well I don't know where to set my breakpoints
You can pause execution and see where the threads currently are
Thx, I'll have a try
It rarely happens to me to, then I just kill the editor
I change it to directly modifying DB but still shows the error
What's the error? And how are you changing it?
I have a job that needs to look at a referenced entity (not the one being indexed) and use a ComponentLookup for that. It just so happens there is a condition that needs to check the same component against the entity being indexed.
My question is about performance. Is there a difference between:
A) Use both indexed entity and other entity in the ComponentLookup logic, or
B) Use ComponentLookup for other entity and use the in Component arg for indexed entity
How do you have a C# Attribute inherit another C# ATtribute? I'm trying to do somethiing like this
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class BehaviorSystemAttribute : Attribute
{
}
So that I just label all my physics-related systems with [BehaviorSystem] and if I ever decide to switch away from FixedStepSimulationSystemGroup I can just modify the above code instead of changing every single system's attributes
Can't you just use inheritance, not this?
Inherit from UpdateInGroup, if it's not sealed
Right, but I want to automatically populate it with a system group behind an abstraction. I ended up just creating a BehaviorSystemBase with the required annotations
Would it not do that if your constructor set : base(typeof(FixedStepSimulationSystemGroup))?
That's perfect! Thanks!
Also, does FixedStepSimulationSystemGroup update like Monobehavior's FixedUpdate?
So even at SystemBase u should use idiomatic foreach starting at 1.0?
Well it doesn't work for managed types so....
anyway to go from List<T> to NativeArray<T>?
I don't think so, you just gotta loop and add em
Will idiomatic foreach support managed component at next release?
public struct FooComponent : IComponentData
{
public BarComponent Value;
public ValueTypeT GetValue => Value.Value;
};
is this okay?
cause otherwise code can become
myComponent.Value.Value.Value;
There is a way, first you have to extract the internal array and then convert that to a native array. But you have to setup a few helper classes first.
i've just redid it so i don't need to do that
i'll ping you one day if i'm forced to do it
Just check this repo if you ever want to do it, it's how I learnt it: https://github.com/Per-Morten/UnityUtilities
bookmarked for future
How to properly destroy Entity properly when GameObject is destroyed?
I get this error : Destroying object multiple times. Don't use DestroyImmediate on the same object in OnDisable or OnDestroy.
private void OnDestroy()
{
_combatEntityManager.DestroyEntity(_entity);
}
but you are destroying an entity not object?
Yes
do you get that error message from destroying an entity?
When MonoBehaviour triggers OnDestroy yep
Wait, could it be my companion link tries to destroy my GO as well?
Mono -> Destroy(Entity) -> Companion Link -> Destroy(GameObject)
namespace Unity.Entities
{
class CompanionLink : IComponentData, IEquatable<CompanionLink>, IDisposable, ICloneable
{
public GameObject Companion;
//...
public void Dispose()
{
UnityObject.DestroyImmediate(Companion);
}
//...
}
}
Yep, it destroys gameobject as well
Not sure how to do this properly hmm..
that's not meant workflow
so you'll have to create a bridge to entity world
either store EntityManager
and entity values in your GO
or switch to destroying GameObjects from Systems
That's what I did, I have a Bridge singleton, and _entity is cached in GO.
I see, so I have to create a system that destroys them
Ok understandable, when GO destroyed, add component data to the entity, and destroy from Entity world
no sir
that's not what I meant either
why is your GO even destroyed in the first place
the correct (ECS) way would be destroying entity this GO is attached to
Game -> Main Menu transition
are you doing ECS or OOP?
Hybrid?
ah, the worst ๐
well, from what I noticed, ppl do hybrid differently too
some do OOP game architecture while keeping some ECS elements or sub systems
some do ECS while using certain classic game objects with companion links
I'll give it a try with system that destroys their entity counterpart.
but that will destroy the gameobject
isn't that's the goal?
in perfect scenario - game object don't do anything but rendering
Yep, that's the goal
not sure it will work if you do like this "Ok understandable, when GO destroyed, add component data to the entity, and destroy from Entity world"
everything can be done from within ECS, unmanaged and bursted
since you will destroy GO twice then
That works
This, I'll try
Just remember that dispose will be called on the CompanionLink as soon as it is removed or the entity is destroyed. So all destroying needs to happen from the ecs side.
๐ค
I wonder if it's possible to make game object instantiation into entity burstable
or maybe Unity already did that...
considering enities with companion link get instantiated bursted right away
Companion link and gameobject is managed, it can't be bursted
but game object itself is not
it's in c++ side of engine
which can be called from Burst
and assigning to entity component is done unmanaged, because it's just index
and assuming array/list of managed components is pinned
you can fill it out of C++ as well
GO is just index? did not know that.
mhm
Ideally yes! :3 - At least if you wanna future proof the project, as well as save yourself a lot of iteration time :3
SystemAPI.Query
Indeed is!.. And IJobEntity is your threaded option :3
Entities.ForEach == bad comp time, and it also doesn't allow for normal syntax like continue vs return break etc.
bad iteration time?
last time I checked
it codegens into efficient IJobEntityBatch (0.51)
which was pretty much all required for best iteration
๐ฅฒ But currently idiomatic foreach I guess can't support managed component yet. Will next release have managed component support?
Indeed does.. But it's more a problem of CompTime, the dataflow analysis of capturing a lambda is really expensive.
Normal managed comps are already supported, and UnityEngine.Component support is comming
you mean for compilation time?
indeed
@proud jackal btw how to increase idomatic foreach max 8 parameters limit without using aspect? Something like custom delegate for Entities.ForEach.
aaah, I didn't realise what you meant by bad comp time ๐
I guess u mean the time taken to scan Entities.Foreach code before codegen?
yeah
even my IDE struggles
when I click inside lambda here
offering me dozens of potential arguments
ripping perfomance
๐ The thing I dun like Entities.ForEach is u always want to create temp var just for Entities.ForEach to consume
Could you guys remind me what class/file is responsible for SystemAPI codegen?
I want to take a look myself and see whether I can implement my own solution
for codegen
The act of doing codegen on a lambda == sluggish. ๐
.. In anycase it also isn't really a nice pattern in general, not very normal foreach by design, the fact that you can't break is not nice to newcomers. It also expects newcommers to think threading is as easy as flipping a switch, which it kinda isn't. foreach->Ijobentity gives you a better idea of oh i should add a number here kinda thing. But I digress..
All sourcegen code can be found in com.unity.entities/Unity.Entities/SourceGenerators/Source paraphrasing the file path. Then you should find a solution called SystemContextSytemModule, which contains a SystemAPI.SystemRewriter ๐
I see but not sure newcomer able to understand or not that the query is reversed. Seems a little weird. Haha.
Btw how to increase idomatic foreach max 8 parameters limit without using aspect? Something like custom delegate for Entities.ForEach.
Currently not a thing, aspect is needed to do that :3
Or again, IJobEntity that can take N amount
๐ฅฒ So no plan to implement custom delegate for idiomatic foreach?
IJobEntity can make it run on main thread only?
workaround could be to .ToEntityArray() on your query and do whatever on the entities, no limit on the amount of components you can access.
Btw @proud jackal how does idiomatic foreach compare to that approach?
does it have better performance? or just less boilerplate
it codegens into chunk iteration afaik
can i use memcpy to copy arrays from 1 place to another, and use size as TypeSize*LengthOfArray?
but the sequence in which you access each entity should be the same, no matter if you use chunk iteration or iterate the entity array? So if memory access is the bottleneck they should have about the same speed?
i realise now that Stride is the proper term instead of TypeSize, but oh well
yes you can but make sure that the source and destination are unmanaged or pinned managed arrays.
im mainly dealing with pointer arrays anyway, so that will be fine, thanks a ton!
if your array is for example: IntPtr[] that is managed, and would need to be pinned before.
ah, no, rather i meant im using c style arrays, like:
int* IntArray;
so did you allocate these yourself or?
im using a c api, it allocates them somewhere and gives me the pointers
Ok, well as long as they don't move its fine.
they move sometimes, but always stay fixed if i tell them to using the api's map function, so it should be fine lol
Why can't CompanionLink just have another bool parameter for DontDestroyCompanionObject
why should they?
companions are created with entities
what would be the reason for them to keep existing once entity is destroyed?
Because sometimes we want to go 80% GO 20% ECS instead of the other way
im wondering does float3 have any function that does the same thing as Vector3.Scale()?
its just normal multiplication on float3s
oh nice!
in general any operation that works on floats, is now componentwise for float3s
ok that is really good, thanks!
wondering, which do you reckon would be faster:
SomeRandomVector3 += (Vector3)(SomeVector3 * SomeOtherFloat3)
or
SomeRandomVector3 += Vector3.Scale(SomeVector3,SomeOtherVector3)
also do you reckon it would be any faster if i put it in a job?
unitys ecs already has a way to enable/disable components right ? Or is this still wip ?
so far, from testing, it appears that the 1st one is much faster than the second one (not as fast as i would like though...)
Hi! (Sorry if I'm interrupting) I'm trying to generate Physics Bodies from script without using the Physics Body Authoring Component with a Subscene. I've added to the Entity all the necessary components: Translation, Rotation, Physics Mass, Physics Damping, Physics Velocity, Physics Gravity, etc. But when I press play the Entity does not move/fall to infinity. Is it because I need to add a Physics Collider or maybe Because I have to assign a Physics World Index? The Problem is I can't find a way to add an Index. Does anybody know how to do/generate it?
Burst optimized for handling Unity.Matematics types so I would assume the first one would be faster for burst.
aha, ill add [BurstCompile] to the function then
anyway i can get tranform.forward as a float3 then?
it can essentially do just one multiplication that works all elements at the same time, (SIMD)
math.forward()
ah i shall look into that then, thanks!
yes in 1.0.0exp8
or do you have a transform?
oh, ye it is a tranform
then just convert the forward vector to float3
and that wont be too slow?
I don't think so, I might be wrong but I think burst can optimize the cast away, since its the same data in vector3 as float3
ok, so a faster version would be this?
SomeRandomVector3 += (Vector3)((float3)SomeVector3 * SomeOtherFloat3)
I think so
ill try that and report back, thanks!
wait are float3 and Vector3 the same in size and memory layout? As im dealing with pointers i might be able to just interpret the memory as a float3 assuming they have the same layout
I think so, but not 100% sure
ill also test that then and see if memory stays good
You can check the burst inspector and see what it compiles down to
burst has its own inspector? Cool!
Jobs/Burst/Open Inspector
never heard of any of those lol, where would i find this burst inspector you speak of?
note im still in the 2021 version of dots for now
OK, its somewhere in the top menu then
you should be able to search for it
im trying, it can't seem to find it
is your function static, has the burstcompile attribute, and its containing class has it too?
ah i didnt make it static, and the class doesn't have BurstCompile either
ill quickly do that, thanks!
hmm i dont think i can make it static unfortunately, is it required?
for burst, yes. But you can make a job also, instead of a static method.
ah and then can i burst that job then?
yup
good, thanks, ill try that and report back!
you need a collider too
Alright thanks! I'll try it out.
making it a bursted job seems to be even worse for performance, odd
perhaps im doing it wrong though, ill send my code
sorry for flooding chat....
hold on ill just resend it as that pastebin site thing so i dont flood chat lol
anyway, any speed improvements you can see?
how long is the array?
the array can be anywhere from 0 to 30 thousand in length, it shouldnt matter much though right, cause it is just grabbing one index out of it?
Scheduling a job has some overhead, so it only makes sense if you have a large enough array
ah unfortunate
even just invoking burst code has some overhead, but for the most part that should be very tiny.
try using .Run() instead of schedule
nope
and yup still way slower than just using the line i commented out
So basically the operation you are doing is not expensive enough for it to be even worth running it in burst
its just a multiplication and add
unfortunate, what would be the fastest alternative then?
just run it without burst
vector3's or float3's?
doesn't matter really
float3's seem faster in my testing, so ill use them-ish i guess
at some point i would like to run this in a loop, but for now i doubt that is possible due to the odd way i setup my collision detection, thanks for all the help!
if you would for example launch multiple particles at the same time, it would be worth doing a job that does that with a loop inside.
multiple particles can be in the trigger volume at once, but ive currently got it setup to run the method multiple times, rather than running it once with an array of all the particles in collision with the trigger volume, so eventually ill be able to make it more efficient, thanks for all the help! (for now it is a pain to change, cause everything else that relies on this collision detection system would need to be changed to make this work lol)
I want to make a simple ComponentSystem that runs once per frame in the same rate as MonoBehaviour's Update method. Which attributes do I need to add to the system?
ok finished converting everything to use nativelists, and do looping, any performance improvements anyone can notice? https://hastebin-plus.herokuapp.com/92dyDpbxX1
if direction and power is always same you don't have to compute that in the job
Anyone got a sample on how to display graphic with entities?
AddComponent<RenderData> no longer available, and don't know the new format
no attributes required for that, by default they end up in the simulation system group which is ticked at the same rate as monobehaviour
I just need to render basic mesh and materials without animations.
Creating entities from scratch need some pointers.
Awesome. What do I need to do if I want it to run before the fixed step group stuff?
unfortunatley direction changes a lot
[UpdateBefore(typeof(FixedStepSimulationSystemGroup))]
well in your job, it is constant
oh I thought I had to specify a system for that attribute good to know it works with groups too.
ty!!
you are doing the multiplication for each index, when it is constant. Although maybe burst will realize that and just do it once.
Found out informations about it https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/HybridURPSamples/Assets/SampleScenes/EntityCreationAPI/TestEntityCreationAPI.cs
oh, good point!
it might, although i would rather not take a chance on burst, unless there is a way of checking
so ill just do it once before the job and pass it
what is ScheduleParallelByRef in 0.51?
before i try this
can you have a buffer of buffers somehow?
or do i need a buffer of entities
which also have buffers?
basically trying to emulate List<List<T>>
I think that is possible in 1.0.0, haven't tried tho
with like NativeList<NativeList<int>>
You will lose the ability to write to the inner list inside of a job though
What do you mean? What it does or what the function is called?
can you actually have NativeList<T> on a component
and not use IBufferElement?
You can, but the safety system will not let you write to it from a job
thats problematic
You can use an unsafe container or wait until unity manages to add this functionality to the safety system. But ideally if it's only a single native list you would use a dynamic buffer
Is this mutable data? Or is it just for reading stuff
Also, a dynamic buffer already behaves like a List<List<T>> since you can have multiple entities with the buffer on them
You can store a reference to the entity
I mean it's not really a "buffer of entities", it's just entities
yeah
hmm
i'll go back to my drawing board for alittle bit
make sure this is absolutely necessary
You can also look into blobs, maybe those are better suited for your problem
hmm based on quick google don't think so
basically i have an entity that has 1 vector2 and a buffer of vector2s
i'm trying to store all the A* pathing outcomes for 1:Many of those
The first vector is the starting point and the buffer are the destinations?
yeah
hmm
okay i think i got it
i don't care about what the paths belong to
so i can just flatten this to 1d
just get the AI to pick a random path to use
wait no
that won't work i need to know the end
hmm
I'd just go the lazy route and use an UnsafeList<UnsafeList<T>> if you really need it all on 1 component
its okay
i just need another component
i think
okay i'll use index's as keys
that should work
makes it flat and i can reverse lookup both arrays
to get path and end point
since there will be N array elements for both
Seems like it is not possible to destroy a GameObject from a system's OnDestroy() that's running in the editor world... Annoying... Anyone done this and found a workaround?
why not?
no idea... seems like a bug.
what error do you get?
when I enter play mode the editor world closes, so OnDestroy is called on my system and the GameObject is destroyed, but as soon as I exit playmode the GameObject is back again
what it does opposite to simple one
What the name says, it passes the job struct by ref instead of copying it
hold up, did you mean to remove GO from scene completely?
yes
I use that
I know destoy doesn't work in editor
ok, so again it is about little performance gain
but I use DestroyImmidiate
thing is, If I cache the GOs I want to destoy in a static list and delay destruction until the systems OnCreate is called once I exit play mode, they are destroyed fine.
Isn't that just because the scene was never serialized to disk?
It will load the old version would be my guess
You can try marking it dirty and then saving
although maybe you can even skip the marking it dirty step, I think a direct call to save will do it regardless of whether or not it should
Ah yeah, there's even a note about it
What method is that?
Thanks I'll play around with this and see if i can fix it.
I'm still super confused by the entities workflow. Why would I even do anything else than schedule jobs from a system if a systems update is main thread only
Because scheduling also has overhead, sometimes it can be faster to just do it on the main thread. Also you may need some previous data to schedule your jobs
I can do that in job and schedule the next job from a dependency. I mean I get a lets say MainPlayerMove system that moves my 1 player based on input to be just a Update on the system
but moving the 10k zombies that chase the player needs to be a job
It's up to you really. There's also some stuff that is just easier on the main thread if it uses managed types that haven't been converted to ECS
e.g. input system, 2d stuff, etc
some things are just super fast and require main thread
for example: player input
let's say player spawns entities
it's structural change, that can't be done in a job
so why create ECB, schedule it when you can instantly process input
and spawn entities
after all
all ECB run through main thread in the end anyway
Ideally in this case you would move your system close to another structural change
Yep, just letting them know that it's not super efficient to do that "between" two other structural changes
I get that. It's just most tutorials I see do for each entities in a system Update to move the enemies etc etc
and that seems like it should be in a job
input, spawning etc etc are ok on the main thread ofc
Entities.ForEach ... .Schedule()/.ScheduleParallel()
those?
they schedule codegened jobs
I mean the cool thing is you can always choose. e.g. IJobEntity has overloads for all types of scheduling, and can also be run on the main thread
So "everything" is already in a job, it just depends on how you are scheduling (or in the case of Run, not scheduling) it
" Entities.ForEach is fundamentally a job generator, and it makes it very easy to create parallel jobs. This unfortunately comes with a complexity cost and weird arbitrary constraints, which is why more explicit approaches are preferred. Those explicit approaches (IJobEntity) are covered later in this tutorial." I see
Also I would not use Entities.ForEach anymore, it is being deprecated in the next update
Use either the SystemAPI.Query API, or IJobEntity
(or IJobChunk if you want to be more explicit on what is happening)
I was talking about seeing many examples of ``` [BurstCompile]
public void OnUpdate(ref SystemState state)
{
// The amount of rotation around Y required to do 360 degrees in 2 seconds.
var rotation = quaternion.RotateY(SystemAPI.Time.DeltaTime * math.PI);
foreach (var transform in SystemAPI.Query<TransformAspect>())
{
transform.RotateWorld(rotation);
}
}```
this is main thread
this is not a job at all right
Yes, it runs on the main thread
regural everyday foreach loop
Well, burst compiled, so still very fast
well yes
Also has good cache coherency due to the the way the data is layed out, and does not allocate any garbage
don't take it too close to heart, unity themselves probably still haven't figured the best way to organise systems, so ๐
It's probably depends heavily on project too
Regarding your example, I would probably put that in a IJobEntity
But this is very true
I think I'm going to watch the 3 hours V rIsing stream
I thought they only used DOTS, not ECS?
I've still not gotten around to watching it...
bro at this point I dont even know the difference.... I've been using Jobs in regular projects for a while now
am I using DOTS ?
fuck if I know
DOTS = Job, Burst, Collections, etc
ECS = Entities, Physics, Graphics, etc
(vs "normal" MonoBehaviour stuff)
ECS is part of the whole DOTS stack as far as I can tell
I'd call it classic
Yeah that might be better
yeah, it's culmination of it basically
No luck ๐ฆ
but the guy in the stream starts talking about data oriented design so I guess they did ECS
Weird. Maybe it's the timing then? Are there any error messages?
no errors
You can still use data oriented design for performance critical sections (and make it very fast using Jobs, Collections, Burst), without using ECS
Weird. I've never tried this, maybe you just can't save the scene while the game is already starting?
You could write a custom "start" script that does your cleanup stuff or something? Not the cleanest solution though...
I was going to do that and leave it, but unfortunately its not only when entering and exiting playmode that causes the problem, but also when I close the whole editor and open it again, the GOs come back. I'll see if I can somehow manage a separate scene where I instantate my GOs to.
any official docs on how to use the new input system with ecs ?
There is no specific integration
So just use them separately, and modify the ECS state however you like according to your inputs
my idea was to have a InputData component that a system fills up. I'm not understanding how to get the InputActions connected to the system
Just read from them as you would normally?
from a monobehaviour ?
Why would you need a monobehaviour, just read from it in a system
there are couple of options so far I know
- create a huge struct stored in NativeReference<T> and just access specific fields through pointer
- use components for every action and it's state
for example
Started<RMB>
Performed<RMB>
Cancelled<RMB>
for now I use second approach, I do enjoy it
But it certainly has downsides
Why not just store the struct on a component
why not?
it doesn't change the fact that you will access it only once
kek
allthough
I see what you mean
Accessing it by pointer sounds more complicated than just reading a component
well, not really
NativeReference<T> is easy
it's like native array of size 1
you pass it by value
and then add dependency overhead for what?
it's input
written only once before World update
read only in World
If you want to micro-optimize that far sure
People using unity normally are often times not very familiar with pointers in C#
NativeReference<T> is easy
it's certainly better
than getting entity query for singleton
and accessing it through entity manager
every frame
So you mean just pass the NativeReference to the job
well, considering you usually use input for one time actions
you are probably just going to read it in OnUpdate
for some boolean for example
I know, but often times when you try to explain something you skip over details, and that makes it hard to understand what you mean
and then do early return if it's not
e.g. this isn't very clear
๐
Then yes, I agree, the approach you mentioned is easier, I originally thought you meant something completely different
Something I've been wondering, do ECBs do any kind of pre-processing on the requested commands? For example, if I add a component and then remove a component on an ECB, will it move that entity twice? or not at all?
should probably check source to figure that out
but I wouldn't count on it
since they specifically mentioned
that if you destroy entity in ECB
and then add smth to it
it'll throw
Seems kind of difficult if you have multiple systems that can e.g. destroy entities in an ECB
one more headache to look for ๐
Wait so I can use the generated c# class, new it in the systems oncreate and read inputs
Yes
Why the f didnt you say so๐คฃ๐คฃ
I assume you knew how the InputSystem worked ๐ this is the #archived-dots channel, not #๐ฑ๏ธโinput-system
inputAction.performed += _ => em.AddComponent(inputEventEntity, performed);
I usually do it this way
Alternatively you could try baking InputActionReference and reading the baked references, but I just read an instance of the generated C# class
We normally use this https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.PlayerInput.html and invoke c# events this is why I was confused
well, that works too
but I tried it
and it sucks for all in ECS approach
because it's like combing OOP with ECS
result is uugh
so instead I decided to use all those callbacks
to just setup state in World
so systems can react on it
I still dont get your aproach
Here's simple toggle switch for example
[UpdateInGroup(typeof(EarlySimulationSystemGroup))]
[BurstCompile]
public struct ToggleMapHandler : ISystem
{
private Entity _requestEntity;
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<Performed<ToggleMap>>();
_requestEntity = state.EntityManager.GetOrCreateSingletonEntity<Singleton<OpenMapRequest>>();
}
public void OnDestroy(ref SystemState state) { }
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.EntityManager.AddComponent<OpenMapRequest>(_requestEntity);
}
}
everytime I press ToggleMap action button
it creates an entity with this tag
and this system runs OnUpdate just once
What is Performed<ToggleMap> and what does it do ? Somehow I still dont get it, thank you for taking the time to explain
just a tag
๐ฅฒ Sadly dots input is not a thing yet
emtpy struct
So who reads that for examole M was pressed to toggle the map ?
what it does - it exists the same frame Performed on ToggleMap action is called
that system above
state.RequireForUpdate<Performed<ToggleMap>>();
this makes this system run only if this component exists in world
and I clear all those components on end of frame
Really deprecate are next dots preview release? So fast. ๐ฅฒ
In the full release at the latest iirc
But all the system does is add a component
Not necessarily in the next one
๐ฅฒ I still fixing compile errors of my production project. Can't enter play mode yet
well, it's just simple example
Here's more complex
[UpdateInGroup(typeof(PlayerInputGroup))]
[BurstCompile]
public partial struct FocusOnPlayerHandler : ISystem, ISystemStartStop
{
private Entity _player;
private Entity _cameraEntity;
private EntityQuery _playerQuery;
public void OnCreate(ref SystemState state)
{
var em = state.EntityManager;
_cameraEntity = em.GetOrCreateSingletonEntity<SpaceCameraTag>();
state.RequireForUpdate<Pressed<FocusCameraOnPlayer>>();
_playerQuery = state.GetSingletonEntityQueryInternal(typeof(PlayerTag));
}
[BurstCompile]
public void OnStartRunning(ref SystemState state) { _player = _playerQuery.GetSingletonEntity(); }
// [BurstCompile]
public void OnUpdate(ref SystemState state)
{
var em = state.EntityManager;
var pos = em.GetComponentData<LocalToWorld>(_player).Position;
var sysID = em.GetSharedComponent<StarShared>(_player).systemID;
em.SetCameraPosition(_cameraEntity, pos);
// Set star system if it's not already current
if (sysID != em.GetEntityStar(_cameraEntity))
{
em.SetStarSystem(_cameraEntity, sysID);
em.FixRendering();
}
}
public void OnStopRunning(ref SystemState state) { }
public void OnDestroy(ref SystemState state) { }
}
state.RequireForUpdate<Pressed<FocusCameraOnPlayer>>();
So every frame this component exists
System runs
meanwhile this component gets created in Started and gets removed in Cancelled
of NIS callbacks
Ok I get it.. where do you hook into the nis callbacks ?
out of OnCreate of other system
And you use the genersted c# class there ?
var inputActionTypes = TypeUtility.GetAllAssignableFrom(typeof(IEventAction)).ToList();
_inputExtensions = TypeUtility.InstantiateAllOfType<IInputExtension>();
foreach (var inputExtension in _inputExtensions)
{
var asset = inputExtension.Asset;
inputExtension.RegisterCustomInput(em, inputEventEntity, pressedEventEntity);
asset.Enable();
foreach (var inputAction in asset)
{
var name = inputAction.name.ToLower();
foreach (var type in inputActionTypes)
{
if (!type.Name.ToLower().Equals(name)) continue;
if (allStarted.TryGetValue(name, out var started))
{
inputAction.started += _ => em.AddComponent(inputEventEntity, started);
}
if (allPerformed.TryGetValue(name, out var performed))
{
inputAction.performed += _ => em.AddComponent(inputEventEntity, performed);
}
if (allCanceled.TryGetValue(name, out var canceled))
{
inputAction.canceled += _ => em.AddComponent(inputEventEntity, canceled);
}
if (allPressed.TryGetValue(name, out var pressed))
{
inputAction.started += _ => em.AddComponent(pressedEventEntity, pressed);
inputAction.canceled += _ => em.RemoveComponent(pressedEventEntity, pressed);
}
inputActionTypes.Remove(type);
break;
}
}
}
not really
I just iterate ActionMaps for InputAction
and automatically assign callbacks to them
name based
if type name and name of InputAction matches
I create all callbacks for all registered components
basically just for components that are used
but
I assume there's better solution
with just 1 giant struct
which contains all values for those actions
I assumed that for 1.0 at least input would work๐คฃ
because this way you'll avoid any structural changes at all
lul
let's be glad we at least have character controlled for free
๐
For 0.5
I can complain that there is no proper input handling in a 1.0 version even if its experimental
1.0 means all the parts should at least be there but what ever just unity things
nnnah
it's just ECS that will be ready
everything else will probably be external packages
because I'm certain, those things will not do well with existing dev's solutions
Wdym no audio? Dots audio has been a thing since mega city they havent expanded on that at all ? Do i need to do magic trickery to play a bullet impact sound as well ?
How do you play sounds ?
you better read FMOD about it
in short, you just create event instance and use method on it
like
musicEvent.Play();
Fmod has ecs documentation?
So I pass the FMODUnity.EventReference to a component from the Baker I beleive it is called now and used to be AuthoringComponent and then from a system I can call the fmod runtime manager to play the sound ?
yeah, you pass eventReference and then you need to instantiate an event instance.
You can store it on component
Everything is unmanaged
which is pog
[UpdateInGroup(typeof(InitializationSystemGroup))]
[BurstCompile]
public partial struct AddSoundInstanceSystem : ISystem
{
private EntityQuery _query;
public void OnCreate(ref SystemState state)
{
_query = state.GetEntityQuery(new EntityQueryDesc
{
None = new[] { ComponentType.ReadOnly<SoundInstance>() },
All = new[] { ComponentType.ReadOnly<SoundSource>() },
Options = EntityQueryOptions.IncludeDisabled
});
state.RequireForUpdate(_query);
}
[BurstCompile] public void OnDestroy(ref SystemState state) { }
public void OnUpdate(ref SystemState state)
{
var em = state.EntityManager;
using var entities = _query.ToEntityArray(Allocator.Temp);
using var sounds = _query.ToComponentDataArray<SoundSource>(Allocator.Temp);
for (int i = 0; i < entities.Length; i++)
{
em.AddComponentData(entities[i],
new SoundInstance { value = RuntimeManager.CreateInstance(sounds[i].guid) });
}
}
}
Smth like this
And then played like this
[UpdateInGroup(typeof(InteractionSystemGroup))]
[BurstCompile]
public partial struct SoundInteractionSystem : ISystem
{
[BurstCompile] public void OnCreate(ref SystemState state) { }
[BurstCompile] public void OnDestroy(ref SystemState state) { }
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Entities.WithAll<InteractedTag>()
.WithAll<InteractionSound>()
.ForEach((ref SoundInstance sound) => { sound.value.start(); })
.Run();
}
}
There is no reason to have a specific input system for dots, its not like input is a bottleneck in any game. Here is an example from unity of how to use the new input system with dots: https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/PhysicsSamples/Assets/Common/Scripts/DemoInputGatheringSystem.cs
Wait wait this is what I was looking for
the argument is sound. i think that's also the reason why they dropped priority on audio. unity knows everyone uses fmod
Ofc unity hide the input example in the physics demos kekl
Soo not entirely dots or unity specific but im trying to replicate a pure c# archetype based ecs.
If anyone is interested let me know ^^ i think its pretty interesting, the current version is still very very basic but i already have a benchmark for the iteration performance.
Unity ECS is already pure C#
๐
Yeah but tied to unity, we cant use it outside of unity right ? ^^
no you can't
why not just use existing C# ECS libraries?
why invent a bicycle? ๐
Yep thats why i made my own one and for learning purposes ^^
Couldnt find any archetype based c# ecs... only sparsesets
well, pure C# without burst will not do well if you try to do it same way as unity
whole reason to return to monke do unmanaged code is because Burst
The main purpose was actually learning.
Yeah, "my" version does not use unmanaged code. But i try to utilize the L1 cache atleast ^^
I mean if you want you can take a quick look at it : https://github.com/genaray/Arch
Its not that much code, pretty small currently ^^
oof
well, I don't favor this approach because it's way too much GC allocation
for every little change in archetype
tons of allocated data
Interesting, let me hear... what exactly do you mean ? ๐
Are thats what you mean, well yes... the only way to make it compatible with public struct MyData{ string s } components for example was to use regular arrays.
I also played around with a chunk variant that actually is unsafe and uses manual allocation of memory... i had the idea that the archetype could just support both, based on what the types are basically. If all of the passed types are unmanaged it could use the manual allocation approach and be more efficient probably
I just wonder... if i can really utilize the cache with the current managed array approach. Since they are... managed... but every single person on this planet has a different opinion on this, most people actually told me that they are of course cache efficient
and figure a nice approach to iterate over them
But lists destroy the whole cache utilization idea ๐ฎ
no they don't?
Dont they ?
I actually tested giant array approach vs chunks approach
arrays won
List is just array with better handling
So chunks are not usefull ? Since the idea was... well... one chunk = 16kb, fits perfectly in the cache... insane iteration speed...
Therefore thats the iteration itself :
ref var chunk = ref archetype.Chunks[chunkIndex];
var transforms = chunk.GetSpan<Transform>();
var rotations = chunk.GetSpan<Rotation>();
ref var transform = ref transforms[0];
ref var rotation = ref rotations[0];
for (var index = 0; index < chunk.Capacity; index++) {
ref var currentTransform = ref Unsafe.Add(ref transform, index);
ref var currentRotation = ref Unsafe.Add(ref rotation, index);
currentTransform.x++;
currentRotation.w++;
}
no, that's not the idea
I tested perfomance
in unmanaged context chunks are very versatile vs large arrays
so unless you want to hardcode access to them in your every system, just use chunks ๐
in managed scenario though
hmm
I'd guess your chunk can contain data about at what indices starts it's entities data in those arrays
Damn... but why ? I cant imagine a reason why one big array is faster than ๐ฎ
So chunks only make sense for unmanaged memory, interesting
Well each chunk has one entity array in it, i wasnt using it in the example above ^^
look for BrokenBricksECS it was the ecs i used before unity released theirs
not relates to your question though. might just give you some ideas
If I'm using native streams and want to schedule something in parallel, do I need to set the index count to Threads * Chunks? Or can I check in a thread if the writer for that thread has been set to the correct index already
Also, I'm still not 100% clear on the usage. Do I pass the NativeStream itself to the job, then create a writer, or do I pass the writer to the job (calling BeginForIndex on the main thread)
https://docs.unity3d.com/2019.3/Documentation/Manual/UnityasaLibrary.html you can use Unity as a library tho
not sure how it can be tied to packages
you pass the writer to the job
in the job, use BeginForIndex before writing
i use the unfilteredChunkIndex for the index but that's up to you what you need. it's also possible to use the entity index if you need to group it per entity and not chunk
though that's a bit more tricky in 1.0 where IJobChunk doesn't have the entityIndex as parameter anymore
What do I set on native stream creation though then? Since each index can only be used once, it would need to be ThreadCount * ChunkCount right?
Also couldn't each thread just keep re-using the same index?
chunkCount is enough.
I thought the indices can't be re-used? Or is that just after reading
Since I need to call EndForIndex after the batch is finished
yes, but that would mean disabling the safety
whoah
that's some good stuff
You can write to the same index multiple times?
that's why the reader returns a count when you start reading from an index
It just returns the same thing as RemainingItemCount right?
(once you set the index)
I'm trying to use streams more since they seem really useful for parallel operations where the total count is unknown (since the other parallel writers can't resize the underlying collection)
yeah, afaik the remaingItemCount gets decremented with every read
yeah it does in ReadUnsafePtr, i have a while (stream.RemainingItemCount > 0) so it's fine.
๐ค
wait what? so you just never close the index then or what?
anyone worked with BRG yet?
I'm trying to understand whether I can render into specific RenderTexture
oh man, this API is so bad to work with
like this ```inCombatStream.BeginForEachIndex(batchIndex);
for (int i = 0; i < chunkCount; i++)
{
inCombatStream.Write(...)
}
inCombatStream.EndForEachIndex();```
sure, but after that you can't write to that index again, right?
no, theoretically it would work but BeginForEachIndex sets the ElementCount to 0 so not with the NativeStream implementation.
So basically you can write multiple times to the same index once ๐
That makes native streams really useless for IJobEntity then, unless you create a buffer for each entity which does not seem like a good idea
correct ๐ i must be misremembering this part - i thought i did this in the past at some point. how the code looks though, 100% not the case ^^
hardly matters honestly.
What do you mean?
opening an index for each entity is fine
Really?
yeah, the memory block. m_BlockStream->Ranges is pre allocated beforehand
it's overhead, sure, but very small
Oh, opening an index sure, but I mean creating a native stream with that many indices
yep, even that
Oh ok, I thought it was slow-ish due to this comment:
Using a job to allocate the buffers can be more efficient, particularly for a stream with many buffers.
I'm guessing using an IJobChunk with the unfilteredChunkIndex as the stream index is probably faster though
sure it is, especially when reading then
{
long allocationSize = sizeof(UnsafeStreamRange) * forEachCount;
m_Block->Ranges = (UnsafeStreamRange*)Memory.Unmanaged.Allocate(allocationSize, 16, m_Allocator);
m_Block->RangeCount = forEachCount;
UnsafeUtility.MemClear(m_Block->Ranges, allocationSize);
}``` that's the part where the forEach ranges are allocated
i think 24 bytes per element
IJE has no chunk index? i'm very unfamiliar with it
nope
Maybe you can get it somehow, but it just has the read / write handles for the components normally as parameters
Nevermind, you can get it
yoooo, I figured how to do custom rendering now
๐
var sys = World.GetExistingSystemManaged<EntitiesGraphicsSystem>();
var fieldInfo = typeof(EntitiesGraphicsSystem)
.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.First(x => x.FieldType == typeof(BatchRendererGroup));
_brg = (BatchRendererGroup)fieldInfo.GetValue(sys);
var mesh = _brg.GetRegisteredMesh(mmi.MeshID);
The BRG in it is private?
yeah

yeah
well, it's not really an issue
sad part
I didn't figure how to draw with BRG
so I'll use legacy system
Entities graphics system is 3k lines
hope I won't need the same ๐
huh that's kind of weird you have to do that
wcyd
technically, nothing stops you from registering generic types in runtime either
but to do that you have to use Harmony or some other code injection hack
won't work in AOT though
and why are you doing this?
I use selection tool which needs entities rendered
with new API old way of getting meshes broke
so
fixing it now
hehe
ah i see
in fact
it seems like the whole process is actually a bit easier now
if it wasn't for me being pepega for so long
allthough I might take back my words ๐
so I have entities in a chunk
each entity might have their own meshID
while I need in the end nice them groupped, so I can draw same meshes batched
๐ค
I'd guess obtaining hashMap value on every entity iteration is not a good idea
Not too different from reading a component / buffer lookup
yeah, but I need it for very fast job
I need to collect all entities indices and transforms into 1 good looking array
while separated by meshID
but while iterating chunks I might get different indices every time
hmm
I'm checking at implementation of HashMaps rn
I need a hashmap to which I can write in a batch
<int,int> hashmap
where I need to write array of Entites as batched key,value pair
NativeHashMap seems like using some sort of integer between pairs
so that won't work
meanwhile UnsafeParallelHashMap makes me ๐ฅด
Why do you need an unsafe collection
I was checking internal data structure
but it's so low level
I can't understand it
Sounds like you want a hashmap of lists
that's what I do rn
but implementation I need is just ๐ฅด
it used to be so cool when it was just 1 render mesh per chunk
now I need some complex map solution
I need this structure per batch:
uint meshID
float4x4[] matrices
int[] indices
any idea how I can implement one?
@rotund token
any materials on BRG?
I mean "external materials" i.e. tutorials, something more on the matter than: https://docs.unity3d.com/Packages/com.unity.entities.graphics@1.0/manual/batch-renderer-group-api.html
?
you can add any to it
I don't use it to do selection rendering though, so