#archived-dots
1 messages · Page 85 of 1
the collision is already made up into a "collidingWith" buffer and a "colliding" component that works as a tag
the reason for why I'm using buffers is that I can collide with multiple objects as well as multiple entities can transfer various amounts of units to a single entity
If those collisions happen frequently, then the adding and removal of tags, and thus changing archetypes, might have a notable performance impact
I believe the 'proper' way to do communication like this would be to, instead, create a HealthTransfer entity on collision (remember, an entity is just data, it doesn't need to be an actual in-game thing).
So on collision, calculate how much each unit transfers to each other unit, then later you run a system which takes all these transfers and apply the effects to the correct entities. Dunno if that will have better perf, or is even reasonable to do (code efficiency and maintenance wise), but eh
yeah I was thinking on creating a new entity per transfer as well, but then I would have to apply that back to the original entity, making this even more complex imo
Potentially, yeah?
But the flow would be:
-Check for which effects(transfers) to create
-->(and create entities for them)
-Use transfer entities to apply changes (deleting the entities)
As for how to get the entities you want to change from the references you ought to store in the transfer entities, I haven't done that kinda stuff and don't know how easy/hard/simple/complex it is, but i know it's possible.
hm, so how great is getting other entities from jobs? because the way I see it, ecs jobs are only optimized to work on a single entity, not multiple ones at the same time.
if I do the transfer I feel like i have to get references to the other entity twice
The first time could potentially be lightning fast, it's the second time, grabbing by the entity ID that is questionable. Again, no experience with doing that kinda stuff, so can't really say. I'd probably go for whichever leaves the best code, in terms of readability and maintainability(debug/extend later), unless I'd profiled and found it to be a performance hog
Eep, it's suddenly september (meaning, too late), so unfortunately I can't answer any more questions you might have, but good luck!
haha, thanks for your time though!
No problem, I would want people to answer my silly questions when I butt my head into some wall and can't see the path around it (been there, done that...), so it's only fair
Yea, entity per collision sounds reasonable - I’d start with a simple job that uses a CDFE to add/subtract and then if it turns out not fast enough and you have many ‘leaches’ per entity, it might be worth having a job that sums the effects before writing results via a hashmap method or something #rambles
what's a CDFE? ComponentDataFunctionalEntity?
ComponentDataFromEntity - allows you to access any component by entity
i am already using them, or trying to
I'm getting this error though: "... is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type."
i do have to write to those tho
Cool... if you design it so you’re sure you never write to the same entity, you can disable that safety check but in your case you possibly write to the same entity multiple times?
not sure actually
if you do, perhaps two jobs - one that sums the damage/health and a second to apply them
sorry, also got to disappear - a very common pattern is to fill a hashmap or multihashmap with job1 and then process that with job2
hm, well thanks for all the hints. it's also way past midnight for me so i'd have to go soon anyways. cheers!
good luck 🙂
hello, does anyone know how to declare a new array inside a job's Execute method without allocating garbage? I tried float[], but it seems that declaring reference types like that causes an enormous amount of lag.
@safe lintel i finally figured out a way to approach parent child kinematic physics objects 😄
@thorny halo NativeArray might do it
@lament orbit ty
Anyone here has experience implementing the BoidSystem from the ECS samples into their own project?
Have some quick questions
I need to store static list of lists and i need to access it in a job, but job can't be bursted because of using managed collection. What can i use to avoid it?
Hi all,
Need some help conceptually again.
I want to run a series of jobs, passing data between them, but for each of an entityquery. It seems like I need to do a foreach of the entity query in OnUpdate (ie on the main thread?) and kick off the series of inter-related jobs, like the way the boids examples does for each set of boids with the same SharedComponentData, but this time just for each individual entity - which doesn't seem like the canonical ECS way.
@surreal rune Sebastion League made a really good video about Boyds a week ago, check it out if you haven't yet. https://www.youtube.com/watch?v=bqtqltqcQhw
Trying to create some flocking behaviour, and getting a little distracted by spirals along the way... Links and Resources: Project source: https://github.com...
@frosty siren you might try breaking out the relevant data for the job from the lists in the OnUpdate by passing that data as burst friendly variables to the job scheduler.
@lament orbit yeah but it really big extra work. I know what list of lists i need only inside of a job. Also the list of lists stores inside class which not only one.
I use it for RO, so maybe i can use something like UnsafeList ?
@frosty siren I had a similarish case - I now calculate my publicly-available NativeMultiHashMap and NativeArray data in a system, then other systems access those data as readonly in their jobs. Can burst that way.
@thorny halo Thanks a lot! Think thats exactly what i'm looking for
But that's not ECS specific right?
It's just the main logic of how the boyds work.
Hmm yeah I understand. I didn't really ask my question clearly i think. I was advised to take the Mapping of Entities to locations from the Boids project
So I just want to use their implementation for the Quadtree like grouping of entities
if that makes sense
I found that example incredibly difficult to understand, but worthwhile spending the time trying to. I watched the video by Mike Acton and had the source code up from the Unity Samples github, and made notes - I must have watched that section of his video like 5 or 6 times, pausing, writing everything down and making sure I understood in my head exactly what was going on with the data. It's really worth doing it
Yeah it's very difficult
And his explanation too
Feel like there's a ton of info/knowledge I needed leading up to it, even though i feel like i have a lot of unity experience
Like a lot of terms that he dismisses as common knowledge that i've never heard of
Do you think there's a simpler alternative if i want to implement it quickly or should i just power through?
I feel the pain! I'm still very new to ECS myself and currently trying to put together a project almost entirely in ECS. whoever said ECS isn't hard it's just different was, unfortunately, lying. It is hard - but mostly because there aren't any intermediate examples.
but it does get easier, like everything, with practice and repetition. I will probably go back over bits of that video again myself soon, with my notes to hand!
Yeah for sure
Hello, has anyone used "IJobParallelForTransform" jobs before for thousands of transforms? I'm having trouble with performance after partitioning my TransformAccessArray into multiple chunks and scheduling multiple jobs for each chunk instead of just a single one. There's spikes of 15-25ms every 5-10th FixedUpdate which come from job scheduling, however, i can't pin down why the spikes would occur as I'm sending the same amount of data with the same Transforms each FixedUpdate. If i don't partition my TransformAccessArray, the spikes do not occur, however, i then need to send all of my transforms into a single job, out of which i might need only 10% to actually be updated, it ends up wasting a lot of performance. Is it normal for these spikes to occur if I'm scheduling 100 jobs instead of one?
Can I pm you @wary anchor ?
sure, but bear in mind I'm really quite a newbie at this myself!!
Earlier this year we made several additions to our high-performance multithreaded Data-Oriented Technology Stack (DOTS).
Join us September 23-26 for #UniteCopenhagen to learn more and see what’s next!
145
Looking at Unite schedule, Sept 24 has:
- Creating games with a tiny binary footprint: Project Tiny Overview & Roadmap
- Get moving: an overview of physics in DOTS
- GameObject to Entity conversion
- Wreaking Havok: an overview of Havok Physics in Unity
- Unboxing DOTS: designing workflows for humans
- Introduction to Unity.Mathematics
- Unity Entity Component System for mobile: Metropolis Traffic Simulation
- Using Entity Command Buffers
Sept 25 has:
- What to expect in 2020: Unity roadmap (and they still talk about Unity's 3-year vision here)
- Creating a third-person zombie shooter with DOTS
- Converting your game to DOTS
- Building a Turn-Based Game Protoype using ECS
- Introducing Data Flow Graph, the graph data processing system for DOTS
and Sept 26 has:
- Options for Entity interaction
- Introducing the DSPGraph, the new audio rendering/mixing engine
- Intrinsics: Low-level engine development with Burst
I want to have a box to check collision with, kind of like a bounds or AABB but it needs to be rotated
Maybe i'm stupid but I can't figure out if there's such a type or if I'm just using the AABB incorrectly
I'm looking for an OBB implementation but I don't think Unity has it right?
Forgive my paint skills:
Basically i want to create box 2 for checking interesctions
I know the Quaternion for rotating it
Just need to know what kind of Type i can use for this
AABB is axis aligned and my google searches don't result in much
Creating a third-person zombie shooter with DOTS - please let that mean dots animation
also summer is running out for havok physics, wonder what the hold up is
probably waiting for Unite Copenhagen + Unity Tokyo
best to just drop all the accumulated updates and examples in one fell swoop
let it rain dots packages galore 😃
@surreal rune OBB with SAT https://github.com/jeffvella/UnityAStarNavigation/blob/45a8221e6f04608728680e76dff581fac80162c6/Assets/Plugins/Collisions/SimpleBurstCollision/IntersectionUtility.cs#L281
or use ECS physics package
@safe lintel ```Creating a third-person zombie shooter with DOTS
Far North Entertainment is working on a third-person zombie shooter using the Data-Oriented Technology Stack (DOTS), which has brought both great performance improvements and faster iteration time. This intermediate-level session will explain why DOTS is able to process data much faster, how the team increased iteration speed using the Entity Component System (ECS), and its experience learning and working with Unity's ECS package.```
so not an animation talk 😄
also
This session will provide an overview of the Havok Physics integration and workflows in Unity. Attendees will gain insight into how we've integrated the industry-leading Havok Physics system into Unity using our Data-Oriented Technology Stack (DOTS). This session will cover the shared data layout of our physics engines, the performance and fidelity benefits of Havok Physics, and future development plans, as well as showcasing several examples from the Unity community that leverage these systems.```
https://www.havok.com/products/havok-physics/ still says this:
so... if past has taught us anything, they are postponing the release to be aligned with Unite
I feel that stacking upcoming feats like they do for these events is just silly
it used to serve a purpose when they were actually releasing major new engine versions, like Unity 4, Unity 5 etc
but now when we got software as a service model, it would make sense to just give people the things as soon as they are actually ready for distribution
might be to also give buffer
when they announced megacity and the fps sample it sounded like they barely just finished those on time
then it took awhile after to finish up for proper release
ah, for those projects, sure
but I mean like actual packages and systems now
I guess they could just set the milestones there
but they stack these suspiciously large amounts for these events
and if it's some crunch for the events, that's not good either
and I do feel Unity has lots of crunching all the time
they definitely have had such for late engine releases and I can feel the crunch stress here already few months before next big events are up
Yeah I'm not a fan of them waiting for big events either
But they are doing some good shit, so I hope they keep at it
hi all. I'm at a decision point and need a sounding board...
I've written a movement system for my 3D protein planets project, but the collision and gravity systems are not working quite how I'd like yet. The gravity is furthest along and I can probably get that sorted fairly soon, but collision detection and correction is a bit more tricky.
I could return to try to use the ECS Physics package now I'm a bit more au fait with ECS. It might pose some problems for gravity (gravity's per object and local) but I could probably overcome those.
I'm just not sure if it's worthwhile pursuing my in-theory lighter weight solution or get to grips with the more out of the box complete system
imo that depends on how complex your collision system could be - can you get away with pretty much just sphere colliders?
Yes, it's in fact only sphere colliders!
But for some reason my first attempt at it isn't working right and I'm in the middle of troubleshooting
it is sort of working so I'm not a million miles off
even if ecs physics was stable and easy to use, I might expect a custom solution to be better suited and faster in your case... given I don't think you can say that about ecs physics at this point (although tbf I haven't played around with it yet), I'd say it's a no-brainer - likely to spend longer trying to get ecs physics working than fixing whatever issues you have I would guess
Hmm yeah that seemed to be my impression when I first played with it, but I was even newer to ECS then so had even less of a clue what was going on! 🙂
Thanks @amber flicker I'll push on with my own and try to get this nailed!
Caveats - just my opinion and I wouldn't normally advise doing all your own physics but if you have local gravity and simple spherical collisions, I think it's the better route. Good luck 🙂
For version 2 it'll be raymarching. We live for tomorrow's tech today, right
new Burst preview I see
## [Burst 1.1.3-preview.3] - 2019-09-02
- Query android API target level from player settings when building android standalone players.
- Add calli opcode support to support bindings to native code.
## [Burst 1.1.3-preview.2] - 2019-08-29
- Fix to allow calling [BurstDiscard] functions from static constructors.
- Correctly error if a DLLImport function uses a struct passed by value, but allow handle structs (structs with a single pointer/integer in them) as these require no ABI pain.
- Upgraded burst to use LLVM Version 8 by default, bringing the latest optimisation improvements from the LLVM project.
- Added support for multiple LLVM versions, this does increase the package size, however it allows us to retain compatability with platforms that still require older versions of LLVM.
- Fix bug in assembly caching, subsequent runs should now correctly use cached jit code as appropriate.
- Add support for Lumin platform
## [Burst 1.1.3-preview.1] - 2019-08-26
- Add support for use of the MethodImpl(MethodImplOptions.NoOptimization) on functions.
- Fix an issue whereby static readonly vector variables could not be constructed unless using the constructor whose number of elements matched the width of the vector.
- Fix an issue whereby static readonly vector variables could not be struct initialized.
- Improve codegen for structs with explicit layout and overlapping fields.
- Fix a bug causing SSE4 instructions to be run on unsupported processors.
- Fix an issue where storing a pointer would fail as our type normalizer would cast the pointer to an i8.
- Begin to add Burst-specific aliasing information by instructing LLVM on our stack-allocation and global variables rules.```
they upgraded the LLVM
nice @ explicit/unions improvements
im hoping one day my xmas presents will all come at once and ECB processes commands in burst
uhm, this is madness... I just bypassed all my spatial partitioning code to try to get to grips with a rotation bug I'm seeing, and I see exactly the same frame rate and system calculation times for cycling over 33k positions and calculating the average vector based on (pos - targetPos)/sqDist for all of them
so your spatial partitioning code is super fast ? 😄
Or super irrelevant 😄
Having a weird bug and I think I may see what's causing it but I'm not sure. When I move left/right, the up axis seems to update every frame as expected. When I move forwards, I don't get the same local rotation of the player. I think it's because I'm referencing the LocalToWorld in several places during my calculation but setting the Rotation.Value manually but I'm not 100% sure. Does anyone have any simple code showing how to set LocalToWorld directly? The docs are kinda dry on this and while I understand quaternions reasonably, I'm not good with matrices yet
I don't unfortunately - only setting translations/rotations and letting the default systems do the rest. Are you wanting to set the LTW before the TransformGroup does its things with it in order to get the result updated sooner or something?
whoa I've screwed something up, sorry hang on eek
whoa okay found it that was a bit hairy for a moment.
Sorry, so I'm modifying the gravitational axis per frame based on nearby objects, but it seems to be screwing with the movement in different directions. I am now pretty sure I'm not ensuring my vertical velocity is actually perpendicular to my horizontal movement, so they're interfering with each other. I can't get over how fast ECS is though.
yeah its pretty good 🙂
when u see benchmarks 50x faster than standard c# code doing the same thing its like woah.
Hmm now it appears if I change how I calculate my up axis (which gets normalized afterward!), it changes the mouse rotation and the graviational pull. THat's weird, I have really screwed something up here! Time to get a coffee and get stuck in
i have something that might help you, i updated my debug drawing script to run in jobs and discard in burst
Oooo this looks shiny, thanks let's have a butcher's
never heard that expression before, are you english? sounds english
haha, classic
actually, i only updated some of the methods. i know drawline works, but anything with Debug.x in it like DrawWireCube and Cone etc woudl need to have that moved into a new IDebugDrawing type, so that it gets passed into the queue for main thread.
I tried DrawArrow and it said it only runs in the main thread
All my movement code is currently in 1 job struct because I was having no end of trouble with jerkiness and it was getting overly complicated before. I'm very close to a working solution here!
hold on then i can fix it for u quick
var tempRotation = quaternion.LookRotation(localToWorld.Forward, upAxisThisFrame); This is the problem. If the up axis rotates such that up/down is no longer orthogonal to forward, I don't get the rotation I want. Hmm I need to think on this. It's a shame not all of the Quaternion methods are available in quaternion, actually have to think a bit!
you could always do it with Quaternion and then convert it to quaternion 😄
not inside a job, I can't!
surely?
I think I need the quaternion equivalent of Quaternion.FromToRotation()
No need to on my account, @mint iron! But of course I'll gladly use it if you have it!
yes, I have narrowed down my problem.
What is the Burst/Job compatible version of Quaternion.FromToRotation(axisFrom, axisTo)?
so i'm not really that strong with this stuff, but maybe its just a multiplication to * from (with quaternions) ?
I solved it. This is pre-refactoring:
var tempRotation = rotation.Value;
float3 oldUp = math.normalizesafe(localToWorld.Up);
float3 newUp = math.normalizesafe(upAxisThisFrame);
float3 cross = math.cross(oldUp, newUp);
float dot = 1 + math.dot(oldUp, newUp);
var fromToQuat = math.normalize(new quaternion(cross.x, cross.y, cross.z, dot));
tempRotation = math.mul(fromToQuat, tempRotation);
rotation.Value = math.mul(math.normalize(quaternion.AxisAngle(upAxisThisFrame, inputComponent.RotationHorizontal * 0.0174532925f)), tempRotation);
Ugly, but works 🙂
0.0174532925f this hurts
then don't look inside Unity.Mathematics.math 😉
If i want to use a NativeArray in a job but don't know yet what size it is going to be, what can i do?
NativeList can't be used in a job right?
Oh only not in parallel jobs hmm
I want to remove entities in an IJobForeachWithEntites, but if i do that I can't use burstcompile because it's not compatible with the commandbuffer right?
Are there any alternatives?
Like somehow marking it for removal or adding a component so it gets deleted later
@surreal rune you can convert a list to a nativearray as well
I am having trouble getting my player to render, I read that you need to have LocalToWorld matrix, but my player isn't rendering. I'm using a cube to render the player and a default material:
var playerMesh = new RenderMesh() {
mesh = playerMeshFilter.sharedMesh,
material = playerMaterial.Result,
subMesh = 0,
castShadows = ShadowCastingMode.On,
receiveShadows = true
};
EntityArchetype playerArchtype = manager.CreateArchetype(
typeof(PlayerInputData),
typeof(MoveableData),
typeof(PlayerMovementData),
typeof(Translation),
typeof(LocalToWorld),
typeof(WorldRenderBounds),
typeof(RenderMesh));
var playerEntity = manager.CreateEntity(playerArchtype);
manager.SetComponentData(playerEntity, new Translation { Value = Vector3.zero });
manager.SetComponentData(playerEntity, new PlayerMovementData { Speed = 0f });
manager.SetSharedComponentData(playerEntity, playerMesh);
Rendermesh should look like this
EntityManager.SetSharedComponentData(Currentrobot, new RenderMesh { mesh = RobotCustomerMesh_1, material = RobotCustomerMaterial_1 });```
I am setting the RenderMesh, I updated the first comment. See above. I also checked, and made sure they are not null
ok then I have no idea, the code is fine, its the way your getting the mesh and material perhaps
@pliant pike Thanks
I just tried GameObject.Instaniate and assigned the material. And that worked. ┬─┬ ノ( ゜-゜ノ)
Is there an accepted standard way to represent child entities in terms of gathering all nested children and using them to produce a result. Much like the hierarchy, one element can point to many which in turn can point to many. I have a working system but it's very top level (child elements always belong to a single root so the root just stores a list of them).
Isn't that just recursion?
Given the name of the method here, I don't really know how I could achieve what I want to do.
I want to find all entities in my world that can be associated with one type of component.
public static NativeArray<Entity> GetAllEntitiesWithComponent(Type T)
{
NativeArray<Entity> entities = m_EntityManager.GetAllEntities(Allocator.Temp);
// What now?
}```
Is that even possible?
Because the entity manager only has "GetAllEntities"
But no way to get all entities with types
And using LINQ would likely not be the way to go
Lol
An entity query will return you the entities that have the component you want.
Recursion isn't a thing in ECS. It's all about getting flat.
So you need a linear representation. I probably need to dig deep into their hierarchical transform code for an answer.
Okay, and thanks
No problem. Just remember that your best performance will be running through the component data in a job rather that just retrieving them all on the main thread.
I'm trying to use jobs yea
I'm making a very simplistic and naive "life" simulator with varied creatures
Something I'm trying to figure out right now is "collision" in the sense that, if a piece of food has a distance of less than any given creature plus its scale
Then it is consumed by that creature
And so what I was thinking was
"What if I make a job for each piece of food? to test that?"
Does that sound insane?
not really no, but why not do it differently
I'm all for ideas
I'm just trying out ECS to get it
I've so far not made any GameObjects and that's ultimately the goal
its kind of a pain in the ass to multi thread it because you basically need locks when you consume food
well, that would be the easiest for making sure you dont eat the same food twice
you are just doing a distance check after all
hm
Yea
you could do three passes actually
on the creature put a position and a, for the lack of a better term, mouth component
and the mouth stores a entity ref of closest, and distance
Right now they are just circles moving about. No sense of "front".
then first pass, populate all the mouths with closest bit of food and the distance to it
[UpdateAfter(typeof(CreatureConsumptionSystem))]
public class MoveTowardsFoodSystem : ComponentSystem
{
private EntityManager m_EntityManager;
private float deltaTime;
protected override void OnCreate()
{
base.OnCreateManager();
m_EntityManager = World.Active.EntityManager;
}
protected override void OnUpdate()
{
deltaTime = Time.deltaTime;
Entities.ForEach((ref CreatureComp creature, ref Translation transComp) =>
{
if (creature.IsIdle == false && creature.FoodTarget != null)
{
float3 pos = m_EntityManager.GetComponentData<Translation>(creature.FoodTarget).Value;
transComp.Value = ((pos - transComp.Value) * creature.Speed * deltaTime);
}
});
}
}```
This is what I've set up.
then do another pass to remove duplicates, then a final pass to actually consume the ones in range
Then the idea for each creature to find food was to run a job for each creature to simply look for a piece of food.
the second pass is the only tricky one
yeah no, you cant think like that
you have to think in passes over data
not actions or logic
you achieve logic though data transformations
I want this thing to move closer:
pass over all things and take the direction vector and add a delta towards it to the position on the thing
thats the logic vrs the data transformation
yeah I'm not saying thats wrong
thats just a example of logic vrs the actual data transformation you need to think of
so when you say, I want all my creatures to eat the closest thing
But then, wouldn't it make sense to just use jobs for finding the nearest thing..?
you now need to think of how to achieve that with data passes. thats why 'a job for each to find food' isn't correct, thats the desired logic you want
They will be competing for food regardless.
you will be doing that in the first pass actually
first pass, distance check all food or spatial structure to find it faster instead of checking each, storing the closest food and distance onto the creature
For every piece of food in the world, check distance to that object.
Store the shortest distance Entity in the creature and keep moving towards it.
second pass, make it so you wont try to eat the same food twice, this is the tricky one
third pass, actually do the consumption on each creature, though the first pass entity reference, if its close enough
second pass basically, you keep a thread safe native hashmap and try to add to it, that you are going to eat this thing (the hash map has a lock internally so it will be safe but thrashy to do this)
if you succeed in adding to the hashmap, you are the first one to try and eat this thing
if not, you cant eat this because another thing is going to eat it
optionally you can distance check (which could be your value in the hashmap) and overwrite the other creature as you are closer
in the final pass you can then take the final collection of keys in the hashmap in a job and pass over them, doing the consumption there, so that any overwrites are ignored and only the final, closest stored one is the one who eats
something like that should be close
hahah yeah
It's not enjoyable to use
soon as you get conditionals, and want to do them multi threaded it gets nasty
And I dread that this is the future.
I know ECS has existed long before Unity but geez..
multi threaded shit is hard even with a framework
this isn't really ECS, more of jobs and safety system
I mean..
its the same reason rust is annoying
just think how easy this would be in a regular component system
just do the consume, delete the target if its empty, go to the next creature
because theres only one thread ever accessing all foods and creatures
but if you multi thread, you can have race conditions and try to delete the same food at the same time
or eat a food value into the negatives
on the main thread thats super easy, but multi threading you have to rework things so that you can't do that by design
Half my pain with ecs it's just figuring out the right way to do things. Like... currently there's not a nice way to dispose NativeMultiHashMap so still having to do it in silly ways. And moving from 2018 ECS to 2019 ECS where they settled on some naming.
actually someone pointed out they have a special version of dispose now you can chain
produces a jobhandle
so just use that as the final job handle in the chain when you schedule
Where and how? Have some infos?
Is it possible to get a component via the EntityManager in a job?
I tried to do that myself and it yelled at me that I can't dispose in a job
Yes. GetComponentDataFromEntity<>. Pass that to your job and you can query it for what you want.
So I have to pass a manager to the job?
It's not a manager it's more a pointer to where it can find those entities.
no, thats only for a special type of job thing
yeah
you want to get a ComponentDataFromEntity<T> that you store as a public field
I have an array of entities that contains all my creatures.
The job then gets that array so it can look for the creature closest to itself.
@low tangle do you happen to know where that special dispose is?
But I can't call GetComponentDataFromEntity in the job because, well, there is nothing to call it on
No call that in OnUpdate and pass it in. It's function that's part of the job system.
I have 1 entity.
It represents a Creature.
The Creature has Translation on it. I need that.
But I also need the Scale which is on the same creature.
public struct ConsumptionJob : IJobForEach<FoodComp, Translation>
{
public NativeArray<Entity> CreatureArray;
public EntityManager m_EntityManager;
public void Execute(ref FoodComp c0, ref Translation c1)
{
Scale creatureScale;
Translation creatureTrans;
float shortestDistance = float.PositiveInfinity;
float distance;
Entity winningCreature;
for (int index = 0; index < CreatureArray.Length; index++)
{
distance = math.distance(c1.Value, (creatureTrans.Value + creatureScale.Value));
if (shortestDistance > distance)
{
winningCreature = CreatureArray[index];
shortestDistance = distance;
}
}
CreatureArray.Dispose();
}
}```
This is what I'm attempting to do
I'm not done yet, but that is the general gist...
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
EntityQuery query = GetEntityQuery(typeof(CreatureComp), typeof(Translation));
ConsumptionJob job = new ConsumptionJob
{
CreatureArray = query.ToEntityArray(Allocator.Temp)
};
JobHandle handle = job.Schedule(this, inputDeps);
return handle;
}```
I need to change that query to just CreatureComp
@honest dirge yeah one sec
That's hilarious. It's literally what I was doing but it's removing the safety checks around it so it doesn't spit out errors. Thanks!
no problem :)
var sscale = GetComponentDataFromEntity<Scale>(true);```
I don't understand what this does
I don't know what entity it's getting this information from
Inside of an OnUpdate()
In a JobComponentSystem
thats a way to get a accessor to other entities
with that component on them
var scale = sscale[aentitythatyouknowhasone];
I have this:
EntityQuery query = GetEntityQuery(typeof(CreatureComp));
NativeArray<Entity> entities = query.ToEntityArray(Allocator.TempJob);```
So I thought I could do something like, make 3 arrays with the components I wanted, attached to that entity...
oh no, if you want a array attached to a entity, thats a DynamicBuffer
EntityQuery query = GetEntityQuery(typeof(CreatureComp));
NativeArray<Entity> entities = query.ToEntityArray(Allocator.TempJob);
NativeList<Scale> creatureScales = new NativeList<Scale>();
NativeList<Translation> creatureTranslations = new NativeList<Translation>();
NativeList<CreatureComp> creatures = new NativeList<CreatureComp>();
Scale scale;
Translation translation;
CreatureComp creature;
for (int index = 0; index < entities.Length; index++)
{
var sscale = GetComponentDataFromEntity<Scale>(true);
}```
I wanted to do something like this...
That GetComponentDataFromEntity method is not clear in what it does
it gives you a tool
to get other componetdatas by indexing using a entity
its not a thing, or a method
its like a magic array you can pull any of the component out of, using a entity
oof...magic in programming.. <.<
its actually just a chunk + size offset calculator like a 1d to 3d array stride
okay
I am not a fan of magic in programming
Makes me nervous
xD
New question
[DeallocateOnJobCompletion]
public NativeArray<Entity> EntityArray { get; internal set; }```
Why is this not valid?
It says that it has to be used on type "field"
Isn't that exactly what that is..?
@tardy locust A member with a get and set accessor is a property.
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/members
Yeah it's too late for this. I forgot the distinction.
👌
thanks though
all good!
So
Can I use the Addressable System to just load in a Scriptable object?
Because it looks like it's more for like
World objects
So uh, forgive me for walking in blind and not knowing if there's a FAQ or not but, what is the Entity - complete - system?
Neat.
IndexOutOfRangeException: Index 50 is out of restricted IJobParallelFor range [0...49] in ReadWriteBuffer. ReadWriteBuffers are restricted to only read & write the element at the job index. You can use double buffering strategies to avoid race conditions due to reading & writing in parallel to the same elements from a job.
hm
These are the so-called race conditions I suppose
But the actual error message of "out of range" doesn't really make much sense to me
50 is the 51st element in a 0th based array
I get that
The issue is I don't understand the "range" thing it talks about
It shouldn't be raised...
Back to the drawing board I guess
Looks like a new thread is trying to process something outside the bounds of the array, maybe something in the schedule function was wrong?
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
EntityQuery query = GetEntityQuery(typeof(CreatureComp));
NativeArray<Entity> entities = query.ToEntityArray(Allocator.TempJob);
NativeArray<Scale> creatureScales = new NativeArray<Scale>(entities.Length, Allocator.TempJob);
NativeArray<Translation> creatureTranslations = new NativeArray<Translation>(entities.Length, Allocator.TempJob);
NativeArray<CreatureComp> creatures = new NativeArray<CreatureComp>(entities.Length, Allocator.TempJob);
var scales = GetComponentDataFromEntity<Scale>(true);
var translations = GetComponentDataFromEntity<Translation>(true);
var creatureComps = GetComponentDataFromEntity<CreatureComp>(false);
for (int index = 0; index < entities.Length; index++)
{
Entity entity = entities[index];
creatureScales[index] = scales[entity];
creatureTranslations[index] = translations[entity];
creatures[index] = creatureComps[entity];
}
ConsumptionJob job = new ConsumptionJob
{
EntityArray = entities,
Scales = creatureScales,
Translations = creatureTranslations,
Creatures = creatures
};
JobHandle handle = job.Schedule(this, inputDeps);
return handle;
}```
I should preface this by saying that I don't really know what I'm doing here
I just have an idea of what the end result should be
As I understand it
public struct ConsumptionJob : IJobForEach<FoodComp, Translation>```
This grabs every entity with those components on it
Correct?
yea
right.
So
I want to get every entity that has the FoodComp on it (I need to remove the Translation thing)
And for every one of those food items
I want to check the distance between itself and all possible creatures that can eat it
Now the job looks as follows:
public struct ConsumptionJob : IJobForEach<FoodComp, Translation>
{
[DeallocateOnJobCompletion]
public NativeArray<Entity> EntityArray;
[DeallocateOnJobCompletion]
public NativeArray<Scale> Scales;
[DeallocateOnJobCompletion]
public NativeArray<Translation> Translations;
[DeallocateOnJobCompletion]
public NativeArray<CreatureComp> Creatures;
public void Execute(ref FoodComp foodComp, ref Translation foodTrans)
{
float distance;
int winningCreature = 0;
for (int index = 0; index < EntityArray.Length; index++)
{
try
{
Entity entity = EntityArray[index];
distance = math.distance(foodTrans.Value, (Translations[index].Value + Scales[index].Value));
if (distance <= 0)
{
winningCreature = index;
foodComp.IsEaten = true;
break;
}
} catch(Exception e)
{
Console.WriteLine();
}
}
if (foodComp.IsEaten == true)
{
CreatureComp creature = Creatures[winningCreature];
creature.Energy = creature.AbsorptionRate * foodComp.Energy;
}
}
}
I just added the try/catch
And it makes little sense with the exception
Because the Index is 50, yet the size of the array it is trying to operate on is 100
which line is the error talking abt mainly? just the entity array?
Entity entity = EntityArray[index];
This one
When I double click the error it takes me to that line
hmm
It looks to me that this is something to do with "IJobForEach" itself
As if it had some sort of arbitrary limit on it of 50
that might be the case 🤔
dumb question, what happens if you limit your array size of 51?
I can try
ah dang 😐
okay so I can definitely reproduce what you had
so my thinking is, because there is no read safety insurance on the collection and the compiler can't determine that
if you ensure that the native array is considered ReadOnly, you can ensure parallel reading and it doesn't look like you need to modify the data of the arrays in the jobs
The "creatures" one is the only one that I have to write to, potentially..
I can't give any of these the "readonly" attribute
The entity array can be read only, unless you intend to grow and shrink the array or change its elements mid job, as for the creatures one, if you really need to write back into an array - NativeDisableParallelForRestriction is an option
I can see that this warning is stacking up:
Internal: JobTempAlloc has allocations that are more than 4 frames old - this is not allowed and likely a leak
but if every food is modifying that array, you'll certainly have a race condition - and that warning has been there for quite some time, afaik Joachim did say it was a bug in the editor
oh okay
I guess the problem is that
I'd need some way of marking food and have a main thread system
Like
Do the actual consumption
But that would be changing food
Instead of creatures..
I thought I was clever with this but...I guess the job system just fucks me over once more.
-.-
yea consumption might be a main thread thing, especially if you want creature a and creature b to not eat food x when food x can only be consumed by 1 creature
That's super disappointing...
the other possible way i can think of is if you used some sort of bloomfilter or a concurrent native hash map/set so that for each creature you process on you pick a food to store and check if the food is owned by some creature
then in a separate job, based on your constructed mapping of creature -> food, you can do your consumption and perform your calculations on energy acquired or so
public class MoveTowardsFoodSystem : ComponentSystem
{
private EntityManager m_EntityManager;
private float deltaTime;
protected override void OnCreate()
{
base.OnCreateManager();
m_EntityManager = World.Active.EntityManager;
}
protected override void OnUpdate()
{
deltaTime = Time.deltaTime;
Entities.ForEach((ref CreatureComp creature, ref Translation transComp) =>
{
if (creature.IsIdle == false && creature.FoodTarget != null)
{
float3 pos = m_EntityManager.GetComponentData<Translation>(creature.FoodTarget).Value;
transComp.Value = ((pos - transComp.Value) * creature.Speed * deltaTime);
}
});
}
}```
I'm trying to make this into a job instead as that seems rather straight forward at least...but I can't quite wrap my head around how to approach that.
I've come this far and I'm blanking
public class MoveTowardsFoodJobSystem : JobComponentSystem
{
public struct MoveJob : IJobForEach<CreatureComp, Translation>
{
Entity FoodTarget;
public void Execute(ref CreatureComp c0, ref Translation c1)
{
if (c0.IsIdle == false && FoodTarget != null)
{
float3 pos =
}
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
MoveJob job = new MoveJob();
JobHandle handle = job.Schedule(this, inputDeps);
return handle;
}
}```
I'm having an issue here because I store the Entity to the food I wanna get to
But I'd still need to get the Translation for the food I'm heading towards
And I don't really know how to achieve that
The job system is really not intuitive
public struct MoveJob : IJobForEach<CreatureComp, Translation>
{
Entity FoodTarget;
[ReadOnly] ComponentDataFromEntity<Translation> FoodTranslation;
public void Execute(ref CreatureComp c0, ref Translation c1)
{
if (c0.IsIdle == false && FoodTarget != null)
{
Translation foodPos = FoodTranslation[FoodTarget];
float3 pos = (c1.Value - foodPos.Value) * some_speed * some_delta;
c1.Value = pos;
}
}
}
might be what you're looking for
the job system will certainly take some time getting used to
ComponentDataFromEntity<Translation> FoodTranslation;
This I was unaware was a thing
And it's not something I would have guessed just by looking at it
Because it feels like I am declaring something that I should populate
But from the way you write it, this is not the case.
well when you schedule the job
you will certainly populate it via the constructor or short hand constructor
Alright then..
Problem now is that
Unity says I didn't declare shit ReadOnly
When I did
InvalidOperationException: The NativeContainer ConsumptionJob.Data.EntityArray has been deallocated. All containers must be valid when scheduling a job.
fun
Well
It's all just systems now, no jobs
Though I can see that my implementation is pretty faulty somewhere
The creatures move insanely fast, like jittering
Is there a way for entities to use light probes or lightmaps in LWRP? Both static and dynamic game objects which I convert to entities are just black at runtime
nope 😦
That's a pretty major limitation, isn't it? Are the plans to have it implemented at any point?
AFAIK we don't know any specific plans but for sure, they'll support it eventually - it is a major limitation - hopefully we should find out more when Unite hits
Hm okay thanks for the info. Just to double check it's not something that a custom SRP could handle?
im sure a custom srp could do it but that sounds like way too much work for something unity should get around to doing themselves
anyone here going to Unite Cophenhagen?
not me 😦
😦
are you going?
i'm considering it, i have relatives coming from NZ on the 26th so i'd have to cut it short.
Hmm, if I had thought about it earlier I could probably use my employer's standing offer to pay for relevant conferences, especially since the trip itself wouldn't be particularly expensive (from Norway), but it's a bit short notice now, having a contract out september and all.
Then again, I did give it some thought earlier, and essentially came to the conclusion that it would probably not be worth it with most important talks being available online (recordings or summarized) and I don't particularly like traveling.
i enjoy travelling, but im bad at networking so i guess the main point of these conferences is wasted on me 😄
Question for you folks
I have the following job system to move my creatures around:
public class MoveTowardsFoodJobSystem : JobComponentSystem
{
public struct MoveJob : IJobForEach<CreatureComp, Translation>
{
public float deltaTime;
[ReadOnly]
public ComponentDataFromEntity<Translation> allTranslations;
public void Execute(ref CreatureComp creature, ref Translation translation)
{
if (creature.IsDead == true || creature.IsIdle == true || creature.FoodTarget.Equals(Entity.Null))
{
return;
}
else
{
float3 foodPos = allTranslations[creature.FoodTarget].Value;
float3 moveDir = Vector3.Normalize(foodPos - translation.Value);
translation.Value += moveDir * creature.Speed * deltaTime;
}
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
ComponentDataFromEntity<Translation> translations = GetComponentDataFromEntity<Translation>(true);
MoveJob job = new MoveJob
{
deltaTime = Time.smoothDeltaTime,
allTranslations = translations
};
job.Schedule(this, inputDeps);
return inputDeps;
}
}```
But when I run the code, I get the following error:
> InvalidOperationException: The writable NativeArray MoveJob.Iterator is the same NativeArray as MoveJob.Data.allTranslations, two NativeArrays may not be the same (aliasing).
And I suppose I understand what this means but
I don't really
How would I possibly get around this issue?
oh wait, no I see you're taking it as a component into the job as well
I just tried that any way. Didn't work
yea you can't take it as a component in a job at the same time as a CDFE (as far as I know) - so if you instead use IJobForEachWithEntity, you can then lookup your translation component via that entity
cool - yea it should work fine but report back if there are errors
fyi I also think you should do inputDeps = job.Schedule(this, inputDeps); as otherwise you're not passing on the dependencies of your job - also you can [readonly] to your creature ref I think
new problem
Now it seems that the issues I had are at least solved
But
The creature is looking for food
Yet the entity that is used for the food on the creature
Might not exist
Could you post your new system code
Okay I got around that
I just check my array of translations if the food entity exists in it
If it does, then the creature can move towards it
But one thing that's weird now is that even though I assign a delta time to the job
DeltaTime is 0
public class MoveTowardsFoodJobSystem : JobComponentSystem
{
public struct MoveJob : IJobForEachWithEntity<CreatureComp>
{
[ReadOnly] public float deltaTime;
[ReadOnly] public ComponentDataFromEntity<Translation> allTranslations;
public void Execute(Entity entity, int index, ref CreatureComp creature)
{
if (!allTranslations.Exists(creature.FoodTarget))
{
return;
}
else
{
if (creature.IsDead == true || creature.IsIdle == true || creature.FoodTarget.Equals(Entity.Null))
{
return;
}
else
{
float3 foodPos = allTranslations[creature.FoodTarget].Value;
Translation creaturePos = allTranslations[entity];
float3 moveDir = Vector3.Normalize(foodPos - creaturePos.Value);
creaturePos.Value += moveDir * creature.Speed * deltaTime;
}
}
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
MoveJob job = new MoveJob
{
deltaTime = Time.smoothDeltaTime,
allTranslations = GetComponentDataFromEntity<Translation>(true)
};
inputDeps = job.Schedule(this, inputDeps);
return inputDeps;
}
}```
interesting
i had pretty much the same aliasing issue earlier this week and ended up splitting it into multiple jobs 😦 this approach is probably better! the part i was missing was to remove the Translation from the IJobForEachWithEntity and use only the ComponentDataFromEntity
But why my delta time be 0 now? ;_;
yea - the error's much more obvious when you use IJobChunk - bit of a shame you can't iterate over some of the components linearly with rand access to the rest but I guess it makes sense because of the type lookup stuff
Okay so
DeltaTime is higher than 0...
But my creatures are not moving
Yet I do make it into the job that is supposed to apply movement
missing an allTranslations[entity] = creaturePos; perhaps
Translation creaturePos = allTranslations[entity];
when you change creaturePos.Value you're just changing the local struct - you need to assign it back
ah fuck
But how am I supposed to do that from the job?
The translation collection is readonly
if you want to write to it, you have to remove the readonly
then it will likely give you an error because from a job you might be writing to the same entity more than once
Yeah it says I need a different collection...
fuck this =_=
InvalidOperationException: MoveJob.Data.allTranslations is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.
either you can be totally sure you won't (because you only ever set each creature's translation) - in which you can just add [NativeDisableParallelSafetyChecks] (not that but something similar - I forgot the exact name)
or you have to go down the route of two jobs
NativeDisableParallelForRestriction
Or a entity command buffer
ah yes good point
cool cool
The job is supposed to only work on a single creature at a time so
It shouldn't be a problem as none of the other jobs would touch other creatures
yea, that's exactly why that attribute exists - to make sure you think and understand that you gotta be careful
but that if you know, you can just do it
have you enabled burst?
[BurstCompile] above your job?
would also try with safety checks disabled when looking at performance at all
should be night and day difference
Just the struct right?
I think so
if you do things like add or remove components (via a commandbuffer) for example, that's not supported by burst atm
Okay but so
eventually you won't have to add it I would guess - they've just been taking an 'opt-in' approach so far
It's just because burst is under development atm that you'd not want the tag on all jobs then
I believe so
it's been asked previously - I think they just want to feel 100% about it before they make it default
any faster?
yea there's something odd going on - did you post the full system above?
I haven't posted all of my code, but one system in particular is taking a ton of resources
And I'm pretty sure I know why
It's because each piece of food tries to check if it's colliding with any creature so it can be marked "Eaten".
public class ConsumeFoodSystem : ComponentSystem
{
private EntityManager m_EntityManager;
protected override void OnCreate()
{
base.OnCreateManager();
m_EntityManager = World.Active.EntityManager;
}
protected override void OnUpdate()
{
NativeArray<Entity> creatures = GetEntityQuery(typeof(CreatureComp)).ToEntityArray(Allocator.TempJob);
Scale creatureScale;
Translation creatureTranslation;
CreatureComp creature;
Entities.ForEach((ref FoodComp foodComp, ref Translation trans) =>
{
if (foodComp.IsEaten == false)
{
for (int index = 0; index < creatures.Length; index++)
{
Entity entity = creatures[index];
creature = m_EntityManager.GetComponentData<CreatureComp>(entity);
if (creature.IsDead == false)
{
creatureScale = m_EntityManager.GetComponentData<Scale>(entity);
creatureTranslation = m_EntityManager.GetComponentData<Translation>(entity);
float distance = Vector3.Distance(trans.Value, creatureTranslation.Value);
if ((distance - creatureScale.Value) < creatureScale.Value)
{
foodComp.IsEaten = true;
creature.Energy += creature.AbsorptionRate * foodComp.Energy;
if (creature.Energy > creature.IdleThreshold)
{
creature.IsIdle = true;
}
creature.FoodTarget = Entity.Null;
break;
}
}
}
}
});
creatures.Dispose();
}
}```
It's the one task I'd like to try and jobify
ah ok
So for every 1 piece of food
It needs to check a potential 100 creatures
Or well
250 creatures in this case
you can put the GetEntityQuery(typeof(CreatureComp)) into OnCreate() and store it to a field rather than creating it every update
Problem is
I might wanna start destroying creatures at some point
And adding new ones
eventually you can do that by using a new system but anyway, yea jobify and burst away I guess
I want to remove entities in an IJobForeachWithEntites, but if i do that I can't use burstcompile because it's not compatible with the commandbuffer right?
Are there any alternatives?
Aight @amber flicker Now my FPS is 270
Like somehow marking it for removal or adding a component so it gets deleted later
nice
much better @tardy locust nice
yea
@surreal rune ideally you would use a bulk query call.. e.g.. EntityManager.DestroyEntities(myEntitiesToDeleteQuery) or something - usually you have to preselect a subset of entities from an archetype so you can either fill a nativequeue in parallel then read one by one or you could look into NativeStream's which are supposed to read and write in parallel but I'm not familiar with them
you can also just use command buffers
Ohh so i can make a nativearray
In my jobforeach i fill the nativearray with entities to delete
So not delete them there and then
yea
and then delete the stuff in a seperate job?
So i can burstcompile the first job
and the second one has less entities
So its faster i guess
yea exactly
np
Hmm
One more question
I dont know before the job how many I'm going to need to delete
So i can't use a nativearray
And i cant use a nativelist in parallel
do you have any tips for that?
nativequeue supports parallel add, so does dynamic buffer If I remember correctly @surreal rune
Alright which of those 2 would you recommend?
er anyone getting issues with building stuff with dots and 19.3b1?
specifically a resulting build has entity conversion and (so far) rendermesh entities appearing in the wrong place/not getting the right translation/rotation/scale data as compared to an in editor play result(which appears correct)
Thanks @low tangle
So I have a NativeQueue Parallel writer i want to use in a IJobForeachWithEntity
After completing the job, i want to use the same NativeQueue in a job
But in a normal job, I can't or don't need it as a parallel writer
Should i convert it back somehow?
ok just tested in 19.2, definitely a 19.3 bug 😩
also anyone know why static objects dont get converted, only destroyed? this has been a thing for a while, dunno if this is by design or what
can't just chain the queue though multiple jobs?
right, but you just put the base queue as a varable, then bring in the parallel for one, and direct for the second
why might this be slowing down my game so much? I'm getting less than 40 fps with only 30 entities
Entities.ForEach((ref Position2D pos,ref Velocity velocity,ref MovementData moveDat,ref Radius radius) => {
Vector2 velocityDir = math.normalize(velocity.value) * radius.value;
Debug.DrawLine((Vector2)pos.value,(Vector2)pos.value + velocityDir,Color.black);
float speedPercent = ((Vector2)velocity.value).magnitude / moveDat.moveSpeed;
Debug.DrawLine((Vector2)pos.value,(Vector2)pos.value + velocityDir * speedPercent,Color.green);
});
its in a ComponentSystem
You might want to create a deferred buffer for the debug draw lines based on color.
The Debug and Gizmo draw functions work better when you don't change the color between calls, wheras with what you're doing you're doing it every time.
If this is for editor only code, I suggest the Gizmo drawing routines.
You may also get more perf out of the low level GL drawing commands instead of debug.draw, as the Debug.Draw functions are ancient and aren't built for speed.
I'm getting this error: InvalidOperationException: The NativeArray GetPlantsShouldBurn.Iterator must be marked [ReadOnly] in the job PlantUpdateSystem:GetPlantsShouldBurn, because the container itself is ma
What's weird is that GetPlantsShouldBurn is an IJobForeachWithEntity
So i have no clue what to mark as readonly
Hey guys can sombody help with one script
It errors on creation of the GetPlantsShouldBurn Job
Can anyone help me with this?
I can't help you im very bad at scripting and i need help to
This is ECS channel
ik
Mentioned above
Sorry, I haven't touched ECS and jobs yet 🙂
Ah alright
@surreal rune put [ReadOnly] before the read only arguments in your Execute method,
public void Execute([ReadOnly] ref BoardPosition boardPosition, // etc
I just figured that out as you said it
so wait
If i don't write to an argument, it must be readonly?
I thought the readonly was optional
Just to increase performance or something like that
@mint iron Thanks for the tip btw!
np! i've been caught by that one a few times, its a pretty confusing exception message. If you're using a query then it seems to be based on the ComponentType.ReadOnly / ReadWrite used in the query declaration. If you're passing in the system then i'm not sure how it decides.
Hmm I get it now thanks!
One more question
I keep getting these errors
And up to now ive been trying to manually find the NativeArray to blame
Is there a consistent way to find the issue?
How would you go about matching an entity to another by a value of component? Say I random value for a component on an entity, and want to add it to a separate archetype which holds same value. (which I know existst)
Setting the define TLA_DEBUG_STACK_LEAK in script defines doesnt seem to wrok
@mystic mountain you mean like a component has a bool with true and you want to find all entities with that bool set to true?
Sort of, I have a player entity which chooses a faction, and I want to place him on a ship with that faction.
Seems like it would be easier to just make a Component from the faction
You mean one for each?
Yea
if the player has the faction entity, then you could loop through the players, lookup a buffer on the faction entity with ComponentDataFromEntity/BufferFromEntity and add the player to it. So now the faction knows all the players assigned to it. Then you could have a ship grab the players from the faction that the ship is assigned to. It just depends on where you want to store the data.
So you can use the builtin ecs functions
I should look into these buffers
@mint iron Do you have a tip for my last question maybe?
sorry if im asking a lot lol
I don't like it since then they will become separate archetypes
@surreal rune no sorry i've never seen that exception before
Really?
I get it all the time if i don't dispose a nativearray
But i kind of have to guess which array it is
Did you enable full stack traces?
Then no idea.
Anyone know how in what order Translation, LocalToWorld, LocalToParent are applied? If I add LocalToParent, will it be using that matrix to calculate Translation, or other way around etc?
@mystic mountain here is a manual for the transform system https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/transform_system.html
the basic is that the location, rotation, scale, etc, are used to make the local matrix
then using local to parent, they calculate local to world
but there are a lot of combinations in that manual
like you can have only some of those components, or variations of those, and what gets calculated, or calculated only once changes a bit
I see, so if I have my wanted position locally, I need to first convert it with parent localToWorld.
From quick overview it looks like LocalToWorld is calculated last.
Good info!
So what is the best way to render a ton of entities?
I have 3 types of entities which should be represented by a green box, red box and black box
Now i just use sharedRenderMeshes but it still impacts performance a ton
What is the most efficient/performant way to render simple stuff like this?
Just turned on GPU instancing on my materials which made some difference but not a lot
Rendering the entities made my fps go from 300-600 to 40-70
What quantity of entities?
I dont suppose anyone knows how/if I can use a dynamicbuffer with HasSingleton
I get a boxing error conversion, I think the method can only take Icomponent data
if you're after a dynamicbuffer with a singleton couldn't you just use a NativeList or similar as a public property of the singleton system or something?
@surreal rune typically rendering about 100k cubes takes very roughly ~4ms on my i5 - if you want it to be faster I think you need to look into calling DrawMeshInstanced directly
can you use nativelist or nativearrays in Icomponentdata's?
it's easier? I only need one set of the data, their waypoints stored in a buffer
that seems like the simplest cheapest way to store the waypoints on a single entity in a buffer
There might be a way but imo it doesn't make a lot of sense - I don't see the benefit of tying it to an entity or how public NativeList myWaypoints is much harder
@amber flicker Couple thousand
with Burst enabled, what does your profiler look like? it shouldn't be that expensive with instancing on
Burst for rendering?
I assume RenderSystemV2 (or whatever it's called - the hybrid render stuff) needs you to have Burst enabled in the menu for you to see decent performance in editor
I see so you mean store it in a system instead of an entity, that probably is better your right, thanks
yea with something like waypointSys = entityManager.GetExistingSystem<WaypointSystem>() on create then waypointSys.waypoints
And this is with only 170 entities
safety tests off? and can you show the timeline view?
you're just rendering basic cubes right? no complex meshes
that looks like a lot of gc
safety tests on by any chance? they generate a lot
Safety checks now off
But doesnt seem to make much of a difference
Safety Checks off this time
Hmm
This time it seems just my systems
that last screenshot doesn't seem to show anything happening on your other threads - worth expanding 'jobs' and extending down the 'main thread' area a little too
nvm its not the systems
More like this
Not really used yet to reading the timeline
only the hierarchy lol
yea it's such a useful view
esp for multithreaded stuff
how many lights do you have in the scene? might be worth disabling them just as a comparison
Yeah
Only 1 directional
Its an insanely simplistic scene lol
but i'll disable it one sic
sec
I also still get these
Which i find hard to track down
Might be related?
oh well yea.. that'll be killing your perf and probably explains the gc 🙂
So
they're a pain to debug as everytime you get one of those you need to restart the editor to see if you fixed it
Yeah true
But is it all manually looking for it?
Is there no way to see which nativearray?
it says to enable a define
but when i do that in script define in player settings it doesnt do anything
afaik that message about the define isn't useful.. full stack traces is sometimes useful (from the jobs menu)
Thats on already
but mostly just enable systems one by one and look for any time you create a NativeArray or similar
not something I've ever had much trouble with but if you find it difficult, perhaps you could add the tag above every system that stops it being automatically added to the world and then re-introduce them one by one
yea that's probably as easy as anything... they do have a .enabled as well
👍
Thanks!
I have one more question for after this
I have 2 systems, one which updates a nativearray
One which uses that nativearray in a job
Now it says I need to add the first one as a dependency to the second one
Because it reads from the same NativeArray
Is there a way around that?
Because it feels iffy to have to add a dependency to another system
yea that never feels great... easiest solution is to move both jobs into the same system (thus limiting your scope of concerns) but sometimes that's undesirable
This time the Job Alloc error is fixed
@amber flicker, Maybe i should consider that, thanks
I think they can be in the same system
you can also create a persistent NativeList or something OnCreate and destroy it in OnDestroy but you will still have to call .Complete on the first job
correct, but at the cost of some potential performance
Ok
that profiler shot still looks suspicious with all that garbage
so adding as a dependency would be preferable?
yea usually
You mean the spikes in the graph?
it's all the red under everything
I'll show you how I instantiate the entities
maybe thats wrong
Im gonna clean it up when it's functional so dont judge me :p
looks fine at a quick glance - that profiler isn't showing you instantiating a bunch every frame is it?
sure
I have a basic stupid question how do I use a permanent nativearray in a job?
I keep getting mem leak errors and it saying not deallocated nativearray properly
I've tried both [DeallocateOnJobCompletion] inside the job and .Dispose(); outside of the job
Show me what you are trying to do
If you declare a native array outside of a job, and include it in its construction, then you use the attribute [DeallocateOnJobCompletition]. Make sure the NativeArray has "TempJob" as its allocator.
public class WayPointMoveSystem : JobComponentSystem
{
public float MoveSpeed;
public NativeArray<float3> MoveWaypoints;
protected override void OnCreate()
{
MoveWaypoints = new NativeArray<float3>(2, Allocator.Persistent);
MoveWaypoints[0] = new float3(-47, 2.2f, -50.65f);
MoveWaypoints[1] = new float3(-47, 2.2f, 43.8f);
}
struct MovetoJob : IJobForEach<Translation>
{
public float movespeed;
public float deltatime;
[ReadOnly]//[DeallocateOnJobCompletion]
public NativeArray<float3> tempwaypoints;
public void Execute(ref Translation currmover)
{
//if(gothere.)
float3 movedir = math.normalize(tempwaypoints[0] - currmover.Value);
currmover.Value += movedir * movespeed * deltatime;
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
MoveSpeed = 5;
var movetoobjob = new MovetoJob
{
tempwaypoints = MoveWaypoints,
deltatime = Time.deltaTime,
movespeed = MoveSpeed
};
inputDeps = movetoobjob.Schedule(this, inputDeps);
//MoveWaypoints.Dispose();
return inputDeps;
}
}```
I get the error "InvalidOperationException: The NativeContainer MovetoJob.Data.tempwaypoints has been deallocated. All containers must be valid when scheduling a job." if I use deallocate inside the job
because I need it for the life of the system
It seems like it expires at the end of the job though?
I need it to permanently store the waypoints
jobs can only use temp arrays though cant they?
maybe I could just cast the permanent array to a temp array?
Considering how you populate that array, with static numbers, why not just create it in the OnUpdate, pass it to the job struct and use the Deallocate attribute inside the job?
From the way your code is written there is no reason for the array to be persistent.
I dont if I put it in the onupdate then its doing unnecesary work surely?
having to set up the variables constantly
public class WayPointMoveSystem : JobComponentSystem
{
public float MoveSpeed;
struct MovetoJob : IJobForEach<Translation>
{
public float movespeed;
public float deltatime;
[DeallocateOnJobCompletion]
[ReadOnly] public NativeArray<float3> tempwaypoints;
public void Execute(ref Translation currmover)
{
float3 movedir = math.normalize(tempwaypoints[0] - currmover.Value);
currmover.Value += movedir * movespeed * deltatime;
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
NativeArray<float3> MoveWaypoints = new NativeArray<float3>(2, Allocator.TempJob);
MoveWaypoints[0] = new float3(-47, 2.2f, -50.65f);
MoveWaypoints[1] = new float3(-47, 2.2f, 43.8f);
MoveSpeed = 5;
var movetoobjob = new MovetoJob
{
tempwaypoints = MoveWaypoints,
deltatime = Time.deltaTime,
movespeed = MoveSpeed
};
inputDeps = movetoobjob.Schedule(this, inputDeps);
return inputDeps;
}
}```
If you want, I suppose you could have a reference to the MoveWayPoints outside, but considering what you are doing here I think the array has to be TempJob
So regardless it'll need to be deallocated
yeah, thanks, that seems a bit weird having to duplicate the data like that though
Well to be honest
ECS in Unity is a lot of repetition
Of code
From what I can gather at least.
Because one thing you have to consider in this scenario
Is that you cannot ensure when you are actually done with array if it's persistent
It could sit in memory forever
yeah I know its going to sit for the life of the system basically
The point of jobs is that you isolate what you are working on
So it only really exists during the lifetime of the job, I think
So when the job is deallocated after compleition, then so is all of its other references.
At least that's how I understand it
yeah
@pliant pike what you were doing should have been fine if you just put the dispose in OnDestroy instead of the job I think
(though I only quickly looked)
For the most part, components are for data, organized into entities, and systems are for behavior.
Of course, putting a helper function on a component, or caching an archetype on system start isn't that big of a deal, but it all depends on how close you want to follow the principles and/or best practice, and of course, how easy it is to code and maintain.
yessss! I think it works, no errors, thanks @amber flicker
@tawdry tree Well yeah, but then you look at something like the FPS Sample and you find ECS violations all over the place xD
Yeah, hence the last sentence
I imagine the samples will over time get closer to ECS principles. Or at least closer to the best practices, once we actually figure those out...
what happened to GetEntities? It doesn't exist for me, for some reason. Yes, I am using the entities namespace (Unity.Entities)
Might've been deprecated
if it's an entity query, you can do query.ToEntityArray(Allocator)
Btw, has anyone got GameObjectAfterConversionGroup attribute working to successfully modify a converted gameobject -> entity
e.g. let's say I'd like the ConversionWorld to cleanup some entities, like remove the LocalToWorld component datas
I can definitely log that the cmd buffer ran bu the entity when transferred back to the default world still has the LocalToWorld componentdata
i have a really simple system that removes the PhysicsVelocity component during conversion,i dont know about the 'GameObjectAfterConversionGroup' attribute but heres the code. it should still work but I havent used it in a while
using Unity.Entities;
using Unity.Physics;
using Unity.Physics.Authoring;
namespace Game.Modules.Conversion
{
/// <summary>
/// This System tells the conversion system to remove any PhysicsVelocity during conversion.
/// Uses the RemoveVelocity component.
/// </summary>
[UpdateAfter(typeof(LegacyBoxColliderConversionSystem))]
[UpdateAfter(typeof(LegacyCapsuleColliderConversionSystem))]
[UpdateAfter(typeof(LegacySphereColliderConversionSystem))]
[UpdateAfter(typeof(LegacyMeshColliderConversionSystem))]
[UpdateAfter(typeof(PhysicsShapeConversionSystem))]
[UpdateAfter(typeof(LegacyRigidbodyConversionSystem))]
public class PhysicsAdditionalConversionSystem : GameObjectConversionSystem
{
protected override void OnUpdate()
{
Entities.ForEach(
(StaticFractureAuthoring removeVelocity) =>
{
var entity = GetPrimaryEntity(removeVelocity.gameObject);
DstEntityManager.RemoveComponent<PhysicsVelocity>(entity);
}
);
Entities.ForEach(
(RemoveVelocity removeVelocity) =>
{
var entity = GetPrimaryEntity(removeVelocity.gameObject);
DstEntityManager.RemoveComponent<PhysicsVelocity>(entity);
}
);
}
}
}
Ah thnx @safe lintel , maybe I'll jst keep it in the GameObjectConversionGroup instead
Just how split-up do chunks for archetypes reasonably get in practice? Looking at the character controller physics sample, the components there got up to 96-ish bytes all together (there might be some padding in there but I just gave it a quick glance). I can imagine the total component count per component per chunk getting kind of slim after giving an archetype enough systems, but what are the reasonable averages and maximums in practice?
And if the total entity count per archetype chunk ends up getting low too easily, what are some ways of getting around the issue?
Like if you had two large subgroups of related components that could be split (conceptually) easily, where the two subgroups were associated by basically one system that took a component from each set, could you divide those component sets into different chunks somehow? Would it be advisable to do so? And if so, what would be the common strategies for doing so? I imagine things get difficult when you have two supposedly parallel archetypes and have to match their entities with different entity counts per chunk, not to mention the added complexity for copying/removing/safely scheduling/etc
TLDR how likely is it for component-heavy archetypes to bog down entity counts per chunk, and are there ways to deal with the problem?
basically slim down the problem you are solving at any one step, along with using more tag components
archtype and fragmenting only effected me ever once
that one time, was to squeeze the maximal out of a distributed compression and decompression algo across sets of 60 entities
the difference was making it work for 1000 of those at a very reasonable frame rate cost vrs 100s of ms
outside of that one case I haven't had to pay much attention to my arch types other than a asset request system lately where I noticed my type is growing a lot
@coarse turtle i've had success using the new EntityManager.SetArchetype inside an IConvertGameObjectToEntity Convert() to get it to discard all the default transforms and stuff.
Ah cool never thought of that
anyone else having really bad stability on the latest versions + editor 0b1? i tried upgrading everything today because i need a newer version of shadergraph but it broke all my addressables, and all my shaders, and now crashes the editor randomly every 5 minutes.
for the shaders (if it's the LWRP) I did do these instructions to upgrade to the universal render pipeline https://docs.google.com/document/d/1Xd5bZa8pYZRHri-EnNkyhwrWEzSa15vtnpcg--xUCIs/edit
im still upgrading the entities side atm and fixing up some deprecated things
but with shader graph, I just opened the shader graph file and resaved the assets to regenerate the shaders for the universal render pipeline
@low tangle so how did you slim down your archetypes when it mattered that one time?
Or more generally, what are the known/recommended strategies for doing so?
I'm perplexity about computing some data. I have methods that i need to call very rarely. But the problem is i can't predict how many entities will need to call those methods in 1 frame. It can be about 10 in a same frame or 100 in a same frame, or even 1, but 99% of frames methods will not be called. So i want to make it all with jobs.
The first solution for me was to separate logic to IJobForEach jobs that executes every frame and IJobParalleFor for rare logic. But it cause using CDFE/BFE with slow data accessing.
Another way is to use IJobChunk and access all possible data and dazzle together all logic without any troubles with data transfer and using slow data accessors
What the better way u think. And maybe i just misunderstood something
what about only calculating a few at a time?
you can use the chunks version number to only calculate things every 4 frames or similar
i can't predict when i need to update it
@vagrant surge what do you mean using the chunks version number to only calculate things every 4 frames?
@mint iron I get a lot of crashes on recompiling or entering/exiting playmode. None during just play mode or working in editor when not compiling though.
also that SetArchetype looks very handy
@spring hare basically I just reworked how I was thinking about the problem to split the data better, and make more fit into one chunk (less fragmenting)
So you didn’t move data out of the archetype and process some of the data elsewhere
split some entities and just kept refs
but for the most part I could just slim down the entity and make it simpler
When you split the entities, how did you manage the refs? Did you have to eat the per-ref pointer chase cost, or did you manage to iterate different component chunks in semi-parallel, or did you maintain your own parallel nativearrays, or something different?
eat the pointer cost, awhile back I was weary about it, but joachim said on the fourms, paraphrasing 'if it comes down to it and you need to random access some data, the best way is the simplest way of just accessing it though a ref/pointer, its about as fast as you can get'
basically, its okay, just accept the random access and focus your efforts elsewhere. if you really cant eat the performance (hyper critical performance stuff) you will have to rework your design to be more dots / bulk iteration friendly. but that can be super costly and non trivial
simple > complex and slightly faster
That makes sense, thanks for giving a breakdown of your process there
yeah np
Just declined my unite invite 😦 I dont suppose anyone else got one?
I got declined the other day lol
wait unless, I totally misunderstood what you mean 🤔
did you get a free unite invite for community engagement?
Oh no, I applied to do a pop up talk at unite
ohh - what was the proposed talk about?
I wanted to talk about a testing pipeline on production assets with unit/play mode tests
before shipping a project
with workflows using the conversion pipeline for ecs
i wouldve attended 🙂
lol thnx, it's something I've been doing working on art simulations with artists
are you still going to unite then?
No ):
it's a tad too pricey for me to travel there
I think if there was one in NA, I certainly would've gone
yeah, same
booking wise, I kind of waited until Unity gave me a response on the pop up talk application, and the prices just jumped a few hundred on plane tickets
but hopefully they'll stream a few of the ECS talks 🤞
@safe lintel I just accepted my invite
Flights are relatively cheap for me, it's the hotels that cost more
@coarse turtle they usually only stream the keynote live if anything
yeah, i expect that much, i dont remember things being streamed at the talks last year
otherwise it'll be ~3 weeks until they start uploading talks to their youtube channel
thanks :) never attended these live before but couldnt pass the offer as it cant come much closer to me
Unless they somehow do event in Helsinki some year :D
But we have only tiny local Unity office here
We do have one of those smaller 1 day community events here tho
yea same here
@safe lintel @dull copper accepted my invite yesterday 😄 should be fun!
stupid question, I cant use things like transform.lookat, or vector3.movetowards in jobs so am I going to have to figure out the maths to do these things?
Transform.LookAt(...) no you wouldnt be able to run in a job, possibly you can run Vector3.MoveTowards in a job
but you can likely do linear interpolation for Vector3.MoveTowards
As for looking at something, i'd imagine its computing the angle between 2 vectors and easing 1 vector towards the other until the angle is less than some threshold
I didn't think you could use vector3s in jobs, I guess it doesn't matter the maths are pretty simple, I'd just prefer it when they are predone, thanks
I wont paste the full changelog here, it would fill 3 discord screens as it's so long with all the deprecated things so I'll just paste these parts:
## [Unity Physics 0.2.2-preview] - 2019-09-06
### Fixes
* Added internal API extensions to work around an API updater issue with Unity 2019.1 to provide a better upgrading experience.
## [Unity Physics 0.2.1-preview] - 2019-09-06
### Upgrade guide
* A few changes have been made to convex hulls that require double checking convex `PhysicsShapeAuthoring` components:
* Default parameters for generating convex hulls have been tweaked, which could result in minor differences.
* Bevel radius now applies a shrink to the shape rather than an expansion (as with primitive shape types).
* Mesh `PhysicsShapeAuthoring` objects with no custom mesh assigned now include points from enabled mesh renderers on their children (like convex shapes). Double check any mesh shapes in your projects.
* Due to a bug in version 0.2.0, any box colliders added to uniformly scaled objects had their scale baked into the box size parameter when initially added and/or when fit to render geometry. Double check box colliders on any uniformly scaled objects and update them as needed (usually by just re-fitting them to the render geometry).
* The serialization layout of `PhysicsShapeAuthoring` has changed. Values previously saved in the `m_ConvexRadius` field will be migrated to `m_ConvexHullGenerationParameters.m_BevelRadius`, and a `m_ConvexRadius_Deprecated` field will then store a negative value to indicate the old data have been migrated. Because this happens automatically when objects are deserialized, prefab instances may mark this field dirty even if the prefab has already been migrated. Double check prefab overrides for Bevel Radius on your prefab instances.```
### Changes
...
* Run-Time Behavior
* `BoxCollider.Create()` is now compatible with Burst.
* `CapsuleCollider.Create()` is now compatible with Burst.
* `ConvexCollider.Create()` is now compatible with Burst.
* `CylinderCollider.Create()` is now compatible with Burst.
* `MeshCollider.Create()` is now compatible with Burst.
* `SphereCollider.Create()` is now compatible with Burst.
* `TerrainCollider.Create()` is now compatible with Burst.
* Authoring/Conversion Behavior
* Converting mesh and convex shapes is now several orders of magnitude faster.
* Convex meshes are more accurate and less prone to jitter.
* `PhysicsShapeAuthoring` components set to convex now display a wire frame preview at edit time.
* `PhysicsShapeAuthoring` components set to cylinder can now specify how many sides the generated hull should have.
* Inspector controls for physics categories, custom material tags, and custom body tags now have a final option to select and edit the corresponding naming asset.
### Fixes
* Body hierarchies with multiple shape types (e.g., classic collider types and `PhysicsShapeAuthoring`) now produce a single flat `CompoundCollider` tree, instead of a tree with several `CompoundCollider` leaves.
* Fixed issues causing dynamic objects to tunnel through thin static objects (most likely meshes)
* Fixed incorrect behavior of Constraint.Twist() with limitedAxis != 0
* Fixed regression introduced in 0.2.0 causing box shapes on uniformly scaled objects to always convert into a box with size 1 on all sides.
* Fixed exception when calling `Dispose()` on an uninitialized `CollisionWorld`.
@dull copper @mint iron I look forward to living vicariously through your experiences 👍
lol
tbh, if you only care about the sessions, you'll probably get most of them by looking at the recordings anyway
also as I quickly glanced the schedule, some of the things I would have wanted to attend overlapped already
i meant the dinner, tour and allure of swag 😍 also meeting everyone wouldve been nice
now everyone will find out that I'm an old fart, I kinda enjoyed just being an anonymous nickname here 😄
you will still be anonymous to me 😀
Is there something like a NativeSet?
A unique NativeArray?
Right now I just use a NativeHashmap and don't use the values but that's not ideal
this may work for you https://github.com/jacksondunstan/NativeCollections/blob/master/JacksonDunstanNativeCollections/NativeHashSet.cs
i was doing the exact same thing with a nativehashmap, but then i found i was overthinking the problem and didn't even need a set in the first place
I think i do need it though
Or what otehr way did you find?
Might be specific to your scenario
But thanks, that seems like what im looking for!
it's specific to my scenario, i'm sure you have a valid reason
mine was basically trying to keep a set of dirty blocks in a chunk, but i found that just regenerating a chunk's mesh every time was already really fast so there was no need for the complexity
Ah alright
Question: when i import the file, i get errors saying i can only use unsafe if i'm compiling with /unsafe
Is there some setting i need to enable?
oh maybe in player settings
ya it's under player i think
InvalidOperationException: PlantGridUpdateJob.Data.LocationsContainingBurningPlants uses the [NativeContainer] but has no AtomicSafetyHandle embedded, this is an internal error in the container type.
Don't think this works
ooh that's nice 👍
@dull copper good, im an old fart too (by games industry standards), at least that means we wont be partying till 3am?
physics samples updated for the new physics package: https://github.com/Unity-Technologies/EntityComponentSystemSamples
sweet
ah, next physics package release going to happen around Unite
so in few weeks
kinda weird to target such near target right after this release
from forums:
Collider Create() methods are now Burst compatible.
Mesh and convex conversion is now much faster.
Convex shapes now have wireframe previews in the scene at edit time
Fitting shapes to render geometry and/or generating automatic convex hulls now accounts for skinned meshes
Please let us know if you encounter any major issues. Barring any critical issues that arise, our plan is for our next release to fall around Unite. ```
yeah, we had discussions about this
they stack these things for the events
or at least heavily schedule them to be out by the time the events are live
that being said, it's kinda weird they put that 0.2.2 out at all if they plan to release a new one in 2-3 weeks
considering they've been quite slow between the releases otherwise on this
Sucks for developers but makes a ton of sense from a marketing/sales standpoint
I want to get a IJobForeachWithEntity on entities that have either component A or component B
Is there any way to do this?
RequireComponentTag only works on All components given right?
Or should i just make an entityQuery with the Any in the description, get the entities and then manually put the resulting NativeArray into an IJob?
I also need to use the translation in the job
Right now i have this, 2 seperate jobs which do the same thing
the other way is to use GetComponentForEntity<T>
from the JobComponentSystem and pass ComponentDataFromEntity<T> to your job
I think @surreal rune was looking for IJobChunk
oo yea, that works too
Thanks for the suggestions everyone
Currently trying with IJobChunk like @amber flicker said
Is there a way to add and set componentdata in a single operation?
So i dont have to do this:
yea you just pass new Burning as the second arg
AddComponentData(entity, new Burning{blah})
Oh wow
I only just realized there's a AddComponent and AddComponentData
Thanks, that worked!
I see AsParallelWriter() in NativeList. But what is AsParallelReader() for?
Does anyone have any idea how/if I could turn the below code into a JobCompSyst or even whether it would be a good idea?
[AlwaysUpdateSystem]
public class TimeTickSystem : ComponentSystem
{
//1.0f is about equal to 1 second 0.5 is about half a second
private const float TICK_TIMER_MAX = 0.0001f;
private int tick;
private float tickTimer;
protected override void OnStartRunning()
{
tick = 0;
tickTimer = 0.0f;
}
protected override void OnUpdate()
{
if (HasSingleton<TimeTickEvent>())
{
EntityManager.DestroyEntity(GetSingletonEntity<TimeTickEvent>());
}
tickTimer += Time.deltaTime;
if (tickTimer >= TICK_TIMER_MAX)
{
tickTimer -= TICK_TIMER_MAX;
tick++;
Debug.Log("tick" + tick);
if (!HasSingleton<TimeTickEvent>())
{
EntityManager.CreateEntity(typeof(TimeTickEvent));
}
}
}
}```
What's happening with that entity? It seems to me like you don't use it? Or is it used elsewhere?
And for that matter, what are you trying to accomplish here? What's the use case/goal?
I use it elsewhere to create other entity's
What the problem to use IJob and ECB?
its a time tick system so I can have events happen at specific rates, like once a second or 1 every tenth of second
I'm wondering how low I can get the time bits down to
whether a job would make any difference
Which also, by the way, means that whatever uses that would be non-deterministic, since it would be framerate-dependent
It seems like a clunky/awkward way to do that, too, though I shan't complain since I don't have any better suggestions.
its framerate independent though, with time.deltatime isnt it?
Well, yes no sorta
Depends on other things, too
If it's just, say, moving in a straight line, nothing else? Sure.
Except you get floating point inaccuracies.
my frame rate fluctuates like crazy and the time tick seems to be pretty consistent
But what if you suddenly use the position to check something? For example, if X > 100, do something? the first frame after it crosses that line, it'd activate
Of course, you might not care about fully deterministic code, but you should be aware of it
I'm not sure what you mean, but I'm just using the above code to create one entity in another script every second
I'm guessing a JCB wouldn't make much difference, I cant run time deltatime in a job so it would keep stopping and starting the job which would be more overhead than a ComponentSystem
That system seems like overkill for that. If you want to scale it up you would likely (it seems to me) want to have potentially different timers, ie. something goes every 1s, something else every 10s, another every 0.2s)
For using deltatime in a job, you just send it in as a parameter, though?
yeah its cached and you need delta.time updated every frame
I'm not sure how you would do it with less code and different timers
In the other system, the one depending on the timer, in OnUpdate:
if(Time.time % run_every_X_seconds != 0)
return; //Skip
//Implied else
//run system logic/job
That should have the desired effect?
yeah I'll see how that works thanks
KISS principle at work :P
We all fail at it occasionally, miserably at times...
Ah, sneaky extra start-parenthesis
You want to modulo the time, of course, and check if it's not whole, ie. one 'cycle' has passed
Though thinking about it, it likely won't work because floats
oh I changed it to this
if (Time.time > nexttimer)
{
Debug.Log("Tick" + nexttimer);
nexttimer = Time.time + TickTimerMax;
}```
That looks better, yeah
I'd save the time it triggered, rounded to the nearest whole cycle, though
That code can slowly 'drift'
how so?
Greater than.
Say, for example, that the cycle is 1/sec, and the time is 0.99s for one frame.
Then, the next frame, it is 1.01s. The next tick would then come no sooner than 2.01s
Something like this?
int previousCycle=0;
const float tickRate = 1f;
//Update
int currentCycle = (int)Mathf.Floor(Time.time/tickRate);
if(currentcycle <= previousCycle)
return; //Skip
//Implied else
DoStuff();
previousCycle = currentCycle;
Cycles being integers intentionally, such that you can say for sure whether you're at a new one or not.
Also, I use Floor here, but you can use Ceil to start at cycle 1 instead of 0 (if my head-math is right)
ok I think I get it, thanks a lot for that
Would it make sense to use ECS to make a hex grid and maintain it?
Or would it make more sense to keep that as gameobjects?