#archived-dots
1 messages ยท Page 102 of 1
I'm using hybrid ECS in my project and have noticed that Entities.ForEach generates a moderate amount of garbage when given multiple entities, is this normal? Is there any way around this? Is this still the correct way to go about doing this?
//Generates garbage
Entities.ForEach((Module module, Thruster thruster, Hurtable hurtable) =>
{
...
});
//Does not generate garbage
Entities.ForEach((Module module) =>
{
...
});
Is that in JobComponentSystem? If is, I think you need to have ref or in on the components.
yeah you need the refs
Hey guys, Happy new year :).
I'm currently playing around with dots (Hybrid ECS).
I have a PlayerComponent which holds the Score of the Player and i want to show it in the UI. To achieve that i've created a PlayerAuthoringComponent (MonoBehaviour, IConvertGameObjectToEntity) https://pastebin.com/gm7jWp8D
I don't know why, but it feels wrong to get the entity like that. (The Start() method)
can someone tell me if this is good practice or if not, the right way?
i think even without refs it shouldn't generate garbage in JobComponentSystem (while ComponentSystem does) because it uses codegen instead of just lambdas
afaik without ref it's just treated as readonly
or is in really required? dunno
@pine scroll you can just do _player = entity; in the Convert method
@hollow sorrel omg, dunno how i could've missed that :/ thanks
or you can have a system that does
Entities.ForEach((PlayerComponent player, PlayerAuthoringComponent authoring) => {
authoring.text.text = $"Score: {player.score}";
});```
(sidenote - probably worth avoidng string allocation every frame)
Ah I've been working in the ComponentSystem, should I switch to the JobComponentSystem?
99% chance you should
Okedoke thanks a ton! I think I've been following really old guides whoops
I think you're always meant to use JobComponentSystem now. With [AlwaysSynchronizeSystem] it will always be faster even on main thread stuff
not that old, i think the new jobsystem foreach was added like 1-2 months ago
but yea right now jobcomponentsystem is componentsystem++
Also you could consider just using a NativeArray. You can have a NativeArray with a single value shared between your UI and your jobs. Anywhere you update it in your jobs will "automatically" be read by your UI
Oh good, glad I'm not to far behind haha
Hi all, is there a way to access component data knowing entity i'm looking to access without the entity manager inside a IJob struct , or getting a reference to entity manager inside an IJob struct as in Entities.ForEach() where i do have a reference of EntityManager as long as it's without burst ?
look at ComponentDataFromEntity
@worldly pulsar not sure to understand it's a struct
yup, it has an operator[], you give it an entity it gives you the component
works in jobs and with burst
JobComponentSystem has a GetComponentDataFromEntity<TComponentType>() method to create these
@worldly pulsar i'll test thx
Okay so I'm trying to bring over my stuff to the JobComponentSystem, all of my components are MonoBehaviour. Are they supposed to be a separate blittable type? Are the components still added to GameObjects? Are there any tutorials you can recommend for the JobComponentSystem
If you want to use a type in a job it needs to be a struct
If you can't make your types blittable JobComponentSystem will still be faster even running on the main thread
@worldly pulsar u can use a MonoBehaviour in Jobs?
If I want to keep it on the main thread would I run the code in OnUpdate(JobHandle inputDeps) but not return a JobHandle @zenith wyvern ?
Yeah. Give your system [AlwaysSynchronizeSystem] attribute and return default in OnUpdate
That's the pattern right now
In this workshop style video we walk through an example project created by Unity Evangelist Mike Geig on how to script a Pong style game using Unity's Data Oriented Tech Stack (DOTS) including the Entity Component System (ECS). This video covers the latest syntax in Unity 201...
Also a good example of the direction they're going with it now
Ah sweet thats not going to be too hard to convert over, thanks a ton!
@worldly pulsar it should work but i've a "need read only" error with the [ReadOnly] property any idee ?
@pine scroll not in jobs, no. The more complete snippet would be:
Entities
.WithoutBurst()
.ForEach((PlayerComponent player, PlayerAuthoringComponent authoring) => {
authoring.text.text = $"Score: {player.score}";
}).Run();```
which runs on mono/il2cpp, on the main thread
Sorry for not being precise the first time
@worldly pulsar oh thank you now i think i got it ๐
Hello everybody! I'm trying to figure it out again. At the moment I can fill a buffer with vertices and triangles in my system, but when I try to remove the component tag that this system uses, it somehow is still on the entity after running, so the system continues to run for the same entities. Can anybody spot what I am doing wrong? EntityCommandBuffer works for me when in a (different) ComponentSystem though.
https://gist.github.com/kayvanbree/b0e95a9f3fdcb470775f158edeeb1508
Can I do that by just calling job.Complete?
If I check the entity manager after calling job.Complete it doesn't show any changes I made in this code
And there is only one place in my code where the tag I want to remove is added. The breakpoint for that line is never hit, so it's not removing and re-adding the component either.
Can it be that the concurrent version doesn't have this playback method?
Again i have a Question.
It's about the new Unity Physics.
I have Scoreboxes which a player can pickup.
The Question is, is it really the correct way to use something like that: https://pastebin.com/tr6WcTzM
isn't there something like player.OnCollideWith<ScoreBoxComponent>(), i think u know what i mean
because it feels really weird to always check for entityA and entityB and what kind of entity they are
The entityInQueryIndex should also be correct, in the docs it says it should be used as the jobIndex for adding commands to the concurrent ECB
ok
So save the ECB in a var, save ECB.Concurrent to a var, and call ECB.Playback after job.Complete
let's go
on return job; the changes have actually been made
so the ECB is never playbacked somehow
I don't think I'm supposed to call Playback manually, right?
I recently updated
let me check
Yes
0.4
@pine scroll far as i can tell from docs and samples that is indeed the intended way, but i also think it's weird since there's a lot of redundant iterations that way
lemme know if you figure out a better way if it's not answered here
Thinking of using esc for a new project but kinda struggling to understand how we can do any sort of visual editing using it. Either placing the objects in scene or even making โprefabsโ consultingโs of multiple parents and children. Anyone able to point to a tut dealing with stuff like this?
New game is a builder game and with the multiple ai wandering around I think itโll be best to go ecs
you might be overthinking it? conversion workflow pretty much makes it so you use gameobjects to author your entities in editor, which get converted when entering into play mode
Wait I must be missing something? Thereโs a way to do entities that isnโt done via script?
Check the samples repo on github, many of them use the conversion workflow
(link in pinned message)
For lambda ForEachJob is WithAll<> equivalent for regular jobs [RequireComponentTag]?
yup
So you do WithAll<ComponentA>.WithNone<ComponentB>.ForEach then if you need exclude as well I preusme?
I will lool@when I get home. Sounds like it may make life much simpler.
Job system only works with some type of data however correct? Like I donโt think it can handle nav mesh and things. Idk I just started with unity beyond single thread.
only blittable types yea
i wouldn't start with ecs if you're new to unity
there's a lot of stuff missing
you can do hybrid to fill in the gaps but if you're not used to unity you're trying to learn multiple things at once
When using [GenerateAuthoringComponent] is there any way to reference the generated authoring class?
No (and why would you ever want that?)
Oh okay, I was hoping to use it for some of my editor tools
What do you want to do that requires a ref to the authoring class?
You could probably use reflection if it's just for editor tooling
Not new to unity just need to the DOTS. Last project was in lts 2018
So it was 5 letters difference ๐ So there's some singleton stuff going on and the buffer system I created wasn't running at all.
Well, it's quite confusing, and really hard to spot, so a warning would be awesome indeed
Is there a way to do
Entities
.WithoutBurst()
.WithChangedFilter<AHybridComponent>()
.ForEach((AHybridComponent c)=>
{
// Do something in my system when I changed my hybrid component in the editor
}).Run();
It seems doing it the way I wrote it only causes it to run once when the entity is created
I guess I can just tag the entity from inside OnValidate
anyone knows how can I get a reference to an element in a NativeArray that is in BurstCompiled code?
(the element is a struct)
@zenith wyvern in case it helps, live link with live conversion in edit mode enabled will trigger a conversion each time you change a property
Oh, cool. That does help thank you. I haven't touched the live link stuff yet, I'll have to try that
it only applies to monobehaviours within subscenes but that is largely the workflow going forward
hmm i think if you want an index of an array - base_ptr_address + (sizeof(element) * i)
yes, this base_ptr_address , how can I get it?
Ah you're using nativearray -
yea
You should be able to get the ptr if you use the Unity.Collections.LowLevel.Unsafe namespace (I think that's what it's called), there's a function called GetUnsafePtr()
which returns a void* as the base_ptr_address
ah yes I think that is what I needed, thank you very much! โค๏ธ
but I think I have to get the Ptr from a list
are the pointers of arrays stored in here?
oor
nvm found it
NativeArrayUnsafeUtility.GetUnsafePtr
Anyone knows of an example of how to use RaycastCommand inside a JobComponentSystem? I seem to be chaining it wrong since it keeps giving me errors
Got the code for it @soft nova ? Been a while since I used raycastcommand
but iirc should be setting up a collection of origins and directions and using the ScheduleBatch function and chaining that to your next succeeding job
hmm on Microsoft's site they say that we need to pin the object so that it does not move on the heap:
but do we have to do this with nativearrays too?
because this: NativeArrayUnsafeUtility.GetUnsafePtr can't be used in a fixed statement
or do objects even move on the heap in a job?
@coarse turtle So on the system I will need to get the all the positions? Isn't there anyway to do it inside a Job foreach?
@soft nova not that I know of maybe someone here might know a better soln than me :/
@surreal grail hmm not sure about it moving on the heap (don't think it does until there's a structural change which causes data to shuffle) - but I know you don't need the fixed statement
ah, alright, thanks! I guess what I could do is once at the start of the job get that reference to the array again instead of storing it, and that should ensure that I'm using the correct pointer
@surreal grail pinning is only required for objects in managed memory (and you really shouldn't pass pointers to those to a job unless you know what you are doing).
NativeArray uses native memory allocators, and never moves. By default you should pass the NativeArrays to a job (the whole struct, not the pointer you get from GetUnsafePtr) and use operator[] to get the elements - Burst understands NativeArrays and will produce better code than what you'd get with a pointer
allright, thanks! the reason why I'm trying to use pointers is to only change one variable of a struct instead of having to copy a whole struct back to the array, because I think that is why my code is slower than what I'd like. I'm not 100% sure this will make it faster, but I like experimenting with new things and learning more ways to do things
Burst should optimize that back and forth copy out for you
But you probably shouldn't have struct fields you are not using in that job in the first place
if it's perf critical
oh so should break up my job into more jobs that do different parts?
I mean the struct in your native array
I mean I am using it in the job, but in a later part
my code is made of different steps, should I break it up is what I'm wondering about
This is where you use the profiler to test ๐
yea, I'm spending half my time looking at the profiler lately ๐
question about using DOTS and the hybrid renderer. Is it worth using already (currently in the prototyping phase), since it does seem to be missing lighting support which is a bummer
they havent really said much about the hybridrenderer and its foreseeable future so i would not expect changes to occur any time soon
so how would I go about rendering my stuff when all my logic is now in the entity world?
the way it's set up right now is: game objects are for authoring and you modify the entities at runtime.
how would I now, for example, move a box around, based on a value in a component?
they seem to have used the hybrid renderer for the DOTS Pong example...
Has anyone run into the following error when trying to compare float2 values: Cannot implicitly convert type 'Unity.Mathematics.bool2' to 'bool'
assuming your box has a rendermesh you just modify the translation or localtoworld to move it around
@safe lintel so that would imply that I actually should use the hybrid renderer then? cause without it, it does not render at all
well, unless you want to just use gameobjects for rendering or make your own rendering system, id use it ๐
How are we supposed to compare float2 values using Unity.Mathematics? It's returning the comparison as a bool2 value.
you can do all(val1 == val2)
Not at my computer right now, but it would be something like: if(all(val1 == val2)) ?
yup
(I think there is also an .Equals() method that does the same, but not sure atm)
Alright, thanks!
@surreal grail you can do it like this instead of using fixed statement
var opVox = OpVoxes[i];
OpVox* opref = UnsafeUtility.AddressOf(ref opVox);
or
var opVox = OpVoxes[i];
OpVox* opref = &opVox;
UnsafeUtility is needed only when accessing pointers for generics. NET limitation for now
@autumn sleet but how does this still point inside the array? opVox is just copied over since its a struct, no? and it will be a new address?
Hey guys, how can I run 3 jobs in parallel when they read the same data(here FollowList) ? I have always runtime errors :/
{
/// <inheritdoc />
public void Execute(Entity entity, int index, ref EventNotificationVariableIntChanged eventNotif, ref FromEntity fromEntity)
{
if (FollowList.ContainsKey(fromEntity.From))
NotificationSelected.Add(fromEntity.From, eventNotif);
}
#region Variables
[ReadOnly, NativeDisableParallelForRestriction]
public NativeHashMap<Entity, byte> FollowList;
public NativeMultiHashMap<Entity, EventNotificationVariableIntChanged> NotificationSelected;
#endregion
}```
@digital scarab InvalidOperationException: The previously scheduled job FollowEventSystem:LogFollowNotificationVariableBoolChangedJob writes to the NativeArray LogFollowNotificationVariableBoolChangedJob.Iterator. You are trying to schedule a new job FollowEventSystem:LogFollowNotificationVariableIntChangedJob, which writes to the same NativeArray (via LogFollowNotificationVariableIntChangedJob.Iterator). To guarantee safety, you must include FollowEventSystem:LogFollowNotificationVariableBoolChangedJob as a dependency of the newly scheduled job. Unity.Entities.JobForEachExtensions.Schedule (System.Void* fullData, Unity.Collections.NativeArray`1[T] prefilterData, System.Int32 unfilteredLength, System.Int32 innerloopBatchCount, System.Boolean isParallelFor, System.Boolean isFiltered, Unity.Entities.JobForEachExtensions+JobForEachCache& cache, System.Void* deferredCountData, Unity.Jobs.JobHandle dependsOn, Unity.Jobs.LowLevel.Unsafe.ScheduleMode mode) (at Library/PackageCache/com.unity.entities@0.3.0-preview.4/Unity.Entities/IJobForEach.cs:433) Unity.Entities.JobForEachExtensions.ScheduleInternal_ECC[T] (T& jobData, Unity.Entities.ComponentSystemBase system, Unity.Entities.EntityQuery query, System.Int32 innerloopBatchCount, Unity.Jobs.JobHandle dependsOn, Unity.Jobs.LowLevel.Unsafe.ScheduleMode mode) (at Library/PackageCache/com.unity.entities@0.3.0-preview.4/Unity.Entities/IJobForEach.gen.cs:2015) Unity.Entities.JobForEachExtensions.ScheduleSingle[T] (T jobData, Unity.Entities.ComponentSystemBase system, Unity.Jobs.JobHandle dependsOn) (at Library/PackageCache/com.unity.entities@0.3.0-preview.4/Unity.Entities/IJobForEach.gen.cs:929)
Update function
var handle2 =new LogFollowNotificationVariableIntChangedJob { FollowList = _followListHashset, NotificationSelected = _notificationVariableIntSelected }.ScheduleSingle(this);
var handle3 =new LogFollowNotificationVariableFloatChangedJob { FollowList = _followListHashset, NotificationSelected = _notificationVariableFloatSelected }.ScheduleSingle(this);
JobHandle.CombineDependencies(handle1,handle2,handle3).Complete();
And the bool job
{
/// <inheritdoc />
public void Execute(Entity entity, int index, ref EventNotificationVariableBoolChanged eventNotif, ref FromEntity fromEntity)
{
if (FollowList.ContainsKey(fromEntity.From))
NotificationSelected.Add(fromEntity.From, eventNotif);
}
#region Variables
[ReadOnly, NativeDisableParallelForRestriction]
public NativeHashMap<Entity, byte> FollowList;
public NativeMultiHashMap<Entity, EventNotificationVariableBoolChanged> NotificationSelected;
#endregion
}```
because each NotificationSelected is unic for each job and I run each with ScheduleSingle so no parallel writing problem here normally :/
yeah you're right about FollowList, it seems the problem comes from behind my code, no ? because it's LogFollowNotificationVariableBoolChangedJob.Iterator which doesn't like my schedule
yep _newEntityToFollowQuery = EntityManager.CreateEntityQuery(typeof(FollowEvent), typeof(VariableInt)); but all usage are commented in update function for test purpose
here the fullcode https://pastebin.com/9Lb3avgY
ok
oooh indeed, it's that ๐
sorry for noob problem ๐ฆ
๐
Hey people, what is the current practice for animations(2d and 3d) in ecs? I've googled a bit, but it seems like there's still no implementation by unity? With 2d I guess you can make a simple one that just draws different sprites, but what do you do with 3d?
Oh
Thanks.
HDRP GPU skinning only
Does it mean it's not working on built in rp?
I see. I guess I'll stick with 2d for now then.
Has anyone run into problems updating the Entities package to 0.3.0/0.4.0? I'm trying to use the new syntax outlined in this video: https://www.youtube.com/watch?feature=youtu.be&v=a9AUXNFBWt4&app=desktop. I get the following error:
UnityEditor.EditorApplication:Internal_CallUpdateFunctions()```
In this workshop style video we walk through an example project created by Unity Evangelist Mike Geig on how to script a Pong style game using Unity's Data Oriented Tech Stack (DOTS) including the Entity Component System (ECS). This video covers the latest syntax in Unity 201...
Aaaaaaand it's suddenly working.
I'm having problems with the netcode package (which is DOTS based); posted my issue in #archived-networking - if you have experience with netcode please check that out and let me know if you have any input on that
Edit: Figured out the problem
Haven't got Entities 0.4.0 working yet without errors ._.
And no burst either with command buffers x)
So, I feel like I have a good enough grasp of the basics of DOTS, but am struggling with wrapping my mind around converting my project to use it. Sorry in advance for the wall of text, feel like I need to talk this out and get some feedback as a sanity check.
I have a class called Simulator that holds all the data necessary for procedural city generation. This includes things like a list of cities, a list of networks, the number of simulation steps that have elapsed, the seed for procedural generation, etc. The Simulator class is responsible for stepping the simulation forward, which it can do one of two ways. It will step forward one step every X milliseconds if a simulation speed has been set (useful if you want to slow down the simulation to observe each step), or it'll try to complete as many steps as possible within X milliseconds if no simulation speed has been set (useful if you want the city to generate as quickly as possible all at once). I'm using coroutines for this right now.
I'm making heavy use of ScriptableObjects to allow customization of the simulation. Things like the road growth pattern, size of streets, style of buildings, etc are all customized by ScriptableObjects you set in the editor. For each simulation step, there's a chain of calls that need to be made: Simulator > Era > Network > GrowthStrategy. Each class in this chain is a ScriptableObject except for Simulator, which is a Monobehaviour. There's no serious calculation being done until GrowthStrategy. A key point is that the simulation must be deterministic. Because of this, each step requires that the step before it get completed before it can be calculated. I know for a fact that there are some things I can break off into individual jobs since they don't change the overall state of the simulation, but there are some calculations within each step that have to be completed one after another.
I like the idea of making as much use out of DOTS as possible, but I'm not 100% sure what parts should get converted to it. Right now it seems like it makes sense to maintain the overall ScriptableObject structure, using coroutines to step the simulation forward in the Simulator Monobehaviour. I don't see a way for that to be converted to DOTS, except possibly for the data? Maybe it makes sense for there to be a SimulatorData struct?
From there, I'm really confused. It seems like the logic in the GrowthStrategy ScriptableObjects should be broken out into Systems. The issue is that many of those need to be completed one after another, and I guess I'm not sure if Systems can be chained together so they're completed sequentially. Actually, in cases where you need to do a series of calculations on some data, would that all need to be one System? The more I think about it, the less it seems like DOTS would be applicable. All the examples I've seen deal with operating on a small chunk of data over and over, while I need to sequentially operate on a single big chunk of data all at once at specific points. Along with that, the specific data I need to operate on is determined by ScriptableObjects. As an example: the Era changes after X number of simulation steps, and each Era has a list of Networks that can be created. The same Network can span across multiple Eras, or be created for the first time in a later Era. Along with that, the style of road growth can change from one Era to another. The actual work that needs to be done is very heavily dependent on the values passed by the ScriptableObjects.
So, ya, not sure how to move forward. I'd love to get the performance boost from DOTS, but it doesn't seem well suited for cases where a coroutine would determine how long should be spent on calculating the simulation each frame. Any thoughts or feedback would be much appreciated!
@verbal pewter A lot of stuff, and a lot is only described with the name of the word. You can Update groups manually as much as you like, so moving things from coroutines shouldn't be a huge problem.
hehe, yeah that's a long one. i think it's fitting to see your current coroutines as systems. the whole simulator class is more fitting to split up in a bootstrap where you can setup each system and their sequence
ScriptableObjects can be turned into singleton components, and with some simple systems you can make realtime updates to your world if you want to test out with as well.
You can divide and conquer your logic into system as much as you like, and then the automagic data dependency will sort it out. You can use [UpdateBefore/After] to sort what order your logic is run.
hey
how can i solve this?
All compiler errors have to be fixed before you can enter playmode!UnityEditor.SceneView:ShowCompileErrorNotification() (at C:/buildslave/unity/build/Editor/Mono/SceneView/SceneView.cs:3398)
please help me
@gusty comet Only error? Tried restarting to show error? Is this DOTS related in any way?
Sorry, should've been clearer: there's only one coroutine, and it's what initiates each step of the simulation. Everything after that is a series of function calls. How would you go about ensuring that the game doesn't spend more than X number of milliseconds each frame on simulation? The only way I know to do this is coroutines.
Good to know about being able to choose the order Systems get called in.
i donยดt understand too much about progamming so its kinda hard to me
You should ask in the #๐ปโcode-beginner channel. This is for DOTS related questions.
coroutines are not parallel or anything, they are bound to the same concept of monobehaviour update and run on the mainthread
so, the question is, is your code relying on yields, which span over more than one frame
if not, there's not actually an issue. otherwise porting gets more complicated
The only thing coroutines are used for is to do as many simulation steps in a single frame as possible. What I mean by that is that it loops until X amount of time has elapsed, then yields back until the next frame. From my understanding there's no way to do this with DOTS.
@verbal pewter I don't understand what you want to say ๐ Anyway, on that level there's absolutely nothing DOTS can't do, but it's important how the simulation is written. I mean, I wouldn't write a simulation system that advances per frame but then design a game that requires an arbitrary amount of time per step. The wise thing to do is run the system once per frame with a global step time multiplied by game speed of 2/4/8 or whatever the sim speed should be.
Hahaha, sorry ๐ I want the simulation to be useable in two scenarios: complete one step after X amount of time has elapsed (so that you can watch the city grow little by little), or complete as many steps as possible in X amount of time (something you'd do in a loading screen). It needs to work in both scenarios. From my understanding, DOTS would be fine for the first situation, but coroutines are necessary for the second.
@mystic mountain Can't you make jobs that go across multiple frames?
@verbal pewter I don't have the time to read your entire wall of text right now, but it seems to me like something like that could benefit you. Remember that DOTS is made of parts (ECS, jobs, burst), and you don't have to use all of them for everything.
A good way to go about things would probably be to identity some 'leaf' node of logic (doesn't call anything else, except utility methods) and see if that could be turned into a job or ECS-ified.
I don't have that much experience, but to the best of my understanding, most things you can use a coroutine for, you could potentially jobify. (not necessarily a good idea all the time)
That's good advice @tawdry tree, looking at it from top down is frying my brain ๐ฉ
Top down is great for design, not so much for code
agreed
From my understanding, DOTS would be fine for the first situation, but coroutines are necessary for the second.
You could make a world with all the simulation stuff and advance it separately from normal framerate? Custom worlds are kinda complex, though.
At any rate, if you make a DOTS system (so one or more ECS systems, possibly other code) that can run one 'simulation step' of your simulation, then surely you can just do that... twice.
with dots or data oriented in general you have to change your thinking. top level abstraction is only good when the fundament is solid. in your case, you have to question the whole progress of era, network and growth strategy. pick them apart and find the lowest form you need. i think you'll see that they could operate individually with only a few parameters
Oh, and don't forget that jobs are fully compatible with normal monobehavior code. You can totally kick off a job from mono code, and if you don't wait for it to finish there... Well, as mentioned above I think you can just save the reference and check in another frame if it's done (I oughta get around to see if I can use that trick for my procgen)
Well, that's time, good luck!
Thanks!
@tawdry tree Yeah, where did I say something related to jobs directly, or multiple frames? ๐ค I said he could put the coroutine logic into a system group and update it as many simulations as he wanted across a frame.
i think assigning a 'max frame time' would be an issue because each worker thread has its own frame time basically, you could do x amount of iterations per frame easily tho
but then ofc it's hardware dependent
not sure how else you'd do the 'generate over multiple frames' part
Right, ya. And each step of the simulation will take longer as the city grows.
Just stopwatch your time, and run simulation until you've run out of your prefered rendering delta.
Hmm, that's a thought!
yea that works fine if you're doing everything on main thread
but worker threads mucks that up
i don't think you can track how much time has passed on a worker thread
nor assign a job to a particular thread
In my case a lot of the work will have to be done on the main thread anyways.
So, I guess I could see it calculating the number of steps to complete at the start of the frame based on the performance of past frames, then iterating that many steps.
Thanks all for your input, has given me a lot to think about.
sounds a bit like overengineering but i can't think of a better solution that does the same right now
From my understanding, DOTS would be fine for the first situation, but coroutines are necessary for the second.
the second (complete everything at once) should be easier tho, you don't need coroutines for that
just let your systems iterate everything at once
You can call complete for each simulation if you want and then check time?
You just need to define your simulation as a function of time. Then by passing the current/delta time to the jobs it will always be on the stage you want it to be on independent of the frame.
Hi all, I'm getting a really strange error on EntityManager.SetName(...) on builds saying that EntityManager does not contain SetName...? Anyone? ๐
For the sake of giving some context, due to the fact that I want to use com.unity.serialization package myself (great lib by the way... too bad it is hidden inside dots), I have an Assembly Definition file set to one of my scripts folder so that it can reference it...
SetName is only for editor I think, just enclose it in #if UNITY_EDITOR
So how do I go naming an entity created by code? :/
just to elaborate on what sark said, just use it like
#if UNITY_EDITOR
EntityManager.SetName(myentity, "name");
#endif
wait did you want to give it a name for serializing?
No, just naming it so I can find it easily in the Entity debugger
It's an entity I created using EntityManager.CreateEntity()
Maybe have a dictionary In your manager or something with entity Ids keys and string values.
So one can not name his entity created using the EntityManager by code if he does want to do so?... That's weird, isn't it?
Entities are basically Indexes in an array. You can even use string in ecs.
If you want to tag some entity you'd do it with an empty component.
I guess because string is a reference type.
But you could have a component with an array of ints and convert them to/from chars and then to strings.
just do that for setting the name for the editor entity debugger, obviously that gets skipped in a build. there is also NativeString64/128 etc if you want to give your entities a name inside their components although Ive never used that personally
ok, thanks
Has anyone tried running unit tests against the client/server stuff in Netcode? I seem to have some issues with RPCs. Since the NetCodeTestWorld has some internals in it, I found I had to copy that code into my test module. I added the RpcCommandRequestSystem systems for my Rpc Commands on testWorld.Bootstrap (userSystems).
InvalidOperationException: <>c__DisplayClass_NetEvent_AuthChallenge.Data.rpcBuffer is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.
it reacts on this line:
rpcQueue.Schedule(rpcBuffer[...
switching over to applying it as parameter to Entities ForEach solves this error:
(Entity entity, int entityInQueryIndex, in DynamicBuffer<OutgoingRpcDataStreamBufferComponent> rpcBuffer,```
But now the ForEach never runs...
I'm surprised how few unit tests have been written for Netcode
Not much to go by
Oh, and I also get this (which I have to fix locally):
com.unity.entities@0.4.0-preview.10\Unity.Entities.Tests\ForEachCodegen\ForEachTests.cs:(431,25) error DC0022: It looks like you're capturing local variables from two different scopes in the method. This is not supported yet.
RpcQueue.Schedule is of course writing to the buffer, so rpcBuffer can't be read-only
e.g. adding .WithReadOnly(rpcBuffer) to the ForEach
I have no Ghost serialization yet though, so may this be the issue?
e.g. must there be ghosts in order for RPCs to work? I would have thought it would be enough to just have a client and server connection with NetworkIdComponent, etc.
Or maybe the RpcQueue/Buffer just doesn't support Entities.ForEach and must use an IJob implementation
hm
I was running the concurrent / schedule version of Entities.ForEach, but looks like it requires the Run() version... now it works.
Weee!
This is the great thing about Unit-Testing and the current state of DOTS. It makes it so much easier to trigger the errors that still require the runtime to catch.
Its so refreshing not having to generate any RPC related code though, from how it was in the previous version.
Just annoying you have to destroy the RPC entity on receivers end ๐ค
Hehe yes, but they're so type specific. I guess one could generate code for it and run it in a late system
I've though of that, but the heartbeat system adds the send RPC on the same entity, so it would mess up that system ._.
I guess one could check for excluding the heartbeat RPC from that system ๐ค
But it becomes such a idiotic bughole if they decide to add another system doing the same thing behind the curtains x)
Hi all i'm tying to deallocate a nativequeue used only inside my job but i got an "use DeallocateOnJobCompletion" error which, when i use it, give me an "uses [DeallocateOnJobCompletion] but the native container does not support deallocation of the memory from a job" error. Is there a way to dispose the native queue from the job or do i need to use a commandbuffer for that ?
Yeah Jaws, best to roll with the punches and accept some of the short-comings. Its getting better and better at least.
@pseudo epoch After your job has been scheduled you can call container.Dispose(jobhandle) and it will dispose it after the job completes
How can i give the right containers when scheduling job ?? @zenith wyvern
i need a container for each of my job
I'm not sure what you mean, you pass the container during job construction like normal then call dispose on it after your job is scheduled
var list = new NativeList<int>(Allocator.TempJob);
inputDeps = new SomeJob
{
jobList = list,
}.Schedule(inputDeps);
list.Dispose(inputDeps);
So do that once in a forloop for each job?
If you need them to be parallel you can use JobHandle.CombineDependencies on the handle returned from .Schedule
i don't see what u mean ^^' an example ?
for( int i = 0; i < lists.Count; ++i)
{
var job = SomeJob.Schedule(
list = lists[i]
).Schedule(inputDeps);
inputDeps = JobHandle.CombineDependencies(inputDeps, job);
lists[i].Dispose(job);
}
You are scheduling job multiple times
And i don't need to write on containers from multiple jobs i just need each job to have it own container create it use it and free it all by himself
The problem is that i can't dispose containers from inside job and the attribute DeallocateOnJobCompletion don't work
You should be able to figure this out based on what I just posted. Another suggestion: If the jobs container's are truly used only by that job you can create the container from inside the job using Allocator.Temp
Then you don't need to call dispose on it, it will be disposed automatically
Yep but no
i keep getting the "native container can't be deallocated from a job" error
Or a memory leak
All I can say is to read the code I posted very carefully. If you're sure it doesn't apply to your case you need to explain your case more clearly, maybe a pastebin with the full code for context
Combine Dependancies is for write on the same array from multiple jobs no ??
No. It does what it says. It combines two dependencies so when you pass it down the chain the next link waits for both the inputs to finish before it runs
If you don't need anything to run in parallel just forget the CombineDependencies part and do it the way I showed in the first code I pasted except in a for loop.
This is what i'm trying to have
public void Execute()
{
var list = new NativeList<Entity>(Allocator.Temp);
// Use your list and do NOT call dispose at the end, it will be disposed automatically
}
Get rid of the part where you're passing in a list. Just create it inside your job using Temp, like I said earlier.
Testing it
@zenith wyvern yey seems to work !!! Thx and i'm sorry for not explaining myself not clearly enough ^^'
Hey people, How long in cpu time does your PresentationSystemGroup run? I'm running a scene with 101 static entities, no systems running aside from rendering, and it takes 3 ms just for that and + 2ms for the rest of the stuff. I'm asking, because I'm watching a tutorial in which the guy gets twice less cpu time.
So I was wondering if it's just the hardware difference or I'm doing something wrong?
btw, these entities are just quads with some some texture using transparent unlit shader
And I noticed that if I change the shader I can get a variation in the cpu time ranging from 5 to 10 depending on the shader. Lastly, no matter what I do, I can't seem to batch these meshes into 1 batch. They all stay in a separate batch.
Moreover I find that shaders without gpu instancing option actually perform better then with ><
Sounds likely to be just hardware diff. If you're following a tutorial, well, there's a fair chance someone making tutorials have a pretty beefy rig.
I wouldn't worry about the numbers themselves, though - they only really have value in comparing apples to apples (is this code more performant if I do X or Y?).
I also suspect that there is quite a bit of bottom-level overhead, that is, overhead/perf cost that is there no matter what. You might still be able to do a lot of stuff on top of that relatively cheap in comparison.
I see. Then what about the Batches and gpu instancing? Doesn't seem to work for me.
@willow plaza are you using the hybrid render stuff?
you can.. it's only being worked on with hdrp for now though as a warning - if you were using urp with the batcher stuff I think that causes issues
that said, with the built-in/legacy batching works ok for me with hybrid
just have to use a standard shader with gpu instancing enabled I believe
I'm on built in and gpu instancing doesn't seem to affect the batches count.
Hmmm
I wonder if I'm doing something wrong, cause just 1000 entities already take 30 ms cpu time...
yea, from memory I can render about 100k cubes in ~8ms (cpu) with hybrid + built-in
burst enabled, safety checks off yea?
you want Jobs->Leak Detection->Off and Jobs->Burst->Enable Compilation in general
if your stuff isn't batching then it's not instancing
and if your material has instancing turned on then it seems like they are considered as different rendermeshes
Are you using the Hybrid Renderer specifically? So RenderMesh components on all your entities at runtime?
which prob means that they're all getting their own seperate chunk mansion to live in
If so do they all share the same mesh/material?
would line up with it being slower
That's the only scenario hybrid renderer is optomized for right now
Leak detection off, compilation enabled. Still the same processing time ><
Anything else is going to run like crap
@zenith wyvern I do use RenderMesh components on all my entities.
these guys are right.. though 1000 non-instanced individual meshes taking 30ms cpu time still sounds slower than expected to me
And do they all have the same material and mesh?
It's not, if they are all in different chunks hybrid renderer is seriously going to be horrible
what shaders are you guys using?
It's just god awful right now for any kind of instanced rendering. Megacity works well because it's tons and tons of entities with the same material/mesh so they can make a ton of optimizations for that specific scenario
I use built in or URP right now
@willow plaza from memory I think any of the Standard or Mobile/ ones should work - is your mesh high in verts?
And just use ECS for all non rendering stuff
You can verify in the entity debugger if your entities are in the same chunk
also have you restarted Unity recently? :trollface:
okay
false alarm guys
I was generating a separate quad for each entity apparently
That would do it
now the instancing works too
thanks for brainstorming with me.
and the processing time went down to 3 ms with 1000 entities ๐
Sounds better.. what cpu outa curiosity?
cpu time or my hardware?
hardware sorry
I'm not very strong with hardware, but something like that:
and 10000 entities still lag pretty badly
sorry 100000
10k entities are playable I guess: 9 ms
Not that I'd need that many at the same time.
sounds about right
imo hybrid renderer is still very unoptimized even with static batched rendermeshes
Dreaming of a day when hybrid renderer can compete with Graphics.DrawMeshInstanced
Maybe that's an unreasonable hope
is it not the same under the hood?
No, DrawMeshInstancedIndirect can easily render millions of quads at 60fps on my machine
All with unique data
Hmmm
also as you mentioned they were static I think - you should get a big speed up if you put them in a subscene or add the necessary frozen tags (can't remember what they are off the top of my head)
Oh yeah by default it treats everything as dynamic and that adds a ton of overhead
You should see huge improvement if you can get it to treat them as static
I had trouble figuring out how to do that with dynamically generated entities personally
Ah, they're static at the moment, but they're all gonna be moving entities soon.
it's weird because i think they were using drawmeshinstanced in hybrid renderer v1 but then decided to use this other api which is in the C++ part of engine
which you'd think would be faster otherwise why would they use that instead
I'm guessing their new system will fit in better with the whole workflow once they have lights and everything else converted to ECS
Maybe it will always be a little bit slower in order to fit into that
Like with URP? I'm not sure, I think so
public class MovementSystem : ComponentSystem
{
protected override void OnUpdate()
{
float dt = Time.DeltaTime;
Entities.ForEach( ( ref Translation translation, ref MovementComponent movement) =>
{
translation.Value += movement.direction * movement.speed * dt;
}
);
}
}
Can anybody tell me what exactly allocates garbage in that system?
And is it possible to dispose of it completely?
Ignore the fact that it doesn't use jobs atm.
Nothing that I can see, maybe Entities.ForEach in a ComponentSystem generates garbage. There's a good chance whatever's doing it will only do it in the editor
Aaah. Okay then. Thanks.
If you're worried about allocations always make sure you verify it from profiling a standalone build
What kind of allocation does the editor add? Something for profiling?
also on the off-chance you're unaware, Entities.ForEach was recently added for JobComponentSystems so now making that jobified is super simple. I mention this because I believe the JCS ForEach will possibly eventually replace the CS ForEach and has had more work done on it recently - there's rarely (never?) a case when you'd prefer a CS going forward is the intention I believe
the editor adds gc because of the checks - disabling the jobsdebugger & leak detection removes a lot but I'm not sure all
Lots of allocations related to the safety system
And yeah, see the dots pong example for how you're supposed to be writing systems now, even main thread systems
@amber flicker Yeah, I already read about the new JCS foreach. It's just that I'm following a relatively old tutorial where it was not implemented yet. Gonna change it soon.
Alright. I've got it running at least, so I'm done for tonight.
Thanks for help again.
I'm currently using the Job system to calculate 3D-meshes, would changing my render objects (several GameObject with Mesh Render, Mesh Filter and MeshCollider), to ECS components and systems give additional performance?
If you're making effective use of the job system then probably not. ECS would just help you organize your workflow to make it easier to get that performance
For rendering definitely not. You're better off not using Hybrid Renderer for anything procedural
Ok, thanks @zenith wyvern
Btw, the Jobsystem can only be used on the main-thread, right?
Not sure I understand the question. It's a job system, by definition it runs in threads
I meant it can only be scheduled/completed() on the main thread
Oh, yes you can only schedule or call complete() from the main thread
anyone on the current latest packages and getting instability with entering playmode? its a semi consistent thing but after some compiles, the editor will just crash or freeze up after attempting to enter playmode, and a restart fixes it, but not consistent enough for a definitive bug repo
@safe lintel Someone yesterday mentioned running into errors when using it, but I don't know of specifics.
I'm using 0.3.0 and haven't run into any issues yet.
i dont remember it being a thing with 0.3, only 0.4 but i also have a poor memory ๐
@safe lintel I had this issue a lot, disabling the fast enter playmode options seems to help
- sigh * So, I'm trying to convert my project to DOTS and would like to use
NativeLists. It seems like they can only be used with structs, no classes? I have a data structure that has to have references to other values of the same type (ie,MyClasshas a property of typeMyClass), but that's not possible with structs. Guess I just gotta use a mix ofListsandNativeLists?
@verbal pewter That's correct, you need to use a struct. But the restriction is even harder, the types used in NativeArrays (and thus NativeLists too) must be blittable. Therefore the struct can only contain blittable types, here's an article explaining what that means: https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types
Common Unity specific types such as Vector3 etc are also blittable.
@fair vine Interesting, thanks for the info. I'm guessing the Unity.Mathematics types such as float2 are blittable too, then.
Yep, those should work fine
Something to keep in mind is that bools aren't blittable
I've had some trouble with that before, it's not obvious haha
Hey everyone, I'm using an EntityQuery to get a component array in a system update. However, this call is allocating 64B every update. Am I doing something wrong, do I have to just accept this GC cost, or is this actually not a problem?
Here is code:
private readonly List<RenderComponent> _shared = new List<RenderComponent>();
protected override void OnCreate()
{
var types = new NativeArray<ComponentType>(3, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
types[0] = ComponentType.ReadOnly<Translation>();
types[1] = ComponentType.ReadOnly<Rotation>();
types[2] = ComponentType.ReadOnly<RenderComponent>();
_query = GetEntityQuery(types);
types.Dispose();
}
protected override void OnUpdate()
{
_shared.Clear();
EntityManager.GetAllUniqueSharedComponentData(_shared);
if (_query.HasFilter())
_query.ResetFilter();
foreach (var renderer in _shared)
{
_query.SetSharedComponentFilter(renderer);
// This call here is allocating 64B every update.
using (var translations = _query.ToComponentDataArray<Translation>(Allocator.TempJob))
using (var rotations = _query.ToComponentDataArray<Rotation>(Allocator.TempJob))
{
for (int i = 0; i < translations.Length; i++)
{
Graphics.DrawMesh(mesh,
translation.Value,
rotation.Value,
material,
renderer.Layer,
Camera.main,
0,
_props,
renderer.CastShadows,
renderer.ReceiveShadows);
}
}
}
_query.ResetFilter();
}```
Here is profiler:
Oh, I am using Unity 2019.3.0f1.
They're allocations from the safety system. They shouldn't be there in the standalone build.
That's what DisposeSentinel is
Sorry for the really dumb question, but does Burst speed up functions called by jobs? Or is it the code within the job functions alone?
Anything you call from a burst compiled job has to be burst compiled as well, it doesn't call back to Mono
See, dumb question. Thanks ๐
@willow plaza The ForEach itself generates a delegate so garbage. I think the same thing doesn't happen when you use a JobComponentSystem
Has to do with preserving the context of outside variables, there was a thread about it but I can't find it that quickly
How do you guys convert simple box colliders trigger events to dots? Or you would have to handle the collisions yourself?
@woeful quiver physics samples repo has examples how to use triggers in dots https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/UnityPhysicsSamples/Assets/Demos/2. Setup/2d. Events/2d1. Triggers
Thank you!
I'm trying to set up my entities on start via a job that is outside a ComponentSystem, but I can't kinda wrap my head as to how to do it.
According to the docs IJobForEach is supposed to be used in a JobComponentSystem, meaning it wouldn't work outside it?
I was thinking of using IJobParallelFor on a nativeArray of entities, but will I be able to access the componentData of each entity?
Also something I don't completely get about chunks. Is it simply a way to access all the entities with a certain archetype( or rather having the same set of components)? if I set component data of a chunk does it mean that it's gonna set the component data for each entity in a chunk?
If you need to create entities before a system runs you either do it in OnCreate or create a separate system that creates the entities that runs before the dependant system
Regarding your other question - read the docs https://docs.unity3d.com/Packages/com.unity.entities@0.4/manual/index.html
Tells you everything you need to know
yeah, I am reading them, but some places are not so intuitive to understand.
I guarantee no one in here is going to have a better answer to that question than this page https://docs.unity3d.com/Packages/com.unity.entities@0.4/manual/ecs_chunk_component.html
Read it carefully
Okay, I kind of understand about a chunk now. If I set chunk data It's basically data that is shared between all the entities in a chunk. So I can not set an individual position to each entity in a chunk this way.
So when I create entities with the entityManager one of the variations returns a native array of entities. I want to use it right away in a job to set random position to each of the entity. Does that make sense?
Guys, are somewhere out there updated tutorials on entity system? Or is the entity system scrapped? Because all i can find is from 2018 or start of 2019 with obsolete syntax.
Following the tutorials - i can't get anything to work since there's for example no such thing as IJobProcessComponentData.
Is it scrapped idea?
There's a playlist of tutorials pinned to the channel that are the most updated you'll find
ok! thanks!
Right at the bottom. The rest is all related API docs
I find it very difficult to make a bridge between ECS and usual GameObjects/components. For example when you are trying to convert your project to DOTS because you cannot convert everything at once. Converting from abstract OOP to it is sometimes crazy difficult.
What do you guys suggest? i am halfway in the development of a medium sized project, to achieve our objectives we need to convert part of the project to DOTS for performance reasons. However, that part is spread almost everywhere as I am talking about Character Controller and Animators.
@woeful quiver for context, I've been working with DOTS for about a year. I've also struggled massively with performance issues from Animators & Animation Controllers etc in the past. Support for any animation in DOTS is super limited right now - I'd really advise looking at other optimisation strategies within the traditional workflow. GPU animation for simple animators can be a big win, heavy culling where you can (i.e. disable gameobjects when culled) and even time slicing animator playback has worked for us before.
Hey, I am messing around with GPUAnimation: https://github.com/joeante/Unity.GPUAnimation and am having trouble getting it to work with my own model and animations. I think it may be because the animation and the model have different bone structures and naming (which is why I think it works when an avatar is made and used with the normal animator). As someone with limited knowledge about how these avatars and bones and rigs work I'm not quite sure how to fix it. Has anyone tried this and had similar issues?
Hi i'm testing Hybrid Components and added the wireframeGizmo (from ecs samples) on a prefab which i instantiate multiples time using a Spawner but i can't find the wireframe components on my entities while i can find it in the entity debugger of the ecs samples. Knowing scripts for hybrid component only take a few lines of codes how can this component not exist ?
Even create a new empty MonoBehavior with it's own GameObjectConversionSystem won't work ..
@woeful quiver the official animation package appears a long way off, skinnedmesh conversion is done, but the actual dots equivalent for animators is not nailed down, theres a github repo that shows it in use https://github.com/Unity-Technologies/Unity.Animation.Samples
personally not gonna attempt to make it work for my own project, its far too early for me
Thanks for your feedback guys, for me one of the major problems is that i am using many asset store packages, most of them are modified by me to better fit the need of our project. However, using DOTS all over means that i would need to not only change my code but maybe the code of these assets too, that's why it's a tough choice to make.
I say migrate step by step if your project relies on asset store packages. There will probably come alternatives that are DOTS native eventually.
I have a few of those on my list too, and will evaluate whether to use them as a reference for a clean DOTS implementation, or whether to let them live in GameObject space, and set up a proxy to the ECS world for communication
Setting up that proxy is what drives me crazy.
oh I bet
could also do simplified versions of those that works in DOTS until better alternatives come out, or you have time to roll your own properly
early adoption will be early adoption ๐
That's a question i keep asking myself since this morning.
DOTS makes zero sense for anything at the moment really, it's too unstable and incompatible with the rest of Unitys ecosystem
Other than for playing around, testing, etc.
@digital scarab That's not true tho, you can easily do what DOTS does for memory layout, threading, etc...
yeah it's easier for the average programmer in DOTS
but... it's not like it could not be made without DOTS.
Sure, but these are fairly high end customers I assume getting direct support from the core team, which for 99.99% of us is unattainable
So sure, if you have a fortune 500 company and enough money to levarage unity into help you, DOTS is great ๐
Hmm, that might work out, burst and jobs for my needs would do the job well. Thank you all, again!
@digital scarab I've run into so many issues with burst lately
Issues with statics that should work, issues with fixed layout structs, etc.
Is there a way to get the job index in a Entities.ForEach job?
Or rather is there a way to use EntityCommandBuffer in a Entities.ForEach job?
@digital scarab Plus how many platforms are missing Burst support?
I suppose maybe it's just Switch now a days
Yeah that's the one I ran into... of course
So between missing switch support, various bugs, etc.
I really don't get how you guys can call it production ready or stable
Just look at the forums
It clearly isn't
No, i stopped submitting bugs after two of them took 3 years to get resolved (IL2CPP related)
here's one of the issues i ran into
posted by someone else on sunday apparently
Yes, sure... absolutely, but core functionality of the language/platform not working != production ready
No... did I say that?
Fixed layout structs isn't some esoteric feature either, it's a pretty core part of the language
So when something that basic isn't working, then i wouldn't call it production ready? that's what i mean.
Also things like the scheduler doing all kinds of weird stuff, even with all safety features off in release builds, etc.
Threads sitting idle with no work being done on them when there's clearly work available
At some point the label "production ready" just stops meaning anything
Sooo, does anyone know how to use an EntityCommandBuffer in a ForEach job?
I'll be happy if you do.
protected override JobHandle OnUpdate( JobHandle inputDeps )
{
EntityCommandBuffer.Concurrent ecb = new EntityCommandBuffer.Concurrent();
EntityQuery playerQuery = GetEntityQuery( typeof( Player ), ComponentType.ReadOnly<Translation>() );
NativeArray<Translation> targets = playerQuery.ToComponentDataArray<Translation>( Allocator.TempJob);
var targetPos = targets[0].Value;
targets.Dispose();
var job = Entities.ForEach( (Entity e, int index, ref MoveTo target, in Translation entityPos ) =>
{
if(math.distance(target.Value, targetPos) > 0.1f)
target.Value = targetPos;
if (math.distance( entityPos.Value, targetPos ) > 0.1f)
ecb.RemoveComponent( index, e, typeof( MoveTo ) );
} ).Schedule( inputDeps );
//ecb..Playback( EntityManager );
//ecb.Dispose();
return job;
}
I have that in a JobComponentSystem. However unity gives out an error that index is not supported parameter.
@willow plaza use ToConcurrent on an ECB, not new EntityCommandBuffer.Concurrent
Also: you are creating an ECB that is never played back. You should get an ecb from an EntityCommandBufferSystem to have it auto-playback, or call .Playback() manually at some point
https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/ECSSamples/Assets/HelloCube/5. SpawnFromEntity/SpawnerSystem_FromEntity.cs
Here's a working example in the samples
@willow plaza no the API isn't amazing when it comes to usability ๐ฆ
Yeah I was calling the Playback on regular
as you can see I've commented it out, since the concurent version didn't have it.
I guess I'll need to go through the examples after all...
But are they updated to the latest ecs package?
Alright. A lot of stuff to read through then I guess.
@digital scarab Any idea why the scheduler would do this?
I have two jobs, which are sequential
i.e A=>B, Simulation.Collect and Simulation.Broadphase
There's a lot of waste idle times, etc.
This is on an 8 thread machine, and each job is split into 8 intances
And it just WILL NOT use all threads to process A and then all threads to process B, in order.
I can reproduce it every time i run it.
It simply flat out will not use all threads
the higher thread count CPU i use the worse it gets
i.e. on a 2c/4t its mostly fine, 4c/8t you see above, 16c/32t it's even worse than above
8c/16t is about the same as the 4c/8t in inconsistency
How are we supposed to build real time sensitive systems (i.e. high frame rate games) on this when the scheduler simply will not run things in an optimal order? And cause fairly huge stalls. The code above jitters between 0.3-0.4ms and 0.6-0.7ms depending on ... what the scheduler feels like doing
standalone build, all safety off
I probably can yes, i can't share the project as is atm
I know how hard it is to build a good scheduler, i built our task scheduler for our stuff - and put a mind boggling amount of effort into making sure these stalls do not happen.
I'll see what i can do to pack it up into a repro case this week, it's not a lot of code actually (just the start of a deterministic 2d physics engine) but i need to cut some stuff from it
I've seen this happen a few times and every time i have literally no way to figure out what it's doing or why, there's zero rendering or anything going on here also.
It's just pure logic, nothing else
And trying to build a stable predict-rollback deterministic system on top of this is...impossible.
Literally, because you have no way of knowing you CPU budget
When it fluctuates with like up to 2x at times
Alright, I got it working more or less with this code:
protected override JobHandle OnUpdate( JobHandle inputDeps )
{
var ecb = m_EntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
EntityQuery playerQuery = GetEntityQuery( typeof( Player ), ComponentType.ReadOnly<Translation>() );
NativeArray<Translation> targets = playerQuery.ToComponentDataArray<Translation>( Allocator.TempJob);
var targetPos = targets[0].Value;
targets.Dispose();
var job = Entities.WithBurst( FloatMode.Default, FloatPrecision.Standard, true )
.ForEach( ( Entity e, int entityInQueryIndex, in MoveTo target, in Translation entityPos ) =>
{
if (math.distance( target.Value, targetPos ) > 0.1f)
ecb.SetComponent( entityInQueryIndex, e, new MoveTo{ Value = targetPos } );
if (math.distance( entityPos.Value, targetPos ) <= 0.1f)
ecb.RemoveComponent( entityInQueryIndex, e, typeof( MoveTo ) );
} ).Schedule( inputDeps );
m_EntityCommandBufferSystem.AddJobHandleForProducer( job );
return job;
}
However I get a runtime error:
D:\GameDev_Unity\Project HM\Assets\Scripts\Systems\TargetingSystem.cs(32,3): Burst error BC1025: Accessing the type `MoveTo` is not supported
at TargetingSystem.<>c__DisplayClass_OnUpdate_LambdaJob0.OriginalLambdaBody(TargetingSystem.<>c__DisplayClass_OnUpdate_LambdaJob0* this, Unity.Entities.Entity e, int entityInQueryIndex, ref MoveTo target, ref Unity.Transforms.Translation entityPos) (at D:\GameDev_Unity\Project HM\Assets\Scripts\Systems\TargetingSystem.cs:32)
@willow plaza dont think in is supported
in works fine. Can you paste MoveTo definition?
oh, wait, don't do typeof(MoveTo)
oh yeah cant do that
typeof() returns a System.Type, which is managed, a.k.a. Burst doesn't understand it
Or is there no way to remove a component?
and use it inside
oh
RemoveComponent<MoveTo>(etc)
Ah
okay
that makes sense
Alright. no errors finally! Thanks for the help guys.
That dots stuff is much harder to wrap your head around compared to other unity systems I must say though.
Too much stuff. And also a lot of not obvious stuff.
@indigo orchid I was just going through this this morning, i have a model rigged with mixamo and it doesnt appear to work at all, and another model I rigged myself which does appear to work. seems picky on what it accepts but maybe give a different model a try?
Anyone know if there is an ecs example where live link actually works ?
I've noticed that all of the samples in ECSSamples on github are for V31. Are there any samples demonstrating changes in V4 aside from the "pong" video?
V31 is the example version, it's not related to the ECS version. The samples are using the latest API
Ah I see. I've just seen the [BurstCompile] attribute on some of the examples, which I heard is not necessary anymore, so I thought it's for an older version...
The burstcompile attribute is necessary if you're still using the job structs, which is necessary in some cases
IE there's no Job.WithCode.ScheduleParallel(). Though I wish there was
I see. Thanks for clarifying that.
am I the only one getting an error in the Entities.Tests package in 2019.3.f4 / Entities v 0.4.0.preview10?
It probably requires that entities are added in the tests section of the project manifest
but idk
Has there been any word on 2d dots renderer being released this year?
Or does DOTS roadmap exist?
Writing a state machine in pure ECS is quite interesting. System State Component to the rescue
I don't know None, but there's been a few good tutorials on rendering a ton of sprites, but I'm sure you're aware.
@twin raven take a look at Code Monkey channel. (https://www.youtube.com/channel/UCFK6NCbuCIVzA6Yj1G_ZqCg)
He have some videos where you can see how to use it for 2D games.
When I use add a "Convert to Entity (Stop)" script I assume that is meant to stop the recursive conversion of a gameobject to an entity? This seems to be the case when the gameobject is placed in the editor however when trying to then instantiate in the proper manner (DeclareReferencedPrefabs or GameObjectConversionUtility.ConvertGameObjectHierarchy) it doesn't seem to consider these scripts. Is this intended?
I ask because I am currently using an ECS system to render skinned meshes but I still want to use the gameobject to control the position and physics.
Is there a way in a IJobForEach<T> to access the IJobForEach intrinsic NativeArray/iterator of type T ?
I need an array of the T type containing all corresponding T entities and i'm getting the "two Arrays may not be the same (aliasing)" error because of a ComponentDataFromEntity<T> inside the job
Either get the arrays from the query with query.ToComponentDataArray<T> or use https://docs.unity3d.com/Packages/com.unity.entities@0.4/manual/chunk_iteration_job.html
Does anybody know if there is a builtin method in the math library to have an eased version of lerp?
@solemn ice not to my knowledge - though if it's useful, there are many copies of Penner's easing functions which are easy to put in a lerp - e.g. https://github.com/acron0/Easings/blob/master/Easings.cs
Does anyone know if Monobehaviours or if Jobs get executed first? I have a value I'll need to set every frame using a coroutine in a Monobehaviour that will determine how many times the code in a Job gets executed for that frame.
As a side question then, is it possible to have an entity follow the transform of a game object that is instantiated from code? I know of the "CopyTransformFromGameObject" component but am not sure how it works/if you can specify the game object in code or if it has to be the same gameobject entity
It's possible yes but a little annoying and there's no good examples out there from Unity
Wait is the gameobject instantiated in code you mean?
Yeah though Instantiate(prefab, ...)
Wherever you instantiate it you can do
World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<SystemType>()
And pass your gameobject to your system when it gets created
Okay, that sounds reasonable, I will give it a go now. Thank you
is ECS compatible with URP?
I'm trying to spawn simple cubes as entities, I give my cube prefab to my script, convert it to entity, then spawn it in a grid. but nothing is rendered. I can see the entities in the debugger.
I'm using a code demo that uses regular unity 3D and not URP so I'm wondering if it's compatible with URP at all
using 2019.3
or if anyone can show me a demo of spawning entities from game object prefab in unity 2019.3 using a scriptable render pipeline, that would be appreciated
@odd ridge nope, not compatible with URP - HDRP only and even that, only partially (no light baking etc afaik) - support planned for later this year I think
thanks!
np ๐
though I should add.. I believe you can get various degrees of success with standard/mobile shaders with built-in and URP/LWRP if you disable the URP batcher and stick to super simple things but official word is they're focusing on hdrp first
I was wishing I could use both DOTS and have the visual shader editor, what do people use to make shaders without the visual editor?
@odd ridge well, technically to render anything with DOTS, you need Hybrid Rendering package. The official stance is that HDRP is their main focus at first but to me even the built-in renderer seems more stable with it
URP is used by some of the examples too afaik
like, if you look at DOTS shmup repo, I think it used URP with hybrid
there are things that will just break tho
also I think TinyRacing used URP(?), that was totally broken in the editor because of the lack of proper support on it
oh wow.. @dull copper I forgot to install the hybrid renderer package, well at least I got my first ECS experiment working now
is it normal when I click play, it takes like 5 seconds to start even for a nearly bare empty project? and when I edit a script and come back to the editor, it takes 5-10 seconds to recompile the scripts
or script, I got 1 script 50 lines long..
you can try to enable the new fast playmode option - project settings> editor> enter play mode [x]
I'm having trouble figuring out how to create an entity with an IComponentData struct I've created. I'm guessing I'd need to use the CreateEntity(ComponentType[]) overload, but I'm not sure how to convert a struct to ComponentType.
does anyone know if unity is actually planning on speeding up the assembly reload time? its super painful to recompile with even a small dots project and all the package assemblies
you can create an entity of a set archetype which i think auto adds the components specified in said archetype
@safe lintel thanks, does speed it up a lot
Ah okay. So I can't just create a struct and create an entity with it?
@odd ridge it might introduce some instability, in the current latest packages it might crash after a few script changes so beware ๐ฌ
right
why not create the entity and then the component? @verbal pewter
I guess I'm having the same problem with that. _entityManager.AddComponent(entity, myStruct). Says it can't convert myStruct to Unity.Entities.ComponentType. Not understanding how this is supposed to be done.
can you paste you struct?
{
public City City;
public List<ConnectionTemplate> ConnectionTemplates;
public float GrowthFocusStrength;
public float GrowthRate;
public NetworkTemplate NetworkTemplate;
public int NodeCount;
public float PendingExpansion;
public Simulator Simulator;
}```
if you use AddComponentObject instead of AddComponent does it work?
Oooooh, yep! Awesome, thanks ๐
also maybe you want to change struct to class if you are adding it as an object type but tbh im not really too familiar with how class stuff works in the grand scheme of components
Hmmm, didn't think we could add classes to entities. Thought they had to be structs?
its a somewhat recent change, you wont be able to use classes in burst jobs afaik
Ahhh, that's a pretty big downside. Would there be any benefit to using a class?
how do you change the clipping distance for the dots renderer? objects disapear in the far but I want them all to be drawn
should just change the settings for the camera?
also for classes, it allows you to use class stuff in systems on the mainthread to "unblock development", to allow an easier transition. in some cases its ok to use class stuff though if you need high perf you will probably want to restructure it
Hmmm, okay. And to clarify, are there issues with using IComponentData structs that have class fields? I.e., Burst not being useable with those or something?
yeah you wont be able to load NetworkSettingsData into a job as it stands
but the blittable parts could be separated from NetworkSettingsData into their own component and then used in burst jobs
I'm looking in the entity debugger, it shows 3 sections: initialisation, update and prelateupdate
is there a way to entirely disable pre late update step?
@safe lintel That's good to know, thanks. In this case even if I could use jobs I wouldn't since I need to have this code execute in a deterministic way (used for procedural generation). I was hoping Burst would still be able to speed it up, but it sounds like it only provides a speed up when used with structs containing only blittable data?
What the main idea behind dots? Does it really brings that much of a difference?
From what I've seen on youtube, programming seems over the hand, overcomplicated
Also does it improves mobile performance?
It improves performance in all sectors
simply using ecs to program beats the hell out of the old way imo. my own personal issues are that its super early(anim, rendering) for some packages, and others dont even exist yet(like nav, sound). also editor stability issues, can be hard to debug problems.
I have a question about the "DOTS Training", there's a ClothJob project within, and one attempt to put the mesh into a component was basically this: https://hastebin.com/ezepicimub.http
Using GCHandle.Alloc, but in use, I get a "Handle was not allocated" errors. I'm not sure how to use GCHandle, I guess?
@safe lintel my problem so far is it's super slow to compile, everytime I change a script, the editor freezes for 5-10 seconds. the editor playmode fixes entering play mode which would also take its own 5-10 seconds, but it's still very annoying
I wish I can fix this because I don't see myself waiting 5-10 secs for a single file change that should take 1 millisecond to compile
you should try unreals c++ ๐
lol
I thought I could fix this by using an assembly for my code, so that when a change happens, only my code has to recompile and not the whole unity assembly
nope, still extremenly slow for a near empty project
I'm not sure what makes it so slow though, trying to figure out how to get the compile log
@odd ridge you use HDRP?
URP
When people first brought it up Unity was like "Yeah nothing we can do" but it sounds like they're looking into it now at least
I'd suggest adding your voice to that thread if it's that bad for you
thanks I'll look it up
i think its the assembly reload
for the record mine takes like 15-20 seconds on average with a decent cpu(8700k) it drives me crazy compared to how it is on a mostly empty new project
@safe lintel it's just ridiculous that unity recompiles everything for any single change. I have a c++ project and only the files affected are to be recompiled which lets me do changes and get back in the game in seconds whatever the project size may be. I was wishing to use unity for DOTS but that compile time is the worst thing ever
its that it reloads it all, regardless of the change if i understand correctly, the compile time is usually cut down. anyway it makes me want to switch to builtin and throw away all the package workflow. there arent really any significant answers in either thread that gives me the impression some sort of fix is anywhere near close to materialising
and no package means no DOTS right?
yeah
I need to share a Nativemultihashmap across systems on each ticks (initialized by a first system, used by a second, and disposed by a third) but the Icomponentdata say it's not a blittable. Any idee ??
Add it as a field in one of the systems...
No way to make singleton entity work ?? fill all systems is a bit ugly
Nope. Can't you put all the jobs in one system?
This was my setup before but i had trouble with ordering data disposition and data job scheduling so i'm currently splitting initialization, computation and cleaning for make them follow the systems groups of unity
The job scheduling should be the same in both variants. Did you set the job handles correctly?
Highly recommend watching the Overwatch GDC video on ECS. Big systems isn't necessarily bad.
all jobs was running not scheduling and a command buffer inside a job supposed to set a component broke the camera (mostly drawing black depending on the orientation of the camera which have no link with my code)
what do you mean by "all jobs was running not scheduling"?
job.run() not job.Schedule()
It should be the same then if you have multiple systems with dependencies or just run the jobs in sequence in one system. I even mix .Run and .Schedule jobs in some systems. Maybe you hit a strange side effect? They are hard to find sometimes...
i can send u the script if u want
May paste a link to it it here?
i rewrote the original script and send it to you ^^
try pastebin plz ๐
Conclusion:
- Use a new EntityCommandBuffer.ToConcurrent() for each job
- Triple check your job handles/dependencies
๐
<
how do I use the MeshRenderer or MeshInstanceRenderer in pure ECS?
I try to add component to my new created entity MeshRenderer, but I get error "must be a non nullable value type in order to use it as parameter ..."
manager.AddComponentData(instance, new MeshRenderer { material = material });
hmm you can't add a manged component to an entity... if you are trying to work with the hybrid renderer, the component you're looking for is RenderMesh (confusingly), however if you want to work with MeshRenderer's, you need to work with a traditional gameobject, not in a subscene
daschatten, I highly recommend unit testing your ECS code, to confirm your code works as you expect, simply because the docs are not yet super clear on everything, and we are all still learning.
@amber flicker how do I get a RenderMesh? I type it but my VS cannot find it
have you installed the hybrid render package? @odd ridge
@amber flicker I'm looking for rendering in pure ECS, do I still need hybrid for that?
@remote coyote For some parts i use integration tests. But for all the networked stuff i haven't added them yet...
yea it's a little confusing with the naming - I think it's called hybrid renderer because the meshes and materials aren't originally blob assets? I actually have no idea (anyone else know?) but it's the package you need for pure ecs rendering
oh okay, and RenderMesh component would be for pure ecs right?
yes
@amber flicker You can add a managed component to an entity with AddComponentObject
yea that's a good point ๐ I should have mentioned
I'm trying to use RenderMesh as such
manager.AddComponentData(entity, new RenderMesh { material = material, mesh = mesh });
but I get error
"RenderMesh must be a non nullable value type in order to use it as parameter"
AddSharedComponentData for RenderMesh ๐
thanks
Hey people, wasn't the project Tiny available in the preview packages?
Yeah I'm doing it for the networking stuff right now daschatten. Not a lot of tests in Netcode to go by, and the test world they've got there for client/server has internal stuff, so leaves "something" to be desired. Thankfully its all open source.
Maybe it's too early for netcode to have a lot of tests ๐
But at least it seems to work...
I have been using this method to convert game object to entity
GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, ConversionSettings);
ConversionSettings is obtained from GameObjectConversionSettings.FromWorld(DefaultWorld, null);
problem is, I have been using since the start of my project with no problem, and now it doesn't work anymore
unity complains that I cannot pass null as second parameter to GameObjectConversionSettings.FromWorld
"ArgumentNullException: A valid BlobAssetStore must be passed to construct a BlobAssetComputationContext
"
yet it worked for the past 5 hours
why
hmm I use the same - is it actually DefaultWorld that's null I wonder?
Is JobComponentSystem OnCreate called on a thread?
Either that or it runs before Awake on monobehaviors...
afaik yes, it runs on main thread and before awake (though I don't know if that's guaranteed going forward)
how would I cache some variables for a system then? oO
hmm.. not sure I understand your use case but it sounds a bit like what subscenes and conversion are for?
I'm trying to get my GameManager with a static instance. However it is only set in awake of that GameManager,
like if I need to pass some preconfig data to a system on create.
Oh, apparently There's the OnCreateManager() callback for that...
there are so many ways to think about this - I'm generally not a fan of singletons so I'm probably not going to be that helpful. That said generally, if your system requires data to run, then it should potentially require a ICD with that data. E.g. your GameManager might create an entity with that data then the system would run as soon as it was ready. That said, it sounds like you may be sorted and there are pros & cons for any approach obviously ๐
ICD?
IComponentData
Hmm... I guess I could make it an ICD but that kinda feels like a waste, since I only need to cache some material and mesh data.
only once. Then it will be use from the reference.
I can't really speak to your specific use case but I certainly think that somewhat by definition in ECS land, if your system requires certain data to run, it should require that data explicitly
@willow plaza Sounds like a good case for a ScriptableObject
Yeah, I found some suggestions to use it on the forum too.
Put your static data on a scriptable object and inject it in OnCreate using Resources.Load or addressables
but for now I have a different problem:
There's an error from the safety system apparently and I've no clue why.
InvalidOperationException: The previously scheduled job TargetingSystem:<>c__DisplayClass_OnUpdate_LambdaJob0 reads from the NativeArray <>c__DisplayClass_OnUpdate_LambdaJob0.Data._lambdaParameterValueProviders.forParameter3._type. You must call JobHandle.Complete() on the job TargetingSystem:<>c__DisplayClass_OnUpdate_LambdaJob0, before you can write to the NativeArray safely.
I used the jobs as you would do normally(I thnink?). And I get this.
It's telling you what you need to do. You're trying to write to the array before you've guaranteed the safety system that the previous job reading from that array is complete
You either need to call complete on the previous job or schedule your array write depending on the previous job
That's a simple job though. If I force it to run on the main thread the error moves to a different system, that worked perfectly fine before ><
Calling complete doesn't mean you're forcing it to run on the main thread. It causes a sync point yes, and it's your job to make sure that sync point is created somewhere that makes sense, IE: After the job is actually complete, which you can check with JobHandle.IsCompleted
Or you can schedule your write job to be dependant on the read job like I said, that way there's no explicit sync point
Like for example in this job:
protected override JobHandle OnUpdate( JobHandle inputDeps )
{
float dt = Time.DeltaTime;
var jh = Entities.ForEach( ( ref Translation translation, in MovementComponent movement ) =>
{
translation.Value += movement.direction * movement.speed * dt;
}
).Schedule(inputDeps);
return jh;
}
there's no need to complete it or anything, right?
all of my systems are using 1 job only. No complicated logic.
The previously scheduled job TargetingSystem
That's OnUpdate for your TargetingSystem?
nope, but it was working before without giving me any errors. After adding a different system it started giving this error.
Here's the OnUpdate of the Targeting system
protected override JobHandle OnUpdate( JobHandle inputDeps )
{
EntityQuery playerQuery = GetEntityQuery( typeof( Player ), ComponentType.ReadOnly<Translation>() );
NativeArray<Translation> targets = playerQuery.ToComponentDataArray<Translation>( Allocator.TempJob);
var targetPos = targets[0].Value;
targets.Dispose();
var job = Entities.WithBurst( FloatMode.Default, FloatPrecision.Standard, true )
.ForEach( ( Entity e, int entityInQueryIndex, ref MovementComponent m, in Translation entityPos ) =>
{
if (math.distance( entityPos.Value, targetPos ) <= 0.1f)
m.direction = float3.zero;
else
m.direction = math.normalize( targetPos - entityPos.Value );
} ).Schedule( inputDeps );
return job;
}
Here's what was happening before I changed a different system to .Run :
I would say try passing in your Player as ReadOnly as well to the EntityQuery, and also you may need to use
Since your job is dependant on the array generated by ToComponentDataArray
hmm
also your entityquery should probably be created in OnCreate - though I doubt that's the source of the error here
Mmm I guess since you're disposing it immediately it wouldn't be dependant
Yeah
I just don't understand why it worked before, but gives an error after introducing a new system?
that's some quantum mechanics. Programming shouldn't be so indeterministic. ><
Are you sure the error is happening at the first bit of code you posted specifically? Like that's the line the debugger is pointing you to?
if your other job requires Player it may be that the safety system can't tell the job is done with it in this job
no it doesn't It's a pretty long call stack
It's telling you that you're trying to write to something but whatever is reading from it previously is not being provided as a dependency so that the safety system knows it's okay
Hmmm...
That's a potential race condition and it's not something that can just automatically be resolved. You need to be aware of everything that is reading and writing to your components
That's a bit of a different error. I was getting it first, before I changed it to .Run:
If you're ONLY reading and writing to yoru components in Entities.Foreach blocks the safety system can resolve everything on it's own
So the error has to be occurring because you're trying to read and write to your components outside of ForEach blocks
NativeArray<Translation> targets = playerQuery.ToComponentDataArray<Translation>( Allocator.TempJob);
var targetPos = targets[0].Value;
targets.Dispose();
That is, technically.
I don't know if that's the source of your error.
But yeah
That is reading from a component on the main thread, outside of a foreach
this piece is okay, right? Since I run it on the main thread?:
protected override JobHandle OnUpdate( JobHandle inputDeps )
{
material = GameManager.manager.GetEnemyMaterial();
Entities.WithoutBurst().ForEach( ( ref Translation translation, ref SpriteSheetAnimation_Data spriteSheetAnimationData ) =>
{
uv[0] = spriteSheetAnimationData.uv;
materialPropertyBlock.SetVectorArray( "_MainTex_UV", uv );
Graphics.DrawMesh(
quadMesh,
spriteSheetAnimationData.matrix,
material,
0, // Layer
camera,
0, // Submesh index
materialPropertyBlock
);
}
).Run();
return default;
}
SpriteSheetRenderer.OnUpdate (Unity.Jobs.JobHandle inputDeps) (at Assets/Scripts/Systems/SpriteSheetRenderer.cs:41)
that's one of the new systems I've introduced, so I thought the error might be here.
That's what that is right?
InvalidOperationException: The previously scheduled job SpriteSheetAnimation_Animate
Animate writes to it, renderer is trying to read from it before you've called complete on the job. Now I'm guessing the renderer is not doing it's work inside a foreach?
Hmmm
it does
that's the last snippet
so because one runs on the main thread and the other not, they might be accessing the same components at the same time?
I'm not sure about that to be honest, I would THINK Unity could just automatically resolve it as long as everything is done inside a foreach
But I don't know for sure
If you can't figure it out just reduce your problem - create the smallest repro you can that still causes the problem so you can actually see what's happneing
Do you have [AlwaysSynchronizeSystem] attribute on your main thread systems?
I'm not sure exactly what that does to be honest but maybe it would fix it
I don't have that ๐คฆโโ๏ธ
and it actually fixed it ><
How the heck was I supposed to understand it from that error ><
Good to know, I actually thought that was some kind of optional optomization thing. I guess it's required for the safety system
Anyways, thanks a lot @zenith wyvern. I'd be stuck with that tomorrow to if you didn't mention it.
No problem
Alright, routine before sleep(being bewildered at how dots work) done. Time to hit the sack.
And yeah, that seems rough. I honestly think you should make a thread about it if you feel like it, it should really be better documented
Yeah, I'll think about doing it tomorrow.
I'm a bit confused about what situations Burst gets applies to. I have no idea how compilers work so sorry for any dumb questions. In the Language Support section of the user guide (https://docs.unity3d.com/Packages/com.unity.burst@0.2/manual/index.html#cnet-language-support) it lists the types that are supported. Does this mean that Burst will only compile jobs that use only these types, or that it will go through the entire job and will only optimize sections that use those types? For example, if I access an array in a singleton class from a job, will that negate Burst?
Burst throws an error if it sees anything it doesn't support
Burst only works with Jobs, and jobs have some very specific constraints on them in order to achieve thread safety. One of them is that you can't use just any managed type.
Think of Burst-compiled code as native code really
For example to use collections/arrays in Jobs, you use native collections like NativeArray
From my understanding NativeArrays can only be created using structs, right? If that's the case I don't think DOTS is even an option for me.
Yup, any reference types are off-limits for Burst
Are they off limits for Burst, or for Jobs altogether?
Also, when is it that Burst throws an error? I'm guessing when I try running the program, since it's not throwing anything in the console.
it should complain as soon as you press Play in the editor
Alright, not quite there yet but I'll keep an eye out.
I think you can create/use reference types in Mono based jobs (never tried tbh), but you definately cannot have any references in the job struct itself
yup, new ManagedType() seems to work in non-bursted jobs
(not that I'd ever recommend doing that)
Hmmm, alright. The big issue I'm running into is that I'm using ScriptableObjects to make the city generator I'm building as flexible as possible. As an example, I have Networks (such as "Roadways") that have a list of ScriptableObject Connections ("Small Road", "Medium Road", etc). The Network uses values in the Connection during road generation, which is part of what I was hoping to convert to DOTS. How do people generally use ScriptableObjects in relation do DOTS? In this example I guess I could, at runtime, take the values in Connections and create a struct to hold those values. Then, create a NativeArray of those Connection structs as reference values?
It feels kinda dirty to do that, but I'm not seeing any other options ๐
You don't have a choice really. Dots can only handle non-managed types, so you have to convert managed types to nativearrays/structs before you push them into dots.
It's the whole reason they built the whole ConvertToEntity system
Cool cool, thanks. I feel like I a better grasp of it now at least.
Burst/Jobs is so much faster though, that even with doing that conversion every frame you end up with code that runs overall quite a lot faster.
Best solution is ofc not having to do that conversion on the fly
ie if you NEED to have game objects at runtime
Yeah. Definitely some growing pains along the way, but it definitely makes sense to do what I can to get the most out of DOTS ๐
You can write parts of your game using Burst+Jobs, even without entities. I'm doing some of that atm ๐ its really great for math heavy stuff
Yeah, I'm honestly not sure I really need to be using Entities for what I'm doing, but all the examples make use of them. I guess there isn't much overhead anyways.
Using entities where you don't need to be will actually just make your code way worse and harder to understand
Sometimes having a thing just internally use jobs to manage it's data efficiently is great
Do you know of any examples/documentation for that?
Not really, but if you find yourself using entities and you're not sure you need it, what you're probably doing is trying to use it to manage your job dependencies for you
So I'd recommend you try making some simple systems that use jobs in an easy to understand way, so you can understand how to manage dependencies
A Unity port of https://github.com/thebracket/rltk_rs - sarkahn/rltk_unity
A fairly self contained example using jobs to manage a mesh
A big take away: Only use a single job handle. If you pass that job handle to an outside system, it should be taking a jobhandle in to depend on
Thanks, I'll look into that a bit more.
there are some resources and tutorials around, including an old "Jobs cookbook" on Github somewhere
Cool cool, thanks.
Sorry, another question. Working through converting my main Network class into a struct. Each Network has a list of Nodes and Connections, and the relationship between those is important. Each Node needs to have a list of Connections that extend from it, and each Connection needs to know what Nodes it connects to. What's the best practice for managing this? My first thought is to use two NativeHashMaps (one for Nodes and one for Connections), with Nodes and Connections storing the hash value of the corresponding Node/Connection. Does that sound about right?
Though, wait, hashes are strings...
Damnit lol
Collapsing a tree into a 1D array can be a complicated problem depending on the structure of your tree. You'll have to do some research.
My implementation was probably really naรฏve, but they were already 1D lists. I guess there's no standard way of creating a unique identifier for a struct that doesn't involve strings?
Of course there is, that's literally what hashtables do
If your nodes exist within a limited 3d space then it becomes much simpler
Oh duh, use the position ๐
What is the best way to access/use singleton in jobsystem? GetSingleton<> pass in value? EntityQuery.ToComponentDataArray pass in? ComponentDataFromEntity + GetSingletonEntity/ToEntityArray for lookup?
I do chunk iteration as a dependency and grab the first chunk's first element and store it to a pointer
and then pass the pointers to a job
for singleton based data
Hi everyone I am working on a game as my last under-graduate project and I am begining to work with ECS. Indeed, one of the rules given by my teacher is to have more than 2000 enemy in game and ECS is incredibly optimized for this. I am begining to work on my entities but I was wondering how could I give a refence to my player position to the entities in order to make them chase my player. Is it possible to give a gameObject to an entity ? Do I need to give the player's position to the ComponentSystem ? Then how can I give some data to the ComponentSystem every frame ?
Thank you for your help ๐
Do you work in hybrid mode with both GameObjects and entities or do you want to work with only entities?
For the moment I work with both as my map chunks are generated as gameObjects and the player is a gameObject also. But actually in the end we will probably migrate everything to Entities
While your player is a gameobject, you could do the simple thing and have the system keep a reference to them and grab the pos the normal way
Yeah that's what I thought but how can I give it a reference of the gameObject ? Can I access it via World.Active.Systems ?
That'd let you acces the system from elsewhere, yeah
But you could also use normal gameobject style code in the system. Pretty sure you could get a GO that way.
Ok I see
Or go cheap and just make the player (assuming there's only ever one) set itself as a public static variable - Sometimes doing things in a way that goes again best practice (in this case: More hard-coded, and.. other issues)
Nah bad idea unfortunately, there will be 2 players, 1 human and 1 AI :/
I assume the game knows which is which somehow, though?
Some other script component or whatever
or: How would you normally (in the monobehavior world) get a reference to the player?
Actualy my teacher wants the AI to be considered by the game as a second player and not as an AI. So for the game there is no way to make the difference :/
it's probably easier to transition if you go piece by piece, even if you don't do all the optimal things while in the 'moving process'. A refactoring is a big undertaking, even more so when changing paradigms. Do whatever works for you, and ends up with something you are happy with.
If that's the case, then don't ECS need references to both players?
Do you have a playerNum or similar designator for which is which player? You could simply do a dictionary (or custom simple storage) with the index/key being the playerNum, referencing to each player
Oh that's a good idea !
If you haven't seen the link, check out the DDD (Data Driven Design) book that keeps popping up. Data oriented design can be a bit to wrap your head around in the beginning.
The Unite talk on entity interaction sounds like it will be quite relevant to you as well. https://www.youtube.com/watch?v=KuGRkC6wzMY
Interaction is fundamental in games, both in how players interact with a game and receive responses, and in how parts of the game interact with one another. Unityโs Entities package provides a variety of options for writing systems where entities communicate information to ...
While ECS is a bit different, don't to too stuck up on that. As I've alluded to earlier, it is often easier to dothings the simple and familiar non-DOTS way, and then make it more 'DOTSy' later
Oh ok I see
I might waste some time on trying to do it DOTSy now instead of doing it later
It discusses the ECS equivalents of making gameobjects call other gameobjects, but should apply (with tweaks) to entities 'calling' gameobjects as well. Gameobjects -> entities can be done more or less the traditional way (albeit with a different API).
The talks explains in more depth, but entities are just data and as such don't really 'talk' to anything, the systems do.
I'd suggest you make anything new in DOTS (gameobjects are still valid for quicker prototyping, until you get into it). For things which are already gameobjects, do whatever works.
But I gotta get some shuteye, so good luck!
Hi @digital scarab, do you know if it's a known bug that give an entityquery empty ( 0 entities ) to an ECB breaks creation of new entities without exceptions ? Or do I need to report a bug ?
ok thanks ๐
hm, NativeList.AsParallelWriter() results in a NativeArray???
Hey people. I'm watching a video from Unite Copenhagen, that was posted earlier. And I kind of can't wrap my head around something they've shown there. There was no explanation given in regards to this. They create a command buffer right inside a job, which I thought was not possible at all. Why would you want to do this inside a job as opposed to before it? Here's the moment in the video where they do it:
hm, I guess if you have multiple jobs in a system, where they don't all need access to the same ECB, or any ECB, and just a few of them schedule each OnUpdate, its a little wasteful to do the Create on ECBSystem and pass into every job? With this it becomes more on-demand?
Ah no, I read your code more properly now
this is still happening on the main thread
you're just passing in the ECB as a parameter into the job
so it's not happening "in" the job
So SignalActivationEntityECBSystem is just a special ECB System. There are multiple of them.
yeah, that just the struct initializer, not the job body
So that TransmitSignalJob is not actually a job?
the one they call .Schedule() on.
I still have this maybe wrong understanding that a job always operates on a copy of data, so it's hard to understand how it accesses and calls a method in an outside class. ๐ค
It is a job. It's just a struct. It's no different than
var someStruct = new SomeStruct { intValue = 10 }
They're just setting the variable in the struct to the command buffer that they're creating.
Aah. Okay, that makes a bit more sense. So if it was in a Entities.ForEach block would that work too?
With the Foreach you assign whatever you're passing in to a local variable outside the foreach then just use that local variable inside the foreach
Different syntax but exact same result
Hmm. Okay. Still doesn't make a lot of sense in my head and the more I read the docs the more questions I have. I think I need a "dots for dummies" book or something. Feels like there's some basic knowledge/understanding that I miss in order to understand this stuff...
That page gives a very detailed and clear explanation of how to properly use the Foreaches
It's definitely one of the better pieces of documentation right now
I was exactly reading that at the moment.
How come you can't find the "GameObjectEntity" anymore in the add component list? Is there a better way of spawning entities from prefabs and adding them to ECS world?
I don't get Instantiate and ConvertToEntity.ConvertAndInjectGameObject working togeather.
new burst package is out:
## [1.2.0-preview.12] - 2020-01-10
- Fix issue with sizeof on a struct defined in another assembly and would return the size of a pointer type instead of a real struct layout.
- Fix issue with a potential InvalidOperationException related to ABI layout when compiling a function pointer on Linux/Mac.
- Fix issue with a potential NullReferenceException when building a player for UWP.
- Fix issue with a potential ArgumentException `The output byte buffer is too small` happening in the Editor when Burst is trying to compile a function that is producing a large log error.
@mystic mountain https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/ECSSamples/Assets/HelloCube also just my personal opinion, but I'm not keen on workflows involving Convert and Inject.. kinda wish they hadn't added it
its certainly got some odd looking code in it
.WithName("RotationSpeedSystem_ForEach")
i assume these strings are being magically removed on compile
@amber flicker This does not include the hybrid I was asking about. There is no example of ConvertAndInject, as for example you might want to use when spawning a camera.
how dare they not get a nameof(RotationSpeedSystem_ForEach) up in here at least
Seems my problem resides in that ConvertToEntitySystem is does not get part of Client World update lists.
Hi all, has anyone used DOTS with Forge Networking Remastered? Is there any networking solution up and running with DOTS?
DOTS NetCode
I think in theory NetCode does, but I'm kinda scared to write too much code in that direction just yet
Seems like the ConvertToClientServer entity has the same problem ._.
Ok, seems it could be solved by using ConvertToClientServerEntity +
var world = World.DefaultGameObjectInjectionWorld;
World.DefaultGameObjectInjectionWorld = World.AllWorlds[0];
var cameraObject = Object.Instantiate(m_settings.m_characterCamera);
World.DefaultGameObjectInjectionWorld = world;
Not sure how safe it is to assume index 0 is default, but works for now.
I frequently hear the term "managed data", but I still don't full understand what it is. I know Monobehaviors and most unity API is managed, but what exactly does that mean? Anyone has a good reading source for that, as I didn't manage to find anything straightforward with google.
@willow plaza they just mean data that's in C# reference types somehow
and not in natively allocated memory
i..e. C# classes, C# arrays, etc.
and natively allocated would be the c++ part?
no this is just 'what' gave you the memory
unitys native allocator
or the C# heap allocator for a reference type
so, anything that the GC collects is managed?
Is there a different term that explains it and can be read about on wiki or something?
or is it something that is not very common outside unity?
I think this would be a good start for C# - there are subsequent sections about unmanaged memory
yeah, I know about garbage collector, I just was not able to connect it with that "managed data" as they never explicitly explained what they mean.
guess I'll give it a read again though, as the last time was long ago...
managed memory is typically just memory in which c# can handle for you - e.g. if you allocate a new object - some process determines which address the new object can use and be allocated to and would be freed typically through the GC - which would keep track of the object and then determine the 'best' time to free up the memory so you can use the same address again (ofc this is hidden from you as a programmer for a more simplified context when programming)
unity's native allocators delves into the realms of unmanaged memory - as you'd typically have manage that yourself - i.e. freeing them
So I was half correct to say that managed is anything that the GC looks after?
So jobs and burst don't work with managed data, because it might get accessed or altered on a thread, while the GC is trying to clean it up?
Alright, thanks for clarifications.
new Havok physics package as well: https://bintray.com/unity/unity/com.havok.physics/0.1.2-preview
I think this is the first update to it actually after they released it around Unite CPH
The licensing and distribution model of Havok Physics for Unity is owned and managed entirely by Microsoft (Havok) and not by Unity.
Havok Physics for Unity is free to download from the Unity Package Manager. Using the features at runtime may, however, require a development license depending on your Unity subscription plan:
* Unity Personal: Free to use.
* Unity Plus: Free to use.
* Unity Pro: Havok Physics for Unity subscription is required, available from the [Unity Asset Store](https://aka.ms/hkunityassetstore).
When using this package, the Unity Editor will periodically check if you are entitled to use the runtime features. The runtime features will be locked if you are not signed into Unity, or you are a Unity Pro user without a valid subscription. Once unlocked, there is an allowance for working offline as the same user for up to one month before the subscription must be reconfirmed.
Note that the runtime features are always unlocked for standalone applications that have been built from Unity. Standalone applications do not require an Internet connection for Havok Physics for Unity to function.
that link is still broken btw
## [Havok Physics 0.1.2-preview] - 9999-12-31
### Changed
### Fixed
- Fixed the issue of uninitialized array when scheduling collision event jobs with no dynamic bodies in the scene.
- Fixed an issue where contacts were not being correctly disabled in an IContactsJob.
- The Havok Visual Debugger (VDB) is now always stepped, even when there are no dynamic bodies in the scene.
- Fixed the job handle ordering during step. This fixes errors when simulation callbacks were added.
- The VDB is now correctly initialised with the port supplied.```
someone failed to update the date it seems
I'm guessing they had to update this because the initial version will stop functioning on Jan 15th
How can I set up my systems so only certain ones run only when a certain scene is loaded?
Im making a tutorial that's using ecs and I want to be able to have each part be self-contained from the others in the same project using scenes
Since it's not really practical to have a separate unity project for every step
Thoughts are either manually updating systems or adding a required scene tag but I'm sure you've already thought of both of those and I can see why both would interfere with what you're trying to tutorialise. Or else editor script enabling/disabling or adding/removing systems based on scene might work?
I was hoping there was some built in way I was missing. I haven't messed with manually creating and updating systems yet so I guess I have some tinkering to do
I guess if you put the systems in different Groups you could maybe just set enabled on the group but I don't think there's anything built-in with systems per scene. Might be some trick I'm not thinking of though.
Using custom system groups is a good idea, thanks. Kind of annoying to have to explain those extra setup steps to the reader, ah well
Yea - dots onboarding feels quite tricky - almost feel cpu's, cache, memory layout, chunks, archetypes, foreach lambdas and more need to be vaguely understood before even the most simple example means something. Not to mention subscenes, conversion workflow, live-edit etc for the simplest [GenerateAuthoringComponent]. Good luck!
Do DOTS support transformation ? like rotation ? up, right and front vector ? i have trouble finding them
Yes, and they should be used in some of the samples. LocalToWorld should be one for position, I think, but I don't think that's necessarily the one you want to use. Rotation and Position, perhaps?
oh ok, because i'm try to rebluid everything from scrach so i don't think it's the right way
What are you trying to achieve?
@zenith wyvern Put a public static bool Active = false; field in the system(s)?
Then make a monobehavior script, in whose Start() method toggles said field. Could make it set the field in ALL systems, or have multiple such scripts.
Make sure to reset it in the OnDestroy()
Uh, System groups feel like a much cleaner solution (you can either set Enabled=false on them or use RequireSingletonForUpdate<Scene3Tag>() in their OnCreate)
If I have [DisableAutoCreation] on a system then just setting active = enabled won't do anything right? And I don't want to have every system running at all times
If you [DisableAutoCreation] then the system won't exist at all, so you have nothing to set enabled on. Manually creating systems and inserting them into group update lists seems more complex than just declaring them in the appropriate group, especially for an onboarding project
Having a separate group for each tutorial seems like a reasonable idea, but unless I explicitly disable each group somewhere then they are all just running by default right?
I mean ultimately maybe it doesn't matter if everything is just running even though it would have nothing to query in most scenes, it just feels a little off
The simplest solution I can think of is to have [GenerateAuthoringComponent] struct Example3Tag : IComponentData, have an Example3Group you put all the relevant systems in and have the Example3Tag on a gameobject in the Example3 scene.
if you do RequireSingletonForUpdate<Example3Tag>() in Example3Group.OnCreate() the whole group won't update outside of that scene
Yeah I didn't know about the RequireForUpdate attributes either, that feels like it might be the "simplest" way to go while still making it clear what's happening
RequireSingletonForUpdate<TComponentData>() Sounds like a better solution than what I suggesed, yeah
I meant just calling the RequireSingletonForUpdate method every System/SystemGroup has (didn't know there was an attribute for that)
I was going for a "simplest that you can easily explain, if need be" kinda solution, and a gameobject with a script where the user can toggle things (design time) seemed like the best way for newbies
(without considering best practice or anything like that)
@tawdry tree That would work but is definitely contrary to how unity wants you to structure things. But then so is tying systems to scenes, hahah
Yeah, your use case is a bit special, so I figured it wouldn't matter... that much
Maybe for a later tutorial you'd show a more best practice way of controlling which systems run ๐
But then so is tying systems to scenes
I'm not sure if this can be avoided to be honest, especially for gameplay stuff where you sometimes want special rules per level
I think the idea is that it's just done implicitly based on what exists in a scene. In my case I just want to avoid having the user look in the entity debugger and see 50 systems there that have nothing to do with what's going on
In a real game that wouldn't matter
Like, I have a KrakenEncounter component I just spawn in the scene that triggers a couple special-rule systems to run
That sounds pretty close to best practice, and works on the DOTS side, either by spawning or via design (gameobject authoring)
btw, if you do RequireForUpdate in a group, and that query is never hit, the Entity Debugger shows only that group, grayed out
EffectSystemGroup has like 20 systems in it:
I'm trying to create an extension method for NativeList but it's throwing an error saying the type T could not be found. Is this not possible, or am I doing something incorrectly?
{
var subset = new NativeList<T>();
for(int i = 0; i < indexList.Length; i++)
{
subset.Add(list[indexList[i]]);
}
return subset;
}```
Post the exact error message
The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?) [Assembly-CSharp]
public static NativeList<T> SubsetGetByIndexes<T>(this NativeList<T> list, NativeList<int> indexList)
{
var subset = new NativeList<T>();
for(int i = 0; i < indexList.Length; i++)
{
subset.Add(list[indexList[i]]);
}
return subset;
}
(notice the <T> after method name)
SubsetGetByIndexes<T>
Ah right, thanks! Though it's throwing another error: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'NativeList<T>'
T has to be struct
It's telling you exactly what you need to know. You should google it
(really it's a "read on how to use generics" kind of problem ๐ )
Hello, advise how to properly make a large tiled world and its rendering by the player. I use Tilemap, does it make sense to generate new Telemaps when a player moves around the world? Or... - sketch https://hatebin.com/ggbperezid
You forgot the >T> part between method name and argument start parenthesis
SubsetGetByIndexes(this NativeList<T> list, NativeList<int> indexList)
to
SubsetGetByIndexes<T>(this NativeList<T> list, NativeList<int> indexList)
Ahhh I understand, thanks all ๐
@torpid minnow I think you should ask in the #๐ปโcode-beginner or #๐ปโunity-talk - this is a DOTS related channel
I misunderstood the topic of the channel, sorry
Anyone knows how to do a look at with an entity that has physics? Can't figure this one out yet
Are you trying to do a LookAt with a vector or a quaternion?
Might be easier to do the math yourself with a vector and rotate the quaternion using the vector.
var dir = Vector3.forward;
var rotation = Quaternion.LookRotation(dir, Vector3.up);```
If you want the direction between two points you just subtract them.
var dir = to - from; // Normalize?```
@soft nova
On another note:
I'm trying to use Graphics.DrawMeshInstanced() to draw a bunch of entities. Is it possible to use a MaterialPropertyBlock to change the tiling and offset of the main texture of a material using the standard shader?
I tried using this code:
private readonly MaterialPropertyBlock _props = new MaterialPropertyBlock();
protected override void Update()
{
// ... Code
_props.Clear();
_props.SetVector("_MainTex_ST", new Vector4(0.0625, 0.625, 0.625, 0.9375));
Graphics.DrawMeshInstanced(mesh, 0, material, _matrixData, translations.Length, _props, renderComponent.CastShadows, renderComponent.ReceiveShadows);
// ... Code
}
But it does nothing.
It just draws the entire texture and ignores my settings.
I also tried using _props.SetVectorArray() but that had no effect.
I started looking into making my own shader but I'm wondering if I even need to.
Are you trying to make a sprite animation system?