#archived-dots
1 messages Β· Page 122 of 1
no I don't mean a sharedcomponent for the NativeContainer but just to sort them into the right chunk
Yeah that's what I mean, I'm using SCD as opposed to a NativeContainer
@warped trail thanks but they do it particle based, I want to do it grid based (so not each water thing is a entity, but each tile stores how much water there is right now, in which direction it flows etc)
@zenith wyvern can I pn you?
or I mean I can also write it down here but don't want to spam so much:
there is code examples how can you use hashmap to acces your neighbors π€
what exactly are you using the scd for? I thought your voxels arent entites but you have their data in Dynamic Buffer of some other entities?
there's something about physics layers @opaque ledge but I haven't used them myself so I"m not sure how they work.
@warped trail I have a good idea on how I want to access my neighbors, I am just overthinking if my memory layout is good or not
there is a collision filter on raycasts but not on collider casts π¦
I mean I would just do a nativearray and index with [y*width + x]
SCD is used for filtering. So if I want to access a block at world position 10,5,1 - I need to get the region at RegionIndex (worldpos/chunksize) - then access the proper chunk then the block
@opaque ledge my guess that colliders have filters inside themπ€
so what is your scd? just a nativearray that maps region->entity etc?
Without SCD filtering you would need to use a NativeContainer - very annoying to maintain with an "infinite" world - or just literally iterate all chunks until you find the proper one you're trying to access
I don't really understand what an scd has to do with this
ok I have it easier in that my world does not need to be infinite
@opaque ledge cs PhysicsCollider collider; collider.ColliderPtr->Filter
I mean I would then just have chunk entities, they store the data in dynamic buffers and some kind of global 2d NativeArray to access the neighbor voxels of the border voxels of a chunk
hooo thanks @warped trail ^^
SCD is basically equivalent to a global container, but it's attached to the entities so you don't need to worry about maintining it - it lives and dies with the entities.
would you be so kind to show me the scd you are using? I really don't quite understand what is inside of it
It's just an int2 of the region index.
So if I want to access all chunks at a world position I divide the world position by chunksize, then I have the region index. I apply that index to a SCDFilter and it gives me all the entities in that region.
but world/chunksize gives you the chunk index or not?
Sorry I know the naming is confusing considering region and chunk both kinda mean something different in minecraft. Plus theres...the ECS meaning of chunks. And yeah
My chunks are laid out vertically in a region. So a region is any number of stacked chunks.
ah ok so by chunksize you mean how many chunks fit in one region
(per dimension)
?
In my case a chunk is a 16*16*16 set of blocks
They are stacked vertically in a region, so there could be 0 or 50 depending on the region
i think you are confusing him more and more Sarkπ
hmm the only thing I do not get is why worldsize/chunksize is region index π
Well I'll be releasing the source code before too long so you can see for yourself how it works
WorldPosition.xz / ChunkSize.xz = region index
yeah but in a 1d world, if my chunk has size 10 and my position is 23, then 23/10 = 2 is the index of the chunk
if a region would not fit 5 chunks or something and I want to know which region my position is in, I would divide by 5*10 not by 10, that is what confuses me
Thanks Druid, it lowered my raycast system to 0.11 ms from 200 ms lol
A region can fit 0 chunks or 50000000 chunks, the number of chunks in a region has no factor on the region index.
ahh now I get it
also what you mean by stacking it
ok thanks
yeah thanks very much π
you can have cs struct testSCD: ISharedComponentData { public int2 RegionIndex; } then all entities that have testSCD with value int2(1,1) in same chunk
not all entities, but entities of same archetype
All entities of the same archetype will be in the same ECS chunk, yeah
yeah I mean basically that is the idea I came to here with. I already have entities that have data (but I have it per tile, not per chunk now). I thought about using a sharedComponent as above, to sort tiles that are nearby into the same Archetype chunk
And it lets you filter based on that index, regardless of the archetype
then you can do things like give mee all entities which have SCD with value int2(1,1)
THen I know, that if I am accessing the neighboring tiles (which are saved in a DynamicBuffer<Entity> on each tile), I won't have cache misses very often, since most of the time, it will go to the same archetypechunk
You will have cache misses from accessing the entity components though since you would have to use a ComponentDataFromEntity
That's why arrays of entities should be avoided if you can
but how will you access neighboring tiles from different chunk?π€
this makes it easier, since now all tiles just store their neighors and I think about the memory layout only at the end. I don't have to write tons of code for the cases where a tile is on the border of a chunk all the time
@zenith wyvern yes, of course I need a lot of COmponentDataFromEntity, but why is that a cache miss?
if the neighboring tile is in the same archetype chunk
CDFE = random access
Your entities may be in an array, their attached component data is not in that array. It's in a chunk somewhere
yes but I have the archetype chunks s.t. most of the time CDFE will access the same chunk that the tile itself is from.
What I mean is, I have my tiles with a Neighbor DynamicBuffer. But they also have a SCD with regionID.
Then, if I access the neighbordynamic buffer, most of the time, the entity in there will have the same regionID and will be in the same archetypeChunk
btw, CDFE is slow
so I will access the chunk I am working with anyways
as second slowest thing the ecs can do
doesn't that make sense?
dont think of it as a pointer, because its much more expensive than that
@vagrant surge is it really that bad if it's predictable? I need to do another benchmark
ah ok, I was thinking of it as a pointer...
@junior fjord do not store tiles in entities. Make tilemap entities if you want ecs, at least with a bunch of tiles each
like 8x8 or similar
8x8 is 64, so you can even do some bitmask trickery with it
Yeah that's what we were just talking about
@junior fjord the issue is that it has to search where in the chunk the component data is
so its basically hashmap nation
either hashmap or binary search
yeah that is pretty much what sark recommends, I also know of that way. I just want to understand what is wrong with my way π
for learning purposes
just to give an example on my implementation of unity style ecs, and also Flecs
to get the component data for A comp on entity Et, you have to do this
ok, so if Entity would be like a pointer, my idea above would be valid, or are there more problems with it?
1: go to the global entity data array, and use entity ID as index. This gives you pointer to the chunk. world.AllEntities[entityID].chunk cache miss near guaranteed
2: from the chunk, grab archetype chunk->archetype another cache miss. (the ecs might have pointer to archetype on the allentities array tho
3: from archetype, look at its component list, and search for the component A. lets say this has a hashmap archetype->componentdeltas[A]
4: now that you have component delta, you can finally access the data by doing chunk->data[delta + index * compsize]
Your entities may be in an array, their attached component data is not in that array. It's in a chunk somewhere
@zenith wyvern I understand that. What I am talking about is, that nevertheless, the entity I am accessing will have its components very nearby, since the archetypes are sorted by region
so even though it is "random access", it will (nearly) always be random access from the same memory region
which is already in the cache
issue is the search too. THere are other ways to implement it with hashmaps everywhere, but anyway, at the absolute least, its a hashmap search + some pointer math
and btw, entities have big overhead
entity ID is 64 bits. Each entity has 32b (version) + 64b (chunk ptr) + 32b (chunk index) of overhead
and @vagrant surge to your points:
1.+2. the neighbors will most of the time be in the same chunk as the entity itself, so this is not a cache miss, the components data will be in the cache like
still gotta hashmap search + overheads
at least try to minimize it by having multiple ties per entitity
leave the 1 tile = 1 entity for the complex tiles
like a door tile, or chest, or object
so... looking at the new blog post (https://blogs.unity3d.com/2020/03/19/state-of-unity-2020-in-this-together/), it doesn't seem like there's a specific DOTS stream coming up :/
its a big mistake to try to put everything into the ECS itself. you dont have to do that
there's a roadmap thing coming at Wednesday, March 25 β Core technology and workflows
ok, so I understand it right, that memory locality is not a problem, but only the fact that Entity is kind of expensive way of pointer?
yes
so that probably covers DOTS too
its much, much more expensive
Not trying to be right or anything, just want to understand what is going on
yeah no, of course not, but that is why I am using ecs haha π
ecs is cheaper, but still has overheads. Do not use entities unless you need the features of the ecs
also ecs sucks for random access
good candidates for things to not put on the ECS are pathnodes, and tiles, or acceleration structures
if I have two entities that are interacting with eachother and I need to modify component data on both entities, what's the best way to do that? Right now I have a query in my onupdate which returns the components for the one entity, then I use entity manager to get, then set the other entity's component data. Is there a better way?
@slim nebula not really, thats the common thing everyone does
is there a way to get a reference to the component data so I don't have to set it explicitly after?
what is not common and more efficient thing to do?π€
?
@slim nebula Do you mean storing the data of the component in a system or something?
ComponentDataFromEntity
there are some crazy evil shanenigans you can do through unsafe pointers
dont do that
(but you could)
@slim nebula yes, but it won't save you any typing π Look at what the generated code does to go from chunk to component ref
can you show some examples of this shanenigans ?π
it's not that I want to save typing. I guess I just want to save performance. rather than copying to my code then copying back I guess I just want a ref so I can update directly
a real pointer
and then, before accessing, check that the entity wasnt moved
"moved"?
@slim nebula i do it with tags, when my player want to interact with something i put interact tag on that entity then check interaction condition (distance in my case) after that is true you can do your processing and remove the tag
like that the index is the same?
chunk and index is same
but perhaps there is a better way, idk, thats what i do π
with that, you might be able to lower the overhead of random access/set, but it IS crazy evil
and uses extra space
so i dont recomend it
@vagrant surge thanks
GetComponentDataFromEntity looks good too
yeah I'm not sure how much performance I'm going to need but. I want to make sure I don't design myself into a box
the way I'm handling the ghosts for NetCode is to separate the synchronized shit from the calculated shit so that I don't have this massive garbo list of crazy in the ghost authoring script
nah dont worry about the performance of GCDE
but that requires transferring data from the ghost to the real components
and vice versa for the server
GCDE?
GetComponentDataFromEntity
yeah. seems better than GetComponentData -> modify -> SetComponentData
is there a document or tutorial on where [BurstCompile] is valid? when I should use it? best practices, etc?
cant use burst on non blittable types
@dull copper did you get this error when trying out the new hybrid renderer Library\PackageCache\com.unity.rendering.hybrid@0.4.0-preview.8\Unity.Rendering.Hybrid\CopySkinnedEntityDataToRenderEntity.cs(16,26): error CS0246: The type or namespace name 'RenderMeshSystemV2' could not be found (are you missing a using directive or an assembly reference?)
!wait sorry nevermind i forgot latest srp is needed
is that the only restriction? I can put it on any class and the whole class/struct will faster?
ok, did pretty much the most simple test case I could come up with - incrementing a float every frame across 10mil entities - burst on, safety checks off - linear access: 44ms. cdfe: 280ms. I think it's useful to have the numbers in mind at any rate. In theory this is best-case scenario for cdfe I think as it's entirely predictable. ||```cs
using System.Collections;
using System.Collections.Generic;
using System.Timers;
using Unity.Collections;
using Unity.Entities;
using UnityEngine;
public class TestGroup1 : ComponentSystemGroup { };
[UpdateAfter(typeof(TestGroup1))]
public class TestGroup2 : ComponentSystemGroup { };
public struct SomeTag : IComponentData { };
public struct Test : IComponentData
{
public float Value;
}
[UpdateInGroup(typeof(TestGroup1))]
public class TestSystem : SystemBase
{
public NativeArray<Entity> AllEntities;
protected override void OnCreate()
{
AllEntities = new NativeArray<Entity>(10000000, Allocator.Persistent);
var arch = EntityManager.CreateArchetype(typeof(SomeTag), typeof(Test));
EntityManager.CreateEntity(arch, AllEntities);
}
protected override void OnUpdate()
{
Entities.ForEach((ref Entity e, ref Test t) =>
{
t.Value += 0.1f;
}).ScheduleParallel();
}
}
[UpdateInGroup(typeof(TestGroup2))]
public class TestSystem2 : SystemBase
{
protected override void OnUpdate()
{
ComponentDataFromEntity<Test> tests = GetComponentDataFromEntity<Test>(false);
Entities
.WithAll<SomeTag>()
.WithNativeDisableParallelForRestriction(tests)
.ForEach((ref Entity e) =>
{
tests[e] = new Test() { Value = tests[e].Value + 0.1f };
}).ScheduleParallel();
}
}
@safe lintel you have to download source from github
sorry - thought I put spoiler tags round that
thanks, forgot about that π
@slim nebula burst package docs can probably give you more info on restrictions
I'm lookin at that but it's confusing. is burst only for jobs?
does it not work on systems?
it is for jobs and function pointersπ
The idea is that systems do light work to prepare data and build a job graph, where all the heavy lifting happens
function pointers ok
so in theory you shouldn't need Burst in systems π
@safe lintel did you get it running on beta 2?
i forgot it needed the srp from github and am too lazy to clone it/import it all for my project right now π
I asked if we still need b3 on the forums but no reply yet
it does seem functional at first glance when using b2
i saw b2 and got all excited
well, it doesn't break in all directions on b2 for me like it did on b1
The issue has been reported multiple times - iirc it was an issue in the editor side and it was marked benign π€
Well the last time I saw a thread post on it was in 2019 π€
Leak Detection Full Stack Traces?
I saw some similar ones with ppl talking about that error in regards to specific code of theirs, but it didn't seem similar to what I was doing
I mean
I tried that but it doesn't change the stack trace output
log is still the same
Yea - I forget which part was causing the warning - at some point I stopped seeing it consistently
when I add large amounts of logging it goes away rofl. seems to be some timing issue I guess?
possibly
once your game actually does something then it's maybe not a problem?
rofl
ok
well I'll stop worrying about it I guess
just annoying cause I have to turn warnings off
then I dont see other warnings that I want
is there a way to filter the log?
either runtime or in the editor?
i got those errors from Physics debugdraw
Not that I know of, probably some other console editor asset might have that capability
i updated SimulationsSystemGroup in fixed timesteps and there was more than 5 frames between updates of SSG π
SimulationsSystemGroup
ah
all this names are so long
yeah
80 characters is not enough π
at Unity.Entities.EntityRemapUtility.PatchEntityInBoxedType (System.Object container, Unity.Entities.EntityRemapUtility+EntityRemapInfo* remapInfo)```
Guess you can't add component objects in subscene entities via conversion system π
hmm An asset is marked with HideFlags.DontSave but is included in the build: Asset: 'Assets/Resources/Settings/Build/Hybrid.buildpipeline'
ok note to self - build pipeline file doesnt like being inside the resources folder π
@digital scarab is there a way to load in a SubScene from Addressable yet?
ok, thank you.
addressables being dead on arrival
I kept asking about ECS support on addressables while it was on early preview
the answer used to be it's going to be supported once addressables release
now it's out and not much changed π
this was all long before Unity used DOTS term btw
new physics package, doesnt appear to be on pacman yet
I have this code
private EntityQuery defenderThreatTablesQuery;
private EntityQuery attackerThreatTablesQuery;
protected override void OnCreate()
{
RequireSingletonForUpdate<GameState_Encounter>();
defenderThreatTablesQuery = GetEntityQuery(typeof(DefenderThreatMasterTableTag), typeof(ThreatMasterTable));
attackerThreatTablesQuery = GetEntityQuery(typeof(AttackerThreatMasterTableTag), typeof(ThreatMasterTable));
}
protected override void OnUpdate()
{
var defenderThreatEntity = defenderThreatTablesQuery.GetSingletonEntity();
var attackerThreatEntity = attackerThreatTablesQuery.GetSingletonEntity();
var attackerThreatTable = EntityManager.GetBuffer<ThreatMasterTable>(attackerThreatEntity);
var defenderThreatTable = EntityManager.GetBuffer<ThreatMasterTable>(defenderThreatEntity);
}
after that my job comes but it gives an error
"nvalidOperationException: The writable NativeArray <>c__DisplayClass_EncounterShipThreatUpdate.JobData.defenderThreatTable is the same NativeArray as <>c__DisplayClass_EncounterShipThreatUpdate.JobData.attackerThreatTable, two NativeArrays may not be the same (aliasing)."
well i will just change it to normal approach instead of Sark's π€·
is there a way to use subscene more than once in scene?
without duplication of referenced by subscene unity scene
Just uh, create a new sub scene
@dull copper physics new update π
new havok package too
## [Unity Physics 0.3.1-preview] - 2020-03-19
### Upgrade guide
* User implemented query collectors (`ICollector<T>`) may no longer work. The reason is that `ICollector<T>.TransformNewHits()` was removed. To get the collectors working again, move all logic from
`ICollector<T>.TransformNewHits()` to `ICollector<T>.AddHit()`. All the information is now available in `ICollector<T>.AddHit()`. Also, `IQueryResult.Transform()` was removed, and user implementations of it will not get called anywhere in the engine.
### Changes
* Dependencies
* Updated Burst from `1.3.0-preview.3` to `1.3.0-preview.7`
* Run-Time API
* The following properties are added to `IQueryResult` interface:
* `RigidBodyIndex`
* `ColliderKey`
* `Entity`
* `ICollector.AddHit()` now has all the information ready to perform custom logic, instead of waiting for TransformNewHits().
* Removed `Transform()` from `IQueryResult` interface and from all its implementations.
* Removed both `TransformNewHits()` methods from `ICollector` interface and from all its implementations. All the information is now ready in `ICollector.AddHit()`.
* Authoring/Conversion API
* Run-Time Behavior
* Authoring/Conversion Behavior
### Fixes
* Setting `Collider.Filter` now increments the header version so that the simulation backends can recognise the change.
* Asking for collision/trigger events in scenes with no dynamic bodies no longer throws errors.
* Updated to new version of Burst, which fixes a regression that caused `ConvexCollider.Create()` to produce hulls with a very small bevel radius.
* DOTS Run-time failures due to multiple inheritance of jobs have now been fixed.
* Changed `Math.IsNormalized` to use a larger tolerance when comparing float3 length.```
## [Havok Physics 0.2.1-preview] - 2020-03-19
### Fixed
- Changing motion type of many bodies in a single frame no longer results in a crash.
- Trigger events are now consistently raised for penetrating bodies.
- Asking for collision/trigger events in scenes with no dynamic bodies no longer throws errors.
- Android ARM64 and ARMv7 can now be built together without any special actions. Android-specific instructions are removed from [Supported platforms](Documentation~/platforms.md).
where can I find changelog for new unity physics
besides here? π€
where here?
two messages up
I'm dum sorry please hold my hand
oh I thought that was havok because I didn't read
ignore me
changelogs are always part of the package
they'll update the online changelogs shortly after the release
Do you guys know why translation is NaN? After Instantiate the gameObject to a scene, which is attached ConvertToEntity and should be convert to entity after Instantiate .
are you using multiple physics shape or colliders ?
are you using multiple physics shape or colliders ?
@opaque ledge No, Only using one physics shape and one physics body per entity. And no unity collider on it.
can you check what PhysicMass Transform field shows when its converted?
are you using multiple physics shape or colliders ?
@opaque ledge Oh, it does the problem with physics body or collider. I turn them off and the translation is ok
maybe it is the problem that I spawn two entities in a same position
yeah most likely
i had an issue a few hours ago, was wondering if you had the same
but your suggestion sounds more logical
An updated version of the Physics Samples is also out. We have removed LWRP package dependency to reduce the complexity of the package.
why they are not using SystemBase in samplesπ€
why the advanced physics samples are still using the first quick setup they made that's a) totally hacky b) bad example for people trying to learn these things
that vehicle scene bugs me especially
afaik, these physics samples were quite quickly done initially and they haven't really revisited them for making them more like proper samples
I talked a bit about this with the Havok guy at last Unite, but it doesn't seem to be a priority atm
people who make more complex physics setups would benefit from better dots physics examples
instead of making each user experiment and figure things on their own
Has anyone successfully despawned entities inside a ICollisionEventsJob?
hi everyone, I find myself needing to access IComponentData from the player Entity all over my code, and I end up with things like the code below, which seems really bad practice. What can I do to stop creating all these sync points and reduce the code clutter?
NativeArray<Entity> playerArray = playerEntityQuery.ToEntityArray(Allocator.TempJob, out inputDeps);
inputDeps.Complete();
if (playerArray.Length != 1)
{
playerArray.Dispose();
UnityEngine.Debug.LogWarning("Could not find player");
return inputDeps;
}
Translation playerTranslation = EntityManager.GetComponentData<Translation>(playerArray[0]);
float3 playerPosition = playerTranslation.Value;
AIHomingJob job = new AIHomingJob
{
PlayerPosition = playerPosition,
HomingRangeSq = settingsStorageSystem.AISettings.AIHomingRangeSq
};
playerArray.Dispose();
return job.Schedule(this, inputDeps);
^^^ YUK! All help for me to escape from this bad bad bad code would be most welcome! π
RequireSingletonForUpdate<Player>() in OnCreate gets rid of the whole playerArray.Length != 1 section
that would mean making the player a singleton entity I assume
GetSingletonEntity<Player>() lets you get the entity without scheduling a job (or allocating)
well, since you are checking that playerArray.Length is 1 I assume you only have 1 player π
yeah I'm kinda having to do that because it's the only way I could prototype it. I won't be doing MP for this project but the next one based on it has a good chance of multiple player entities
Thanks @worldly pulsar I'll see about how it would affect my implementation as it stands to change over to a singleton entity
and you can do something like cs var arr = playerArray.ToComponentDataArrayAsync<Translation>(Allocator.TempJob, out var jh);
and than pass this native array to your job
if I have to get the playerArray like now it's basically meaning a sync point in every system where I need that reference isn't it - is this avoided with the GetSingletonEntity route?
i guess noπ€
this must be a very common scenario - systems for a variety of things around the game requiring data (eg position or other state) from a different entity, how do you deal with this?
This is not a structural change, so it will only sync the jobs that write to Translation
assuming you use the full dependency automagic, and not the USE_SIMPLE_SYSTEM_DEPENDENCIES (don't remember the actual name of that symbol)
Do all your enemies need the players position? if so, you should probably use a SharedComponent instead, and then have the player's system set that shared component instead
I'm not using any such preprocessor symbol!
Another approach is to save the entity in a component and use the GetComponent<T>(Entity) method
Generally you want to save the data you need in components
all the data are in components on the player entity, do you mean store a reference to the player entity?
Yes
you should probably use a SharedComponent instead
I really don't think this is a good idea
Either that, or have the player's system set the value of some components
For example, have a system that first gets the player position, and then sets some component on your enemies with that players position (if you need the position) on the components that needs it
full on cheese method would be for one of the player systems to write out the various bits of data I need to publicly exposed properties on the system, but that violates so many core principles of common decency it's not even funny
Pseudo code
NativeArray<float3> playerPos = new...;
Entities.Foreach((int index, in Player player, in Translation trans) =>
{
playerPos[index] = trans.Value;
}
Entities.ForEach((ref ComponentThatNeedsPlayerPos comp) =>
{
comp.playerPos = playerPos[0];
}
Or whatever
I can't find any API docs for that @warped trail ?
Isn't that essentially the same as Entities.ForEach though?
Haven't used it before
Ohh, I see
i think this is exactly the tool for that
you are creating IJobChunk with 3 iterators
got a link to the docs for that? google isn't bringing anything up with that name
EntityQuery playerQuery = // Some query that gets the player
NativeArray<Translation> playerPos = playerQuery.ToComponentDataArray<Translation>(...);
Entities.ForEach((ref ComponentThatNeedsPlayerPos comp) =>
{
comp.playerPos = playerPos[0];
}
There's some stuff here
You can also use it directly in the systems of course
ToComponentDataArray is the same as ToComponentDataArrayAsync
okay the async part was throwing me off
ToComponentDataArray creates a job and completes it
π
Man this gametorrahod knows so much, but the English in there is so bad π¦
I wonder who this person is π€
mmm maybe async is in a newer version, I don't have that extension method
they just created explicit methods for ToEntityArray(Allocator, out jobHandle);
this ToEntityArray(Allocator, out jobHandle) became ToEntityArrayAsync(Allocator, out jobHandle)
you can read 0.6.0 changelogs
mmh type must be a reference type to use it...
?π€
I'll leave that until I next upgrade Unity.Entities! It doesn't seem to like having any struct that implements IComponentData as the type for entityQuery.ToComponentDataArray<T>(); for some reason!
ahm but T has to be IComponentDataπ€
oh, it returns a list of all components of all component types from the entity query?!
it returns a copy of all components of type T from query. If you have 100 entities in your query .ToComponentDataArray<Translataion>() will return NativeArray<Translation> with length 100
https://gametorrahod.com/minimum-main-thread-block-with-out-jobhandle-overload/ good read about ToComponentDataArrayπ
when I type ToComponentDataArray<Translation>() I get an error saying that the type needs to derive from class and implement IComponentData... maybe they updated it in the newer version to work with structs
but thank you for the links and advice! Very helpful (I need to upgrade soon, but have a mini deadline tomorrow so not now!)
yeah that looks awesome, it clearly says struct there but at least in the version I have it requires class, which clearly none of my IComponentData structs are because I'm not a monster!
Oh christ it's overloaded with the struct version... thank you I am so dumb
but you need this one cs var array = query.ToComponentDataArrayAsync<Translation>(Allocator.TempJob, out var jobHandle);
that's not in 0.5.1
oh
so yeah I'll wait until after the crunch to update
ToComponentDataArray<Translation>(Allocator.TempJob, out var jobHandle);```
this one then π
but it's bookmarked, thank you (yeah I'll try that with the jobhandle that way)
they just renamed overloaded function
π
basically you can change this```cs
NativeArray<Entity> playerArray = playerEntityQuery.ToEntityArray(Allocator.TempJob, out inputDeps);
inputDeps.Complete();
if (playerArray.Length != 1)
{
playerArray.Dispose();
UnityEngine.Debug.LogWarning("Could not find player");
return inputDeps;
}
Translation playerTranslation = EntityManager.GetComponentData<Translation>(playerArray[0]);
float3 playerPosition = playerTranslation.Value; to thiscs
var playerPosArr = playerEntityQuery.ToComponentDataArray<Translation>(Allocator.TemJob, out var jh);
yup, already done and working, thanks man that's so much tidier!!
and don't forget to combine dependencies π
so I need to dispose of the array, which means calling complete on the homingjob then disposing - this is what I have now have I been triple dumb? This seems to work fine but I'm all about learning from my mistakes :D
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var translations = playerEntityQuery.ToComponentDataArray<Translation>(Allocator.TempJob, out inputDeps);
AIHomingJob job = new AIHomingJob {
PlayerPositions = translations,
HomingRangeSq = settingsStorageSystem.AISettings.AIHomingRangeSq
};
inputDeps = job.Schedule(this, inputDeps);
inputDeps.Complete();
translations.Dispose();
return inputDeps;
}
ooo so yes to triple dumb this is golden
at least you can do this in recent version of collections π
yup same here, so just
return array.Dispose(handle);
```?
yeah
grand, works a treat! Got a few of those cases to clear up, that's going to make some of my code a lot clearer now, thank you
and i think you have to change this cs ToComponentDataArray<Translation>(Allocator.TempJob, out inputDeps) into this cs ToComponentDataArray<Translation>(Allocator.TempJob, out var jh); inputDeps = JobHandle.CombineDependencies(jh, inputDeps); π€
that seems to be equivalent - they're both working at least
isn't this out inputDeps just replaces inputDeps?
yeah I don't know if it needs a new handle tbh...
I mean, it works fine π
even
inputDeps = JobHandle.CombineDependencies(job.Schedule(this, inputDeps), inputDeps);
``` works and that's just hilariously weird
but you have all your previous dependencies in inputDeps
yeah that just makes it all linear doesn't it... good point I'll make a new jobhandle
and out inputDeps just throws them away
so:
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var translations = playerEntityQuery.ToComponentDataArray<Translation>(Allocator.TempJob, out JobHandle translationHandle);
inputDeps = JobHandle.CombineDependencies(translationHandle, inputDeps);
AIHomingJob job = new AIHomingJob {
PlayerPositions = translations,
HomingRangeSq = settingsStorageSystem.AISettings.AIHomingRangeSq
};
JobHandle homingJobHandle = job.Schedule(this, inputDeps);
inputDeps = JobHandle.CombineDependencies(homingJobHandle, inputDeps);
return translations.Dispose(inputDeps);
}
this is unnecessary cs JobHandle homingJobHandle = job.Schedule(this, inputDeps); inputDeps = JobHandle.CombineDependencies(homingJobHandle, inputDeps);
justcs inputDeps = job.Schedule(this, inputDeps)
ahh yeah the scehdule combines doesn't it
DOH
it's a wonder I manage to get dressed most days
just a note, you should probably be transitioning to SystemBase over JobComponentSystem
i'm looking to have one collection (on a component) where sometimes i want to get each element per byte but sometimes less than a byte (e.g. when max needed is 16 go per half byte)
could do a DynamicBuffer<byte> and do bitwise ops on that, but maybe there is a better way?
i noticed there is a UnsafeBitArray in collections, would that be better suited?
Getting stronger everyday πͺ
Looking very nice! Great to see a more "real" project with DOTS
I'm not sure if I should use full DOTS if I only have around 10 gameobjects per scene (ignoring UI gameobjects)
It's up to how you design things
Even in my Minecraft gamemode it only has currently 50 or so entities, but it was very easy to write in about two hours
The monobehavior equivalent would've took double and likely not networked like this one
Ignoring performance
huh, still some things that I am confused on about Entities, such as does DontDestroyOnLoad still work? and what about empty gameobjects with scripts on them?
Yes it does, I use don't destroy on all gameobjects that are managed by entities
Empty gameobjects are fine, all my UI is basically that
How do entities even interact with scenes?
As much as you want
So entities won't be unloaded if I unload the scene they were originally in?
Hm. I guess I could try and learn some of Entities by converting my Player into a Entity.
You can use AddComponentObject to attach monobehavior and unity components directly to a entity and process then like a regular ecs component data
If you are creating a entities sub scene then yes, but all other created entities are not tied to one and are not deleted unless you say so @bright sentinel
Well, I do want to learn Entities so
They are global/don't destroy by default which makes a lot of sense
Only thing I'm unsure of is, if its worth it
That's hard to say as it's team, project, developer centric
Can only talk about personal experience
Yep
He's there one that convinced me to start on ecs after he started in early 2018
RTS are such a natural fit for ecs
I guess it is hard to say if its worth it but would you recommend using it?
Yes 100%
Almost two years of using it and I thought it would be a waste of time, and a gamble to switch to on my young project
Instead it ended up being a solid sane framework, and one thing that's not mentioned too much is the fact you can do massive optimization way later on
battle royales are a great fit, because you have 100s of basically everything
That combined with the fact you can replace any system with better processes is so nice for updating core bits
@low tangle yup. You can turn one system into a highly optimized one later
Currently I'm in my 3rd year of CS undergrad, and I started learning DOTS but literally gave up after a couple of weeks because I simply couldn't understand the flow.
its one of the main features of data-oriented design, it works very well with optimization potential
@dusty scarab read the data-oriented-design book
There's a book?
Like my download and asset streaming system has been patched for bugs over and over for the last year
not about DOTS, but about the same "design ideas"
Yeah read the book
btw its a free book online
my main interest on ECS isn't ECS itself (I'd just use burst + jobs) but I need the new physics quite badly with full source access
It's great for getting your head around this kind of data is everything flow
if Unitys physx integration sources were on my hands, I wouldn't even bother
Things that are weird like, doing lod on logic
(that being said, I've already used Bullet for physics in past)
erm this ? http://www.dataorienteddesign.com/dodbook/
Data-Oriented Design
Yep
allright thanks!
the paid book has a bit of extra content, but that web version is like 90%
500 units in a group? Delete them, delete their meshes, delete their physics. Spawn single combined unit entity for the whole group
the book talks about it on the whole "level of detail but for logic" stuff
one of the fun things on ECS, is that you can have a background "offline" world, and migrate things
You can do stuff like that because you can cross cut and observe anything
so when a NPC is far from you, you move him into this background shadow world
like a subscene?
and just spawn an entity that does distance check to recover
and when the player gets closer, you swap it with the entity in the shadow realm
Yeah and if you were memory constrained, or just have a ton. You can even unload and compress the units data until he's needed again
One question, in this shadow world concept, you only don't only render it right? Because if it moves to a viewable area you need the details on it. And then just render it again
It's a just a chunk of data you want to save
It's not a object that you can render on
The world you store it in might not even have systems
When the npc becomes visible, you spawn all the peices that make up that unit then, which includes the meshes with transforms
I'm currently using Jobs and Burst, I guess it would be a good idea to add some of Entities in there too
erm lemme ask with an example. Like on a multiplayer map A and B are really far away from each other. So, you just don't render A on B and vice versa. So, for any of them to render, you need a system to check whether the systems on A and B move them to a visible area. So, When swapping the visible entity with the one in the shadow world you keep the systems alive
so the only difference with normal way is you don't render it
The systems are only running when there is units they care about to work on
Your render systems don't care that there's a unit that is disabled for rendering, instead, that unit doesn't even have rendering stuff at all and was never even looked at in the first place
I see, because only the components required are seen, not the ones disabled
When the unit becomes visible, is when the unit the rendering system cares about is spawned in the first place
@dusty scarab first of all, turning entities "off" is super easy
just add some sort of Disabled tag to it
but then you need to make sure your systems dont iterate Disabled tag
i think unity already has something like that?
but not sure if its automatic
Prefab is too and it has the added effect of getting stripped if you . instantiate it
Switching the world would be the same right? Just add another tag
not exactly
Those are more implementation details than the logic I was trying to explain
The database he mentions in that book is exactly what the unity entity query system gives you. And when he mentions building look up tables for storting on creation or transformation, that can be achieved with a system state component
So far everything I've needed from that book has a easy parallel in dots
okay, I get some of that. "When the unit becomes visible, is when the unit the rendering system cares about is spawned in the first place" This line actually makes a lot of sense now.
I can write up a simple psudo code for it if that would help
Just need to get to the pc
Don't bother, I'm just trying to understand the concept right now, will make a second attempt at dots programming soon, the first one didn't go so well. I got the CodeMonkey tutorials working and the Pong game by Unity but as soon as I needed to write something by my self the ship crashed :/
yeah those are good
they are super simple, and they are "modern" made
for example the tiny racer one is pretty good
@dusty scarab you need to figure out a lot on your own atm and unity's ecs is still at stage where you constantly need to relearn their systems as they keep changing the API
highly suggest reading the DoD book though
it's been like this for years now
and very poor editor support
well the base level api hasn't really changed much
its still just crud on entities when it comes down to it
yeah, don't get me started on the conversion workflow
the job api is the one that keeps getting changed
it's my least favorite thing about this all
tfw entitas still does it better
yeah I dont do anything with the conversion workflow
Erm, tbh, when I was doing it, I didn't run much into problems with API as VS usually showed me what was depreciated and I changed it accordingly
built my own hybrid systems a long time ago when inject was added because I didnt like that either
@dusty scarab what I mean, the api keeps evolving all the time
honestly i learnt ECS by making an actual real project (commercial!!) on unity with entitas
if you learned this like year ago, your code would look TOTALLY different
and well, tons of random experiments outside of unity
yeah let me pull up a system from early dots
current core ecs is super nice compared to the old setups
I'm not complaining about that at all
it's getting simpler every moment
it's just we desperately need better tooling and more robust workflows for getting things on ECS side if you do hybrid
they needed to just port the rest of rendering
thank god they are
its semi hybrid
like lights in megacity
if it worked like entitas does, you would see a lot more people using unity ecs to optimize stuff on their normal games
its always felt like a isolated team working on their own engine, trying not to rock the boat
it also feels like me like they dont want hybrid to be a thing
yep
because adding entitas style stuff would be trivial
but they dont
so thats a specific decision where they decided they dont want to do that
thank god they didn't take away what they gave us early on
AddComponentObject and TransformAccessArray
current core ecs is super nice compared to the old setups agree 100%, i've been converting a bunch of my old systems to SystemBase/Entities.ForEach/Jobs.WithCode and its really quite nice, it just works.
yeah, it also helps on code readability with all that boilerplate out of the way
yeah I didn't like them at first for how buggy they were, but deleting 100s of lines of bolierplate off each system is great
sucks that jobforeach is going away
means I gotta port a bunch of old systems that are a year old
I really hope .WithRequireForUpdate(ref query) comes in soon
its the only thing I use OnCreate for now 99% of the time
that and caching World.GetExistingSystem
Do you have complex queries? i just tested a system with just an Entities.ForEach and it properly doesn't execute the system unless an entity exists; so that was half of my OnCreate/RequireForUpdate code gone.
talking about the systems that first hashmap or gather up some data from other entities, when you start splitting entities instead of fat archetypes you do this a lot
you only want them to run on the actual entites it processes, not the required extra data
if that other data exists, the system always runs unless you throw the require on the main query
ahh yep, makes sense.
SystemBase is the newest system type right?
yes
Added HasComponent/GetComponent/SetComponent methods that streamline access to components through entities when using the SystemBase class. These methods call through to EntityManager methods when in OnUpdate code and codegen access through ComponentDataFromEntity when inside of Entities.ForEach.
yeah that must be it
you get rid of passing the dependencies manually on it
I think it does
you get rid of that horrible EBBBCCC stuff
at least I converted one such system for the new thing and it worked
no, there is no buffer version yet
huh?
there is no buffer version of Has/Get/SetComponent
Yeah, you use GetBufferFromEntity for buffers
Few slightly annoying limitations as well.. not sure if it's overall types but I couldn't do more than 3 types in .WithNone<> the other day
I was referring to being able to do systembase with entities.foreach that has dynamic buffers in it
you can chain the .WithNone's though
i think you can still put multiple WithAll/None/Any
fluent queries let you do that
only filter is limited to 2
Managed components are now stored in a way that will generate less GC allocations when entities change archetype.
thats nice
thanks for the help guys
time to get to work
just converted this system, https://gist.github.com/jeffvella/7fde48dd2582db7820354cc3e02f73bb tidied it up real nice!
wouldn't it be better to split this system to 3?π€
maybe, but i already have about 50 systems, i think this makes sense because i have two different inputs that can create a score, and this system is the only place that handles claculating the score and producing score events.
you have 3 different queries in system, and you are scheduling 3 jobs even if there is only 1 active queryπ€
two jobs, the third is a shared method they're calling. But thats true i hadn't considered that update would run if either job query matches.
are you using Tertle's event system ?
nah, i'm writing my own
hooo, sounds nice
hows the performance against normal event entities
its pretty good, the bottlenecks are mostly EntityManager.DestroyEntities/CreateEntities. if i could find a fast way to get access to the lower level methods it would be nice.
using batch operations can be much faster
tho i think you probably already do it
a better idea is to not use event entities unless you need the very complex features that can have, and just have normal boring old event queue
the query overloads only seem to get faster after about 1000 entities, before that NativeArray<Entity> is much faster (for destroy). You'd think CreateChunk would be better for creation but its not running through a burst path and CreateEntities(archetype/count) is just bad compared to CreatEntities(archetype,/NativeArray)
interesting
hmm is that the perfomance testing api package? π
yep!
How would I convert a float[][,] to something something Native?
or a float[,] in general?
NativeArray<float>?
You'd be flat mapping the 2d array into a 1d array since [,] assumes that all rows are the same length - it just means you'd have an array of (# of rows) * row_length
int i = x + y * max_x + z * max_x * max_y
int x = i % max_x ;
int y = ( i / max_x ) % max_y ;
int z = i / ( max_x * max_y );
public static int GetIndex(int x, int y, int z, int3 size)
{
if (x < 0 || x >= size.x) return -1;
if (y < 0 || y >= size.y) return -1;
if (z < 0 || z >= size.z) return -1;
return (size.x * size.y * z) + (size.x * y) + x;
}
whoops totally didn't read the whole float[][,] syntax
@low tangle So, I should just have a NativeArray<float> and use that?
like, flatten the float[][,] into NativeArray<float>
this is just for a 3d array indexing into 1d
Using
collisionWorld.CalculateDistance(distanceInput, ref hits)
i get a lot of entries in hits, most of them belong to the same body. Do i have to calculate the unique bodies and their nearest point manually or is there a mechanism for that somewhere?
Basically i want to get all bodies within a certain range, but without creating a collider for a collidercast.
are "hits" include body index ? if so you can do Bodies[entity].entity to get the entity that hit 'something' belongs to, you can then check if that hit belongs to self or not
Why you dont want to use collider cast ?
you can use sphere collider for it i think
@silver dragon you have to manually filter out undesired collidersπ
just copy CharacterControllerAllHitsCollector<T> or CharacterControllerClosestHitCollector<T> from here https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/UnityPhysicsSamples/Assets/Demos/6. Use Cases/CharacterController/Scripts/CharacterControllerUtilities.cs
oh, they changed it a little bitπ
Distance queries easily get prohibitively expensive. Design them out if at all possible
unless it's over very short ranges
even there it's generally you pay a big hit that you don't really need to if you used collider/ray casting
so sphere cast will be cheaper than distance query?π€
Whatever is more restrictive/hits less things will be cheap. It's that using explicit shapes for the task at hand is more likely to produce fewer and more meaningful hits
I thought distance query is the same as a spherecast, just more flexible...
When using collidercast for a range query, especially if you have different ranges, do you create new colliders each cast? Can radius of sphere colliders be changed?
yesπ
but beware that you are using pointer to collider
changing radius in one place will change radius in all places that uses this colliderπ€
Seems I have to cache colliders for each radius I have. Otherwise it can't be used in parallel...
Or use distance query and filter out the points I don't need.
look at Collector.cs in Physics package, there is simple example for custom collectorsπ
Yep, there are some examples. Thx for the hint!
(theoretical) say there's some sort of runtime loading system for, I don't know, rocket parts in kerbal space program? The part configurations describe several modules (Thruster, FuelTank, etc), and the modules are made up of several Components. What's the best way to group sets of components for use in this manner, to add to an entity in blocks?
@unique mantle Going off of my KSP knowledge, they do it by parenting parts. So you have the main cockpit (or whatever your first part is) which is the root. Then it has different slots where other parts can connect, which are attached as children to the parent object in a specific slot. Those parts can in turn have childs etc.
No, parts themselves are made up of abstract modules, like a fuel tank might have a FuelTank module and a PhysicalProperties module and a Model module or something
And a FuelTank module could be made up of a lot of components
Oh I see, in ECS you'd just do that with components then.
well yeah, the question I asked was what's the best way to group multiple components into blocks
Hmm, what sort of blocks do you mean?
groups, rather, that can be added to entiteis
Oh, like prefabs?
sort of like a prefab but not a separate entity
just a thing added onto an existing entity
it's easy enough to do manually but I was just asking whether ECS has it's own system for this
since this might be a potential problem in the future
I'm stil not quite sure I understand exactly what you want. If you want an entity to have multiple components you can just add those components to the entity
Also, since often times systems and jobs use multiple components it's like you add a "MoveSpeed" component or something then wonder why it isn't going anywhere but then realize you actually need "MoveThingamagic" component for it to do anything
good for organizational purposes, so you don't forget a Component and have to do a lot of messing about to figure out why on earth your entity isn't doing anything
Well that seems like a solution could either be a prefab thing, or [RequireComponent]
components can require other components?
Well, not exactly. MonoBehaviors can require other MonoBehaviors, but if they're converted with the conversion system, then it's essentially the same thing
so that would require your own authoring component
instead of the autogenerated one
Yeah, but it's not that hard to do. Either look at some of the samples or the generated code that the autogenerated one generates
You can pretty much copy that and implement it yourself
Cool
It would be nice to sort of make Component groups that you can add to an entity as a single group, prefabs annoyingly describe a full entity which means you can't do that
You can make prefab variants
prefab variants have nothing to do with what I'm asking
And again, you can do your own custom conversion with it π
not talking about prefabs, at all, just the ability to group components and add them to an entity as a single group
instead of having to faff about with adding them manually and spending three weeks figuring out why your entity doesn't work
You could also keep those groups in a list, and then have some system automatically add those through whatever group you make
it's probably easy enough to have your own group system, yeah
also authoring scripts, I could just make a script titled "Door" that actually adds multiple components on conversion'
yep and convert them to entities, and there you go you have an entity for each 'modules', you can give them IDs to identify them
this ECS approach tought me the importance of unique IDs π
I suppose the part loading code could just add multiple components per module to the thing as well if I ran into that situation
I fail to see how multiple entities per part would help here
if your modules doesnt change on runtime you can make scriptable objects and put them into authoring component and convert them to entities
you can convert scriptableobjects into entities?
huh, that might be useful
since I was already a bit annoyed that entities had to have transform components because every converted gameobject happens to have a transform
data-only "non-physical" entities might be useful
you can also have static methods in your struct to create a the module with certain values, lets say i have a weapon and lets say pistol has 10 damage 1 fire rate, rifle has 5 damage 3 fire rate, then i could make something like, Weapon.Rifle() => return new Weapon{damage = 5, fireRate = 3} and Weapon.Pistol()=>return new Weapon{damage = 10, fireRate = 1}
but i think SO approach is better
I don't think the ability to group components and add them to an entity as a single group exists right nowπ€
you can make an Entity field and store your entity
Hello, I have a question regarding Project Tiny. Is there a way to get Mouse Wheel status within Tiny.Input namespace? Somehow I cant find anything in the docs -.-
i don't think there is scroll wheel supportπ€
at least there is no such thing in InputSystem
i'm trying to use UnsafeBitArray to set bits in an underlying ulong but result is always 0 when setting the last few bits, doesn't matter what value is passed
for example where (pos, numBits):
(32, 32) stays 0
(48, 16) stays 0
(56, 8) stays 0
even non-pow2 such as (47, 17) stays 0
but everything around it
(33, 33) is fine
31, 33) is fine
(33, 31) is fine
i can't figure out why this would happen 
maybe missing something fundamental about how bitmasks work
i tried checking the underlying code and it's not long but it reads like arcane magic to me
i tried checking the underlying code and it's not long but it reads like arcane magic to me
Happens to me everytime I read someone elses code lol
@warped trail Ah ... I was afraid that might be the case ... and there is probably no other way how to get some mouse wheel inputs right?
@autumn pond π€·ββοΈ
https://hatebin.com/luokldyltn
is the implementation in case anyone wants to have a look
not sure how the numbers work (they are literally just num1 num2 etc)
Can I directly set variable inside of a dynamic buffer element?
Without insertion and removal of elements
is there a way to check if an entity already has dynamic buffer added? Something like null check?
@autumn pond there is this thingcs var bfe = GetBufferFromEntity<TestBuffer>(); bool hasBuffer = bfe.Exists(entity);
ah, will check that right out, thanks!
@warped trail That seems to be working, thanks!
do I understand it right that an ecb already gives me back the entity and I can immeadiatly use it to save it somewher? (just the actual creation of the components etc takes time)
yeah the entity id gets remapped when the buffer system plays back
but you can't do this? π€ cs var instance = ecb.instantiate(index, spawnerFromEntity.Prefab); spawnerFromEntity.ChildEntity = intance
Yeah the entity you get back from ECB is not valid outside that scope
You need to get the updated entity reference after the command buffer plays back
but if you store it somewhere through ecb it will be fixed? π€
No, if you try to store the entity you get from ecb.createentity or ecb.instantiate, it won't work
You can do all the ecb operations on it like add/set components, etc, but you can't store a reference to it
hmπ€
do I understand it right that an ecb already gives me back the entity and I can immeadiatly use it to save it somewher? (just the actual creation of the components etc takes time)
@junior fjord
You can't save it anywhere
I'm not sure if you do it on the main thread like that, but if you do it in a job then the reference is garbage
Try creating the reference in a job then examining the entity with the reference inside the entity debugger
but you can't do this? - i think you can do that, last time i tested it (in 0.6 maybe), if you add the entity to components using the same ECB it will batch them all to the correct values as it plays back.
Maybe I was doing something wrong then, I just tried doing exactly this a few days ago in 0.8 and it didn't work. I'll have to re-check
mmm, perhaps im wrong, in his case spawnerFromEntity already exists somewhere else outside the ECB, so it can't be updated automatically. ill test it real quick.
it worksπ€
if you set it through ecb it fixes entity referenceπ€
if my test is right π
but this probably won't work right:
var e = ecb.CreateEntity
var buf = ecb.GetComponent<B>(e);
buf.ResizeUnitialized(6);
FillThisBuffer(buf);
since the buffer isn't yet created
the ecb doesn't have some kind of smart thing to give me a buffer reference to something intermediate and copy the values to the right stuff later?
Hmm, maybe that was my problem then, trying to write a reference to a dynamic buffer created at the same time
@junior fjord there is no methods like this ecb.GetComponent<B>(e);
@zenith wyvern i recall June said that ecb does not like buffersπ€
yeah exactly because of that probably, the buffer reference is not valid
where should it point
That really sucks, I need to add a new entity to a LinkedEntityGroup and it wasn't working, I guess that's why
Good to know that it works with a non buffer though
I now circumvented using the ecb by doing all work I can in another parallel system that just creates "command" entities and then one system that only runs through the command entities and does the entity creation and buffer stuff on the main thread
I only needed it for the case where a new tile gets flooded with water, which won't happen to often so I hope that is fine
yeah, similar to what im doing now with these event things, just need somewhere to store the buffer elements, then patch the buffer headers after creating the entity later.
but conversion system manages to fix Entity references in buffersπ€
i should stop assuming things π it does patch entity references within the buffers too https://gist.githubusercontent.com/jeffvella/9acc6681d16e8a5df15a12cd435549af/raw/db05f96802f6c07ca96cec704531d4a063abbc27/gistfile1.txt
anyone know how I'd do the equivalent of transform.up in dots?
looking at the boid samples for heading and its not clicking
Localtoworld.up
ooo love an easy solution
thanks @zenith wyvern
I was trying to do through Translation
you can do this if your entity does not have parent π€ cs math.mul(Rotation.Value, new float3(0,1,0))
I was actually thinking of doing that. I still might because I'm already querying for Rotation.
I'm doing a top-down movement system. Player clicks somewhere on a map and the player object first completely rotates to that position and THEN moves to it
having lots of trouble figuring out the rotation math
yeah ecb's handle the entity ref for you and patch it @junior fjord @warped trail
SetComponent and AddComponent that have entity refrences inside of them get patched, and yeah I think buffer adds now do as well
@fallow mason there is math.slerp(quaternion,quaternion,t)π€
hmm I will try
ah now I remember why I wasn't doing a straight lerp. I want linear rotation (but cannot easily store the starting rotation state to do so) so I have to get the angular distance somehow to do deltaTime / distance
SetComponent and AddComponent that have entity refrences inside of them get patched, and yeah I think buffer adds now do as well
@low tangle so you think thisvar e = ecb.CreateEntity var buf = ecb.GetComponent<B>(e); buf.ResizeUnitialized(6); FillThisBuffer(buf);should work?
buffer is the thing that you might run into issues with if you fill it with any entity reference that is going to be command buffered
yes that is what I also think
just junes comment sounded differently and I wanted to understand what he means
I mean since the buffer is technically a pointer, and the space has not been allocated yet, I can only think of very complicated workarounds on how to make buffer stuff work in ecb
well my solution was just to make another job for the dynamicbuffer adds once the ecb had run(basically skipping a frame), tbh i dont recall seeing anything about dynamicbuffers & ecb's that changed in the updates but id love to know if something was changed
the space is allocated
@safe lintel yeah that is what I do too
within the buffer the ecb uses
its a stretchy malloc within the thread local memory
you can memcpy to it
which I do quite often
when the ecb runs creating entitys, it patches the ecb entitys
so the ecb allocs, you can set it and then afterwards in the ecb system, it copies over what you did to the chunk?
if you look at them they have a version of 0 and a index of 1,2,3,4,5 and so on
yes
not chunk
they are a stretchy memory buffer
what do you mean by "patching" entities?
so the stitching system later on just takes the real index and looks for all entity structs within the ecbs operations
it fixes entity references in buffer π€
wait so does that test succeed?
yes
do you know which update changed this?
mmmm, good question, i am on 0.8
thanks, that is interesting
hmm I guess I could store starting rotations and positions in a nativelist
this is the code for the ecb add buffer
internal BufferHeader* AddEntityBufferCommand<T>(EntityCommandBufferChain* chain, int jobIndex, ECBCommand op,
Entity e, out int internalCapacity) where T : struct, IBufferElementData
{
var typeIndex = TypeManager.GetTypeIndex<T>();
var type = TypeManager.GetTypeInfo<T>();
var sizeNeeded = Align(sizeof(EntityBufferCommand) + type.SizeInChunk, 8);
ResetCommandBatching(chain);
var cmd = (EntityBufferCommand*) Reserve(chain, jobIndex, sizeNeeded);
cmd->Header.Header.CommandType = (int) op;
cmd->Header.Header.TotalSize = sizeNeeded;
cmd->Header.Header.SortIndex = chain->m_LastSortIndex;
cmd->Header.Entity = e;
cmd->ComponentTypeIndex = typeIndex;
cmd->ComponentSize = type.SizeInChunk;
BufferHeader* header = &cmd->BufferNode.TempBuffer;
BufferHeader.Initialize(header, type.BufferCapacity);
cmd->BufferNode.Prev = chain->m_BufferCleanupList;
chain->m_BufferCleanupList = &(cmd->BufferNode);
internalCapacity = type.BufferCapacity;
if (TypeManager.HasEntityReferences(typeIndex))
{
if (op == ECBCommand.AddBuffer)
{
Interlocked.Increment(ref m_BufferWithFixupsCount);
cmd->Header.Header.CommandType = (int) ECBCommand.AddBufferWithEntityFixUp;
}
else if (op == ECBCommand.SetBuffer)
{
Interlocked.Increment(ref m_BufferWithFixupsCount);
cmd->Header.Header.CommandType = (int) ECBCommand.SetBufferWithEntityFixUp;
}
}
return header;
}
they really reserve spacec for the the buffer and then return a pointer to that intermediate location for now.
and in playback it is probably copied over
oh can I somehow make that code expandable?
so that it doesn't block everything
@fallow mason why not just have some value like MaxRotationSpeed and then calculate if you need to rotate, rotate with MaxRotationSpeed ?
hmm but what did june mean with the fake indexes? the ecb immediatly returns the right entity index?
Did he mean that the cmd->Header.Entity here has some fake entity index for now?
ecb does not return right index
Not sure I understand. Limiting to a max speed won't change that the rotation speed varies through the rotation.
wait so if I would do
var e = ecb.CreateEntity();
myEntityMap[x, y] = e;
I would have a problem
@warped trail ?
The only way to get the linear interpolation is if the start and end rotations do not vary.
or adjust deltaTime with the inverse of remaining distance
as far as I know π€
@junior fjord https://youtu.be/SecJibpoTYw?t=874
maybe im wrong about CreateEntity, but instantiate returns negative indexπ€
yeah no I think you are right thanks
and thanks for the vid
always hard to find where to get the valuable information from, it is so scattered π
it would be very weird if CreateEntity would return a valid id and Instantiate not
I think it has something to do with it just not being possible. Funny, I would have thought that returning a valid entity id right away and then afterwards just copying the data to the right location would be easy, and making the buffers work right away would be hard
seems that it is the other way around π
ah ok yeah thanks π
@fallow mason you need to rotate in constant time or speed?π€
speed. sorry I keep conflating linear interpolation and speed.
the do return a negative index, its a placeholder. They need a placeholder because the entity doesn't actually exist until PlayBack() is called. Then they must go through and find all the Entity references you used, and replace them with the proper value.
I think I'm going to need to store starting rotations and positions. It will just make the lerp parts more straightforward.
@fallow mason something like if my rotation is not equal to desired rotation, rotate me with constant speed towards desired rotation, no ?
exactly
so i need to compare relative angle and also take the shortest path there. no rotating 270 degrees. -90
@mint iron Can you explain what's wrong here https://gist.github.com/sarkahn/7a7295e1661287204147b571a79cd881
This fails
@zenith wyvern you have to set buffer via ecb
var newA = ecb.CreateEntity(entityInQueryIndex, arch);
var buffer = ecb.SetBuffer<LinkedEntityGroup>(entity);
buffer.Add(new LinkedEntityGroup{...})```
Ohh, so I can't use the buffer I pass into the lambda?
i guess noπ€
Huh, you were right, that works
That's going to save me a huge headache, thank you
Very strange that it doesn't work with the normal buffer, but I'll just take it as a necessary evil
@fallow mason you can use cross product do determine +- of rotation
oh, not cross product, dotπ
direction to your target with local right vector
@zenith wyvern you can check the youtube link that druid posted above, it does not work with the normal buffer because newA is not a valid Entity yet, it is just a placeholder
I will do that, thanks
The API naming for that is kinda weird though, they called it "SetBuffer" but you're getting back the buffer that you're operating on
Not sure what would be better but that doesn't feel right
there is AddBuffer too π
but yeah it is confusing, i was expecting something like cs ecb.SetBuffer(entity, new BufferElement{...})
Exactly. I feel like at least they should let you change the existing buffer then pass it in, but even that is kinda confusing since you're already operating on it by reference and would expect it to just work
I'm going to make a thread about it
why is there actually so little show off in this channel? I would really like to see what other people are doing/did with dots already
i don't think there is a lot of stuff π
I usually only post show off stuff to the forum
your account is sarkhan probably?
@warped trail I even mean small stuff
like just a gif of something cool that is working π
I really like to see that kind of stuff, somehow it always motivates me
especially if its something cool that can inspire you
there is RTY project going on, i think its pinned on forums, you can check that out π
I got something that's not working lol
blue is "forward" vector, green is target direction
only 3 degrees difference lol
@fallow mason math operates with radiansπ€
I know, I know. Still, not 3.2 radians there.
how are you calculating angle?
this is just for my authoring monobehaviour so I can have some gizmos, so it's not what I've been trying recently for my system
private void OnDrawGizmos()
{
Debug.DrawLine(transform.position, new Vector3(Value.x, Value.y, transform.position.z), Color.green);
Debug.DrawLine(transform.localPosition, transform.localPosition+transform.up * 2, Color.blue);
Handles.Label(transform.position + (transform.up * .9f) + (transform.right * .5f), string.Format("{0}Β°", Quaternion.Angle(transform.rotation,Quaternion.Euler(transform.position-new Vector3(Value.x, Value.y, transform.position.z)))));
}```
@opaque ledge rty?
it is mobile game, no? π€
Well, other than that i am working on a project as well, buts its on very early stages π
by eizenhorn or something? that is not a mobile I think
i also know of someone that published a game using DOTS, but not sure if he like to have his name around
yeah but the kind of gifs where you just see that finally the 100 spaceships are following their leader or stuff can be cool too π even if it is just to start off a discussion on how someone did that
@fallow mason this is too complicated for me π
isnt there Vector3.Angle method?
you can just take the inverse cosinus of the dot product @fallow mason
or you can use acos(dot(A,B))
well you need to normalize it
but normilize A,B
haha yeah π
π
so arccos(dot(A, B)/(dot(A,A)*dot(B,B))^0.5)
@junior fjord if you are talking about my gif, there is no following leader, every ships gets a target and they attack it, unfortunately i have trouble about how to do aggro management, so targeting is all over the place π
haha no I did not see your gif, is it in this chat?
Can I switch to only media somehow?
that was just a random example
sorry, wrangling my 21-mo-old who I guess does not want to watch disneynature chimpanzee
oh lol, its a coincidence then π
thanks @junior fjord @warped trail I'll give that a try
@opaque ledge oh that is pretty cool
haha but yeah their strategy is optimizable π
are you using hybrid renderer or graphics.drawmesh?
hybrid renderer
is the physics stuff tied to hybrid renderer in any way? I never used physics yet
well they are all parts of DOTS, but i dont think its necessarly 'tied' to hybrid renderer
i mean they are all tied together anyway
you can use physics without the hybrid renderer
acos(dot(a,b)) to find angle, and dot(toTarget, right) to find sign
float3 dir = math.normalize(new float3(moveTarget.Value, 0f) - translation.Value);
float angle = math.acos(math.dot(dir,ltw.Up));
float sign = math.dot(dir,ltw.Up);
Debug.Log(math.degrees(angle)+" : "+ math.degrees(sign)); //101.0919 : -11.02272
moveTarget is a float2. ltw.Up is my 2d "forward" direction
I'd expect math.degrees(angle) to equal the 137 I'm seeing in my gizmo :\
if you want the direction you need to take the dot product with your "right", not your forward as druid indicated
why would that matter? woudln't it just offset by 90?
if you take the dot product with your right, then it is positive if the direction is on the right side of you, else negative
ok, well I switch to right and now my debug is 100.0683 : -10.01659
about why the angle is wrong, I don't know. Why do you subtract translation.value in the first line and use ltw.Up in the second line
your angle now changed, did you move something in the editor?
I subtract the translation position from the target position to get the direction
no I didnt move anything, just changed the ltw from Up to Right
but the first number changed too
no only the ltw.Up in the third line needs to be changed
not in the second
and I just wondered since I guessed that the position and the upwards direction are saved in the same struct and you use translation.Value for your position and ltw.Up for your upwards direction
ah and you don't need to take math.degrees sign, you are only interested in the sign of sign for now
yeah that was the impression I got. which is fine. the target angle is indeed to the left of ltw.Up.
but the angle itself is not correct
just don't know enough trig to even guess what I'm doing wrong
I'm stuck
I don't suppose anyone knows how incrementing a variable in a job by 0.001f can make the value jump in one frame from 0.04 to 0.121
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
public class MovementSystem : SystemBase
{
protected override void OnUpdate()
{
float deltaTime = Time.DeltaTime;
Entities
.WithoutBurst()
.WithNone<Cooldown>()
.ForEach((ref Rotation rotation, ref Translation translation, in LocalToWorld ltw, in Move2DTarget moveTarget) =>
{
float3 dir = math.normalize(new float3(moveTarget.Value, 0f) - translation.Value);
float angle = math.acos(math.dot(dir,ltw.Up));
float sign = math.dot(dir,ltw.Right);
Debug.Log(math.degrees(angle)+" : "+ math.degrees(sign)); //101.0919 : -11.02272
//rotation.Value = math.slerp(rotation.Value, quaternion.Euler(new float3(moveTarget.Value.xy, 0f)-translation.Value),deltaTime);
}).ScheduleParallel();
}
}
really simple system. MoveTarget only stores a float2.
@pliant pike because you are changing your floatVal all over the place π
ah ok there someone else can help better I think, I don't know how unity stores stuff in ltw and translation
but if translation.Value is your current position and ltw.up your current forward it should be right. shouldn't there be some kind of position in ltw too? I don't know what translation is
really just using ltw to get the local forward
@warped trail I'm not I'm only changing it one place 
you change you code from last time? π€
I've reduced it to one entity with one variable I'll show you the output if I can
@fallow mason wait, ltw.up is your forward?
@fallow mason hmm the code is right, I guess the problem is what is stored in translation.Value and in ltw
and I have no idea about that
I thought translation was == the position of the Transform component and ltw was the float4x4 of the TRS combo
@warped trail yes. it could just as easily be right though
not a horizontal platformer. top down. player can move in any direction on the xy plane.
but no particular need for it to be up. just how I drew the sprite really lol
I don't know if that helps to explain, timedelta is the value being increment outside the job and is correctly incremented
placeonspline is the value inside the job which I'm also incrementing in exactly the same way and getting the crazy values from
why are you incrementing delta time?
I'm just doing it as a test so I have a consistent value and can see I still get inconsistent results
can you show the code?
Wow, you are trying to work out this Spline moving for a long time now
yep, I had it working when it was only one entity that had to move
so its the Time.DeltaTime gives you an issue ? iirc you said its working fine if its on main thread?
have you tried to comment this line ?cs placeonSpline.floatVal = math.saturate(placeonSpline.floatVal);
yep, second one you mean?
and this cs placeonSpline.floatVal = math.saturate(placeonSpline.floatVal) * Curvecount; i = (int)placeonSpline.floatVal; placeonSpline.floatVal -= i; i *= 3;
@opaque ledge yeah using placeonSpline.floatVal += timeaccumalator; inside the job doesnt work
you are changine floatVal in 2 places π€
@warped trail if I remove that it just breaks it, makes it only go through one curve
but what about values?
how so?
lol components using floats are initialized as NaN, not as 0? π
I'm using the debuglog to check the floatval right after its changed
would have never expected that
placeonSpline.floatVal += timeaccumalator; thats where the problem is
yeah, but after debuglog you are changine floatVal in 3 places π
yeah you have to because you have to calculate it across a whole spline
is cs placeonSpline.floatVal += timeaccumalator;working correctly if you comment this lines ```cs
placeonSpline.floatVal = math.saturate(placeonSpline.floatVal) * Curvecount;
i = (int)placeonSpline.floatVal;
placeonSpline.floatVal -= i;
i *= 3;
placeonSpline.floatVal = math.saturate(placeonSpline.floatVal);``` ?
def not that just breaks other variables
would it be possible to make placeOnSpline less responsible for resetting when it moves to a different curve? Like keep it always a 0-1 value but have your system figure ot which curve its on?
like a 4 curve spline .25 would mean 0 on the second curve?
that's what the above code does though
@pliant pike you have to make your job not touch placeonSpline.floatVal if not necessary π€
increment placeonSpline.floatVal and make everything else use copy of that value
how
that's the whole point of placeonspline
after this line cs placeonSpline.floatVal = 1f; everything should use copy
yes, exactly what I'm talking about ^
and you will find out, that placeonSpline.floatVal is incrementing correctly π
right now placeOnSpline is operating as placeOnCurve
you mean like this ``` placeonSpline.floatVal += timeaccumalator;
var tempval = placeonSpline.floatVal;```
yes
when I check tempval its still coming up with the crazy results though
what about placeonSpline.floatVal?
that means your code is the culprit π
who knows what's the culprit I'm lost 
anyways thanks for the help guys I may have to give this one up
my bet it is this part cs placeonSpline.floatVal = math.saturate(placeonSpline.floatVal) * Curvecount; i = (int)placeonSpline.floatVal; placeonSpline.floatVal -= i; i *= 3;π
that's below where I'm taking the debug from though
in the above screenshot of debug.log it should be incrementing by 0.001 but its not
whait you printet wrong values π€
you should debug.log timedeelta and placeonSpline.floatVal
no the job is
its supposed to be adding 0.001 each loop but its jumping to 0.306 to 0.92 in one frame and then down to 0.763
so placeonSpline.floatVal += timeaccumalator; doesnt add 0.001 ?
nope π€·
wtf π
ok i tested this cs placeonSpline.floatVal = math.saturate(placeonSpline.floatVal) * Curvecount; i = (int)placeonSpline.floatVal; placeonSpline.floatVal -= i; i *= 3;
and it is not working
π€
how so π€
what placeonSpline.floatVal should be after this code is executed?
like imagine placeonspline is 0.5 that means it should be the middle of the spline
are you checking every single variable's value to see if they work correctly ?
the code you posted above does change the floatval but then it changes it back
no π
I'm pretty sure the above code does work correctly
Bezpoint2 = booked.Bezzypoint[i + 1];
Bezpoint3 = booked.Bezzypoint[i + 2];
Bezpoint4 = booked.Bezzypoint[i + 3];```
it assigns those points so its calculating the correct curve
floatVal += Time.deltaTime;
floatVal = math.saturate(floatVal) * Curvecount;
var i = (int)floatVal;
floatVal -= i;
i *= 3;
Debug.Log(floatVal);```
just check it in MB yourself
MB?
MonoBehaviour
public class TestMB : MonoBehaviour
{
float floatVal = 0;
int Curvecount = 24;
// Update is called once per frame
void Update()
{
floatVal += Time.deltaTime;
floatVal = math.saturate(floatVal) * Curvecount;
var i = (int)floatVal;
floatVal -= i;
i *= 3;
Debug.Log(floatVal);
}
}```
if I go through the value and assume floatval is 0.5 which should be in the middle of the spline then math.saturate(floatval) * curvecount = 12
var i = 12
0 -= i;
wait a minute π
but floatVal is 12
floatVal = math.saturate(floatVal) * Curvecount; //0.5 * 24 = 12; floatVal = 12;
var i = (int)floatVal;// i = 12
floatVal -= i;// floatVal = 12 - 12 = 0
i *= 3;```
-= removes 12 from the floatval
but it was 0.5 in the begining
yeah but theres sets of curves all in a spline and its calculating which spline its on
so its at the beginning of curve 36
so you just travelled from middle of your spline to the begining
which should be the middle
yeah that's because its adding curves into a group that is called a spline
and its finding each curve in that group/spline by using the above code to find exactly where it is in that group
so at floatVal = 0 you are at very begining of your spline that consists of many curves ?
at floatVal = 0.5 you are in the middle
yes
and at floatVal = 1 is the end
yes it divides that value by the number of curves basically to get exact position of where it is
but in one step you went from middle of your spline(0.5) to the very begining ( 0 )
