#archived-dots
1 messages Β· Page 191 of 1
Well it seems - so far - to work with the sharedcomponentdata indexing the native array.
I can rewrite it to use chunks if I hit another snag
Thank you!
@warm panther I may be misunderstanding but how about a e.g nativehashmap in a system that stores your entity->index map?
I'm gonna try and explain this gif so you can understand the problem:
First, I add two synapses, the first has an ID of 0 and the second has an ID of 1 to the Buffer.
What happens next is that I press the remove synapse which removes the synapse with ID 1. That also increases the 'offset' integer.
Then in some other code I try and access the synapse with ID 0, which is the only one left. But when accessing it I also subtract the ID with the offset making the number -1 which causes the error.
So, this method does not work when the synapse with ID 1 is removed. But it does work when the synapse with ID 0 is removed as when I access the synapse with ID 1 it would be subtracted by 1 which would give 0 and that would work. I just need a way to make this work in both scenarios and I'm unsure on how.
I hope I explained it fine. https://gyazo.com/3553cfb3f16398ad3bf867371e858504
I can just use a NativeArray for that, and read the value from a componentdata. I think that's equally as fast as the hashmap lookup.
Right now I wonder why my Translation values are drifting (ever so slightly, micrometer scale) ... even though nothing is modifying them, and it doesn't happen if I disable physics smoothing. which is weiiiird:
TranslationType = GetComponentTypeHandle<Translation>(true),
It shouldn't write it in SmoothMotionJob.
is a memoryref of a stack variable an okay thing to do? cs new MemoryRef<PoseSet>(ref idleCandidates),
the answer appears to be no
ofc it's not, it's the stack..
Can any one from the group answer my this question. I am searching an answer since last day.
Hi, I have spend hours in understanding if burst is supported on armeabi-v7a and arm64-v8a and what I have understood so far that it is supported on all arm64-v8a but it is not supported on all armeabi-v7a because some armeabi-v7a supports Neon32 and other do not. (I am still not 100% sure). The main question is how much % of active mobile devices in market DOES NOT SUPPORT burst compilation.
When I see Burst documentation it says it supports arm32 thumb2/neon32 and armv8 AARCH64. But when I get builds from unity for the game, it gives me armeabi-v7a and arm64-v8a. I am confused what is arm32 same as arm-v7a? Is there larger portion of arm-v7a chips which do not support Neon32? By using burst in my game, am I going to ignore a very large portion of the android devices? Any guidance would be highly appreciated.
@tulip girder arm32 = armeabi-v7a
if it doesn't support neon2 i would imagine it'd just use fallback like it does on pc
but you should test anyway
Here Android official site tells me that armeabi-v7a supports Thumb2 Instruction Set.
And Burst documentation tells me that Arm32 Thumb2 is supported.
Also we provide two apks to playstore. i.e. armeabi-v7a also. Does it mean that all armeabi-v7a will support Thumb2 hence Burst compilation? Can any one guide me. Thanks.
Or is there a considerable of portion of armeabi devices which does not support Thumb2?
void Update()
{
if (isUsingJobs)
{
for (int i = 0; i < cubeList.Count; i++)
{
_moveY[i] = cubeList[i].moveY;
_position[i] = cubeList[i].transform.position;
}
MoveCubes moveCubes = new MoveCubes
{
deltaTime = Time.deltaTime,
position = _position,
moveY = _moveY
};
JobHandle jobHandle = moveCubes.Schedule(cubeList.Count, 500);
jobHandle.Complete();
for (int i = 0; i < cubeList.Count; i++)
{
cubeList[i].moveY = _moveY[i];
cubeList[i].transform.position = _position[i];
}
}
else
{
foreach (var item in cubeList)
{
item.transform.position += new Vector3(0, item.moveY * Time.deltaTime, 0);
if (item.transform.position.y > 11 || item.transform.position.y < -11)
{
item.moveY = -item.moveY;
}
}
}
}
}
``` i am getting same result with or without using jobs, when i checked my cpu usage all 4 cores were running even when i was not using jobs ```cs
isUsingJob=false;
``` , is unity using jobs automatically?
afaik, Unity internally uses jobs.
but they dont jobify your code automatically
I assume you've used the Profiler to check what's really going on?
Profiler is always step one when debugging jobs
you should check the profiler
ngl with dots and the way tiny basically says "you cant use anything from old unity"
it really feels like they should have made DOTS its own thing from scratch
because the way hybrid (doesn't) work is very confusing and probably more confusing than it would've been as its own thing
I checked in profiler my code had nothing to do with it, I had 10000 gameobjects and they were utilizing the all 4 cores of my cpu.... Thanks for the help!
because the way hybrid (doesn't) work is very confusing and probably more confusing than it would've been as its own thing
@gusty comet
I agree with you but if we ever get to the point where conversion is less buggy and better integrated with the editor I think it will make a lot more sense why they went this direction.
Right now it's just an awkward annoying hoop to jump through
I also don't understand why we have 2 implementations of DOTS right now and have some of their components exclusive from one another. i.e. Sprites.
There are not two implementations of dots
I think I worded it wrong, but there's Tiny and Hybrid
It just boggles my mind that, considering that DOTS is very early tech, with lots of limitations. It makes Tiny even more Limited at the outset.
Tiny is a separate thing from unity, it's basically it's own engine, it just uses unity as an editor. But it still uses the exact same dots packages as normal unity
They should have a separate template setup with dots where all packages are preinstalled just like urp and hdrp
I would agree with that. It's definitely very limited right now
That would lower the entry requirements which unity obviously doesn't want.
That would be nice but they desperately wanted to get away from letting people easily install preview packages
There is even a Tiny template somewhere
Does Tiny have Components for UI? All I know that Tiny have but hybrid doesn't are Sprites.
No UI yet for tiny
We have text support in Tiny already, and we can already use Tiny 3D together with Tiny 2D (which enables us to use sprites for UI)
It is evolving pretty quickly to be honest, more than Hybrid
Is the Tiny 2d sprite render stuff pretty good? I.e. burst/jobified supporting e.g. 100k's of sprites on desktop with depth sorting? I have.. no idea so appreciate any insight into the current state.
Can Tiny accomodate, for lack of a better term, game as a service type of game? or is it meant to be casual games?
Tiny is missing a lot of parallelism yet, in a not so recent test I got the same performance moving 50k cubes in tiny as moving 1million in hybrid
most things are being bursted, but running on main thread
probably due it being focused on web right now, which lacks proper multi-threading support (but seems like it is coming in the future)
right now, I only recommend it for casual games
but I found it very easy to switch from tiny to hybrid at any time
the opposite is more complicated...
really useful, thank you. Any video playback? Wondering e.g. how suitable it is for non-game web.
nice, that gives me more confidence to stick to my guns for a bit.
only tested it for web, as it was the only reason I had to use it so far (ie. offer proper support for mobile browsers)
I would say "stick to Mono / Hybrid unless you need to support mobile browsers and you are ok with coding web stuff to integrate third parties yourself"
Yup, sorry if I wasn't clear. I was wondering about suitability for interactive content that isn't games. e.g. typical corporate world virtual room, click and launch a video type stuff.
Oh, right, haven't tried anything video-related, so can't help much on that
Np, input much appreciated.
The lightest weight way i can think of would be to lock the chunk so it wont move and pass in the ptr to whatever job needs it. As long as you're only reading from it and pad the allocation either side by cache line size it should be fine. If you don't care about being able to read the component in other areas / from the Entity Inspector etc then you could skip the chunk locking entirely and just malloc some space and use that pointer instead. Its going to be slightly faster than just doing a GetComponent by entity or using SharedStatic which uses a lookup. The case where you'd want to use a blobasset is if the data is being set in a subscene and passed in, then you can just let unity worry about where it comes from / lives and management, or read it on load from a component created by subscene and store it in the malloc then.
Anyone have an idea on this? I've asked before but still haven't gotten a good solution to it.
How do I change the orthographic size of a Unity Tiny camera?
{
public struct Camera : IComponentData
{
public Color backgroundColor;
public CameraClearFlags clearFlags;
public Rect viewportRect;
public float clipZNear;
public float clipZFar;
public float fov;
public float aspect;
public ProjectionMode mode;
public float depth;
}
}```
@gusty comet For an orthographic camera "fov" is the orthographic size
jesus thanks, that works. I've been futsing with the camera for hours
Yeah the documentation is not too good yet
Don't think so
I'm trying to get a Trigger Event in DOTS Physics... but nothing happens.
Is there a matrix what collision filter and collision responses I need to set on my PhysicsShapes / Physics Bodies?
Interesting, it also doesn't collide.
Thanks for being by rubber π¦
I was clobbering some collider data in a system that I wonder what the hell I was thinking to do this test and not comment it out.
so we're not getting disable/enable components by the end of the year are we ^^
Is there a trick to get burst to build compatible with iOS simulators i.e. an iPad simulator? Currently getting:
Unity-iPhone.xcodeproj Building for iOS Simulator, but the linked library 'lib_burst_generated64.a' was built for iOS.
I remember this used to work (at least for the iPhone simulator), and I don't see a setting anywhere to swtich burst to another architecture π€
~~Oh, looks like that might have been fixed in 1.3.9 (I'm on 1.3.7): https://docs.unity3d.com/Packages/com.unity.burst@1.3/changelog/CHANGELOG.html~~
Nvmd, that didn't help π¦
we aren't.
my 2020 is disappointing.
Man, I tried 2020.2 and Hybrid V2 and it's a complete showstopper once again π’
How so
hybrid is still quite WIP
(talking of the hybrid rendering now)
a ton of the renderer functionality still missing or not working properly and progress is super slow
like, everything on DOTS nowadays
Well, non-tiny webgl builds seem to work with dots now...kind of. I was able to get stuff rendering but then my pathfinding just...doesn't work.
No error messages from what I can tell, but it spams the "jobs cannot be longer than 4 frames" warning in the console on attached builds. No idea
Is there a way to run a system/job exactly once for each entity when a component was just added or removed?
π€
I really seem to miss this functionality compared to Entitas.
Currently I work around with tags that then cause a second tag to be added.
My problem is, it deeply couples multiple systems with these pairs of tags, instead of just one tag.
Also, .WithAll<...>().WithNone<...>() can get pretty verbose.
Also, how do you indent this lambda garbage. Asking for a friend, because Rider is out of ideas. 
Btw. if it weren't so much boilerplate, I'd make each of these a system (e.g. additionally to the singular "LeaveBubble" system, I would want a "DisableGraphicalSmoothingOnBubbleLeftOrEntered" system and a "SetTranslationToOpenSpaceCoordinates" system)
But given the massive 200%-1000% boilerplate overhead for 3-10 lines of actual code, separation of concerns and SRP (single responsiblity principle, not scriptable render pipeline...) are often left by the wayside.
I mean, surely this must be Karma for me saying "I like whitespace" once too often in the great braces war of the late 1990s.
I mean... I know the feeling but in reality, this boilerplate used to be e.g. this for every property
Rigidbody rb;
void Awake()
{
rb = GetComponent<RigidBody();
}
void Update()
{
if(rb != null) ....
}```
so I mostly see it that way. As for myself, I have a wider monitor and write long lines - things like foreach params are always 1-2 lines. Helps me scroll less but all personal pref of course. Running a system just once for an entity I do probably what you describe. Add e.g. a 'Created' ICD to my archetype, have a system require that and at end of frame/sync point, call a batch entity query remove component method.
I work around this with inheritance and to some extent with attributes.
Admittedly, still trying to get by [Bind] attribute to work. (basically add that to a field and it will automatically bind it via GetComponent<...>either at edit or at runtime).
Sure, plenty of work arounds, DI etc but everything's a trade-off.
DI has a lot of tradeoffs, but also been using that.
And yeah... I think for ECS, they should have gone with a DSL rather than butchering the poor C# language.
I mean, maybe they'll get there, but these Entities.ForEach beasts practically make unit testing and integration testing nearly impossible.
And that was always one of the promises of ECS... separation of concerns.
~80% of my code is boilerplate in my DOTS project; both by Lines of Code and Character Count.
In my average Monobehaviour pojects, it's nowhere this drastic.
That means I could be spending 5x as much time coding my game if it were an ideal scenario (doesn't exist, but 2x or 3x = 40-60% actual code) would be nice to have.
imo that's because 50% of monobehaviour code is getting your data π . At any rate, sure I dislike the fussy/missing support for generics and some of the verbosity.. but unless you have specific suggestions for improvements..? I'm personally glad they dropped the [Inject] and made things more explicit and the lambdas are such an improvement over IJobChunk for general code.
Yeah generics in components would help. And even though I use them...
using Jovian.ECS.Components;
using Jovian.ECS.Components.Weapons;
using Unity.Entities;
[assembly: RegisterGenericComponentType(typeof(EntityListElement<TagBattery>))]
[assembly: RegisterGenericComponentType(typeof(EntityListElement<CameraTarget>))]
Having to maintain a such a verbose type registry like this defeats the purpose of a generic that in itself is barely as many characters; and also, in stack traces, I only get mangled / base class names. Yay. I also think it would cause many assemblies to get recompiled, or have one registry per assembly.
Big oof.
What would help me more though would be Entities Foreach to work just differently.
Like, its lambda being a function I could implement elsewhere. I am struggling to even call (meaningful) functions from these blocks.
Overall, ECS is very close to how my brain works, but Unity's implementation tries its hardest to be as far as possible from how my fingers work.
Hello, how do you get a NativeArray pointer with an offset? NativeArray<int> array = new NativeArray<int>(100, Allocator.Persistant), to get the pointer to 0th index of the array you can just use GetUnsafePtr(). How to then get the pointer to the 10th index of the array? I'm trying to copy chunks of an array into a different array with MemCpy().
https://www.youtube.com/watch?v=jjEsB611kxs this got posted today on reddit, very interesting talk about component models, and the approach of the guy which is a more hybrid system
A long brain dump about entity/object models in game engines today...
he talks in depth about pros/cons of stuff like unity gameobject model/ue4, and pure ECS
and on his hybrid models he has some really nice ideas
You can offset the pointer by adding the length you want to offset it by to it.
int* ptr = (int*)array.GetUnsafePtr( );
var ptrAtOffset = ptr + UnsafeUtility.SizeOf<int>( ) * offset;
Although I'm not sure if you actually need to multiply it by the size of the type if you have already casted the pointer to the correct type
Yea you don't if you casted it to the right pointer type
Hmmm his hybrid model is the one I like least of the 3. I think he really doesn't have his dependencies figured out yet, or decides that each system can really only live on one thread. For many workloads, this is actually a bottleneck.
but thats not how it works?
he runs LocalSystems as a parallel for over all entities (1 entity = 1 task that runs all the systems for that entity)
and then he runs the global systems in a way very similar to unity DOTS job system
I think most systems (as in, most instructions run on cpu) are global, even though most code lives in local systems.
The local systems only make sense for domains with very few entities in them.
(which he mentioned, like, UI, player entity, etc.)
Real DOTS question:
Structural Changes!
Would you recommend adding 1 Tag or 2 Tags to enter / leave a specific state on an entity (assuming you also need another component to hold data for it) (e.g. "AddUIFocus" and "RemoveUIFocus" versus "UIFocus", given that there's additional componentdata involved anyway)?
Currently I use 1 Tag, and the presence of the data to infer intent. But it's messy - because presence of data and absence of tag will result in removal of data, which is something I may not want for child entities.
But using 2 Tags would imply I would always have to do 2 additional structural changes per state transition. (adding the tag to initiate the transition, and then removing it)
I'd much rather have a system that works on addition and removal of a component, but at least the latter I have NO idea how to write.
(actually these are rare task switches - only a few dozen in a minute)
(but they have implications for a dozens of entities and their children)
I read something about changefilters but... no idea how they work.
Whyyy.
How do I access that in a bursted job?
Just remembered this was why it wasn't a sharedcomponentdata.
I'll try ChunkComponents.
The one time I could actually benefit significantly from chunks -.- They get in the way like this.
yep, that you can't use them in burst makes them dead to me π
chunk component is probably not going to help you though because its just adding the component to the chunk instead of entity, it will be one per chunk
But you can add it to an entity query can't you
So you still have a shared component basically
Thanks for the headsup, I will write it with IComponentdata instead, at least I can write that without a lot of fuss.
I would really rarely write it though, and all entities with the same data would actually greatly benefit from being filterable and in adjacent chunks.
How?
I mean, with foreach? And how can I read it?
A chunk component is just an icomponentdata
Because i need to access it (it actually doesn't contain managed data, it only contains... wait for it ... 1 byte right now. Might be slightly more later)
not sure but it would only be shared for the entities in that chunk, each chunk gonna be different
SharedcomponentData kind of does exactly waht I need, but possibly only in the future (they want to make it non-managed)
Yeah it is per chunk, basically it would just save you a bit of memory since it will be one per chunk instead of one per entity
I have not much control over my chunks, lots of entities may show up e.g. when a ship breaks apart, and then tadaa, moar chunks.
It's not about the memory, it's about the chunk organization.
(I already realized I can't change sharedcomponentdata like chunkcomponentdata... which again is mega counterintuitive, and there's no middle ground)
That aspect is actually fine as well because... I only ever change it for one entity (well, one hierarchy of entities, which could be a can of worms in itself)
(but seldom more than 100 at a time)
While we're at it, a better hierarchy system would be good, or a hierarchy-shared value somehow.
Instead I am faffing about with buffers and generic list components
if you're moving a hierarchy of entities for a floating origin does it not make sense to make use of the parent/child transform stuff and just set the translation of the root?
Sadly, no. -.-
Entities move between spaces (open space and physics bubbles), open space just has different scaling rules.
But when an entity enters a bubble, and that's the entity that has the user's focus (i.e. "is the player"), all the entities in that bubble should have their renderers enabled (and conversely, disabled once leaving).
However, entities themselves stay where they are, fully physically simulated etc. Just "headless" so to speak, tree falling in the woods with nobody to hear it but it did fall, that kinda thing.
So essentially the floating origin system isn't moving an origin, it's traversing a 1000x scaled space to get into another local space.
It actually works but I'm cleaning it up now.
And the 10% of cleanup are the second 90% of each feature with ECS, it seems.
I'm kind of struggling as to why you'd prefer a rand access per entity over just setting the Translation (or e.g. other float3 ICD) for a bunch of entities. It's not a performance concern right?
It's a float precision concern in that case.
That random access per entity happens once every couple of seconds, maybe 1-2 times a second if the game is really busy.
The largest vessels are maybe 100-200 entities. Most are more like 5-20.
(actual physical or visual entities)
An option would be to separate physics from the transform systems (and have them write the floating origin double3 coordinates instead, which in turn write the transforms when needed), but then I'd have to rewrite a lot of stuff that's Unity physics. And that has already changed so much, I really don't want to do that. Also I'm not confident I could write a system like that.
I actually wish I could just replace the pertinent parts of BuildPhysicsWorld and ExportPhysicsWorld.
I'd still need to manage visibility etc, so no gain other than a cleaner separation and Physics not messing with my transforms as much.
But yes I do feel sometimes there must be an easier way that I'm not seeing.
using Jovian.ECS.Components.Space;
using Jovian.ECS.Systems.UI;
using Unity.Entities;
using Unity.Rendering;
namespace Jovian.ECS.Systems.Space
{
public class BubbleVisibility : SystemBase
{
private EntityCommandBufferSystem _ecbs;
protected override void OnCreate()
{
_ecbs = World.GetOrCreateSystem<BeginPresentationEntityCommandBufferSystem>();
}
protected override void OnUpdate()
{
if (CameraSystem.bubbleChanged)
{
var current_bubble = CameraSystem.currentBubble;
var ecb = _ecbs.CreateCommandBuffer().AsParallelWriter();
Entities
.WithAll<RenderMesh>()
.WithAll<DisableRendering>()
.ForEach(
(int nativeThreadIndex, Entity entity, in Bubble bubble) =>
{
if (bubble.id == current_bubble)
{
ecb.RemoveComponent<DisableRendering>(nativeThreadIndex, entity);
}
}
).ScheduleParallel();
Entities
.WithAll<RenderMesh>()
.WithNone<DisableRendering>()
.ForEach(
(int nativeThreadIndex, Entity entity, in Bubble bubble) =>
{
if (bubble.id != current_bubble)
{
ecb.AddComponent<DisableRendering>(nativeThreadIndex, entity);
}
}
).ScheduleParallel();
_ecbs.AddJobHandleForProducer(Dependency);
}
}
}
}
So much boilerplate for effectively a single booelan assignment.
In Entitas, this would be entity.isRenderingDisabled = entity.bubble.id != current_bubble; and at most 5-10 lines of boilerplate to hook up the system.
(I also resent Unity for not treating presence or absence of tag components as boolean properties of the entity itself, I mean ffs, they treat GameObjects as booleans, give me a break :P)
I guess I might tag everything in the current bubble then do (psuedocode):
var query = CreateEntityQuery(typeof(InCurrentBubble), typeof(RenderMesh));
query.AddComponent<DisableRendering>();```
If many fixed bubbles and only a few entities move between I might use ISCDs with an index and filter on the index.
Yeah "not" that, but yes.
I definitely try and use the query add/remove components as much as possible
Yeah that's what I'd like to do but some very fast systems need to know what bubble they're in, and sharedcomponentdata only works on main thread. I could mirror it in a small componentdata of course.
That seems like good advice. How fast is that?
As in, can apply the structural change in parallel across ~100k entities?
If changing all entities of a single archetype it's almost free* well for 100k entities, you may have chunk shuffling and such.. but 1000s of times faster than individual e.g. addcomponent calls
(well actually it's about 10k that get and 10k that lose the component, the rest is untouched and wouldn't show up in the query if done right)
Not a single archetype sadly, well. Not sure what an archetype is.
Is an archetype a class of entities or is an archetype an EXACT combination of IComponentDatas on an entity?
the idea is you group all your entities into a single archetype by giving them a unique tag. That allows you to e.g. later bulk modify the archetype, rather than individual entities.
Exact. (given A, B, C are ICDs) If entity1: [A, B, C], entity2: [A, C], entity 3: [A, B] - each of those entities have a different archetype
So I could have entities that all have RenderMesh and Bubble, but I could treat them the same whether they are TargetCollector or Weapon or Vessel?
Yeah I got a lot of archetypes.
Might optimize that a little of course.
But probably no less than 50.
And that would answer my state machine question I had months back - I use a Cooldown component for the timing of a weapon, and that gets added and removed.
So to cut down on archetypes, I'd rather have one that I keep the weapon's state in.
In Entitas, you encode a lot of your game's state in the addition and removal (not just the presence and contained data) of components.
so that was my intuitive pattern.
It's always a trade-off between structural changes (Add/Remove Tag/ICD etc) or using e.g. an Enum. Often it's good to try and keep chunk fragmentation low and avoid the cost of structural changes but it's hard work.
YEah.
How do I stop my state machine from hogging all my CPU time though ... I mean I assume I can use the changefilter to optimize that a little bit but chances are all chunks are gonna be pretty busy.
Let me try to rewrite that system I posted with an entityquery.
(by busy I mean "time hasn't passed? ok, next...")
currently only entities with a cooldown component even trigger systems that do anything time-based
but I don't like that, It's 70% of my game code already and I realize it's in dire need of a redesign.
Thank you very much for your advice so far. I didn't realize I can "addcomponent" from an EQ.
That is definitely one of my missing links.
There has been quite a bit of discussion on state machines. (e.g. https://forum.unity.com/threads/figuring-out-state-machines-in-dots.1011388/ if you haven't seen it before). My take is that as soon as you care about going wide, doing stuff in parallel just makes life complicated, even with good tools. If you just use 'Run()' everywhere you can get a lot of the convenience features back that you're used to from mb land but that kind of defeats the point.
If I get this right, EVERY structural change is ultimately a sync point?
Yes, any time there's a structural change all jobs are forced to complete immediately
So that's what the EntityCommandBufferSystems also do?
There's no jobs that continue past these barrier systems?
Hello, I am updating an old ecs project from 2019 and my toComponentDataArray calls have broken, I can't figure out why as there is reference to the use of 2 arguments. error CS1501: No overload for method 'ToComponentDataArray' takes 2 arguments. Masses = AtomQuery.ToComponentDataArray<Mass>(Allocator.TempJob, out var masJob);
Correct - assuming the barrier system actually makes a structural change on that frame
The async version of that function is now called ToComponentDataArrayAsync
The non async version doesn't use jobhandles
Ah ok thank you!
At what time in entity conversion are the LinkedEntityGroups actually added to the entity in the destination world?
[UpdateInGroup(typeof(GameObjectAfterConversionGroup))]
I try this but the component isn't added.
(in a gameobject conversion system)
I moved it to an initialization system -.- grml
using Jovian.ECS.Components.Space;
using Jovian.ECS.Systems.UI;
using Unity.Entities;
using Unity.Rendering;
namespace Jovian.ECS.Systems.Space
{
public class BubbleVisibility : SystemBase
{
private EntityQuery _group;
protected override void OnCreate()
{
_group = GetEntityQuery(typeof(RenderMesh), typeof(BubbleShared));
}
protected override void OnUpdate()
{
if (CameraSystem.bubbleChanged)
{
//Hide everything
EntityManager.AddComponent<DisableRendering>(_group);
//Render only those in current Bubble
_group.SetSharedComponentFilter(new BubbleShared() {id = CameraSystem.currentBubble});
EntityManager.RemoveComponent<DisableRendering>(_group);
_group.ResetFilter();
}
}
}
}
This is the system from earlier with an entityquery.
Animations are completely broken (bones are somehow mapped wrong...) . Subscenes don't load anymore. Most of the time it actually freezes immediately as I set the V2 scripting define...
I'd move that CameraSystem.bubbleChanged to a singleton created by that system to hold it's data
what's the right way to check if an entity exists within burst? do I have to get the architype or w/e up front as an array and reference that?
if(HasComponent<Whatever>(entity)) <- Returns false if the entity is destroyed or null
ok thanks
awesome that's really solid
public bool HasComponent(Entity entity, int type)
{
if (!Exists(entity))
return false;
var archetype = m_ArchetypeByEntity[entity.Index];
return ChunkDataUtility.GetIndexInTypeArray(archetype, type) != -1;
}```
thanks again
so I can pass a native container to a job, but what if that result needs to be processed by something else to do more work with that NativeArray data? How do I store that data to be used by the next system? Should I just keep passing the job handle forward as a defacto pointer? I want to keep burst enabled and it seems that components can't store this data unless it's through some secondary lookup (like job handles). Thoughts?
there's also like static data that doesn't change every frame but varies per entity. Do I just make a job and never complete it so I can store NativeContainers and still use burst?
is there some way to have a pointer to a native container in a IComponentData so that I can use it with burst?
burst obviously doesn't require blittable as NativeContainers are supported in jobs
No. If you want to do something like that you're better off using a dynamic buffer
Otherwise you need to pass around the job handle with your native container. There's no getting around it
ok so
is there anything wrong with creating a bunch of dummy jobs that never get run just to pass the data around?
I can probably just abstract it out with helper functions
performance hit would be lookup up the job handle I guess
like if I have layers of hierarchical data, it's not just one dynamic buffer. I'd need to rework and deal with parenting, different hierarchies at different levels. I'd be building an entity system within an entity system. I guess I'd rather just not have to refactor the component I'm working with to do this
I just want a pointer to the data
I've seen people talk about trying something like that before, never heard if it worked out. I wouldn't recommended trying to hack a way around it. Just accept that you need to pass the job handle around, and build an abstraction around that
ok
That's what I woudl recommend anyways
there's just going to be like... dead jobs that are only being used to pass data around then. they will just stay alive forrever
how do I uh.... get the job object from the job handle? google is being silly I'm havin trouble finding it
I don't think you can do that
wait what? then how do I get the data out
You pass in a native container
Populate it, then your container has the data from your job
ok but, you can't have another system process it later tho rite?
Yes you can, but you need to pass the job handle along with the container
how would I pass the container to something later?
And pass in the previous job as a dependency to the new one
that container can't go into an IComponentData rite
so
that means the receiver of that data can't use burst right?
so I would create a hash lookup and key it by entity or something?
how would I look up the right instance of the data if it's just stored on the system?
class SomeSystem : SystemBase
{
public NativeArray<int> data;
OnCreate() => data = new NativeArray<int>(10, Allocator.Persistent);
OnUpdate() => Entities.ForEach(()=>(data[0] = 10;)).Schedule();
}
class SomeOtherSystem : SystemBase
{
OnUpdate()
{
var data = World.GetOrCreateSystem<SomeSystem>().data;
// Pass in your data to your job. But you need to get the job handle from the original systems and pass that in manually as a dependency as well
}
}
Something like that basically
data[0]
If that looks insanely bad and ugly that's because it is, but that's how you have to do it. Use dynamic buffers instead then you can just have your data associated with an entity and let unity worry about the dependencies
Of course you don't need to store your container on a system like that, just put it wherever you want
then I can wipe the native array in one go at the end
yeah it's bad. I get that I"m working around a non ECS object and trying to deal with it
I'm okay with this solution. still uses arrays and index instead of hash map
thank you!
cool this is gunna work. thanks again
so does anyone have a working, real, released game using DOTS?
not me but there'a a bunch of them
At the bottom it lists a few. Apparently ShipBreaker benefited a lot from it which makes sense
I don't remember the names but I know there's a few physics based games on steam that are using it
Shameless plug: https://forum.unity.com/threads/legion-commander-the-art-of-war-dots-ecs-based-mobile-game.887506/
v good, v good
Reminds me that I should post as #madewithunity and maybe get a RT π
is there some way to get a ref of a nativelist element, so I can directly modify struct fields without having to copy the whole struct back?
wait what. can you not store a NativeList inside of a NativeList?
UGH
alt+f4 I'm done
You can store UnsafeLists inside a NativeList
No.
poo
It's basically a NativeList without deallocation and job safety checks
thanks tho. I don't control the underlying structure (or it would require lots of work to change)
So just a wrapper around void*
I don't think there is
You can force set the length of the unsafelist to your array size
What are you trying to do?
I'm trying to deal with kinematica in a more ECS way without rewriting everything above the motion synthesizer
so I have some game objects and some shit like
Trajectory and PoseSet
the former is created every frame for every entity and needs to be used by different steps
the latter is created once per either type of entity or for each entity on creation
both have NativeContainers in them
so I need to pass this data around
and I want to still process animations with burst
but I just don't see a way to do it
I can't store it in a nativelist on my system then index it from a future query because it contains a native container so it can't go in there
the struct itself (Trajectory/Poseset) suppoorts burst
it's just I can't fucking pass the data around
So you want a reference to an element in a native array
I do also want that @compact robin
You could just store the ptr to the data
Can you?
Unless you pin it, they get moved around I think
Like the address changes hmmm
Well you shouldn't store the ptr to the array, but to the data the native array holds
Which won't be moved around
so if I make a class component to GC root the struct, then use unsafeutility in unity to get the ptr, will it change?
Cuz its using unmanaged mem
Unmanaged mem doesn't move anywhere
Yeah
if I add things to the list tho all my pointers could change
When you add stuff to like a native collection, they get copied into it
is there a way to do an unsafe alloc of a struct? or I just do that with unsafelist or something?
You wanna access the elements right?
i mean the backing array could be reallocated and all my element pointers could break
Ye if the array on the thing changes you will point to invalid mem
And most likely crash
Oh a list
yeah
Yeah that makes sense
ok but
Then the only way I can think of is using GCHandle to point to elements
But that's a horrible idea lul
yeah so I can't use that list to root the objects. I'd need separate chunks of unmanaged memory linked to by IComponentData somehow. or having the pointers in the list
Or just allocating them yourself
so is there a way to allocate a struct as unmanaged and just get a pointer and put that on the component data?
then I can just be like *unmanagedValue = managedValue
to set it once
can I just be like Allocator.MakeMeSomeBytes(Allocator.Persistent)
And just write to that pointer I guess
ok perfect
Yes that's what malloc is for
I think I have to do that
But you have to free memory yourself
Yeah
thanks guys. I have a plan for tomorrow now I guess
Are you going to store the data on your IComponentData?
the pointer yeah
So you have two pointers there + their length?
no. I will have a type safe ref created from the pointer using unsafeutility
ref UnsafeUtility.AsRef<T>((byte*)ptr);
the struct I've allocated
which contains a NativeArray
Right
yeah the insides of the struct are blackbox to me
but it's burst compatable
just not blittable (uses native containers)
?
the data and functions on it work with burst
It is still blittable if you have a native container in a struct I think
Hrrrm I'm writing something that smells extremely like Subscenes.
But Subscenes can't have offsets, right? That's the feature I actually need.
Is there a straightforward way to load in a Subscene at runtime, at an offset? I.e. can I identify all entities that were just loaded?
Well you can't really have pointers to
it's not legal to have on componentdata
Non-blittable structs
Can you get the ptr to a managed type? Which is basically what you want to do right?
but then I can't use burst @north bay
No you can't do that unless you pin with GCHandle
but sorry my bad it's blittable, it just has nativecontainers so it can't go on componentdata
Yeah it has to be blittable
You can't have pointers to non-blittables, its a C# thing
It is not
rip
Wat.
Native containers ought to be blittable. Not deep blittable, but shallow? *goes to check ... *
yeah
I always thought they were blittable
how are they used in jobs
Too bad my Unity's down
Unity does some magic and removes the dispose handle
Which is what makes them not blittable
If i remember correctly
Oops
I mentioned it wrongly
I meant to say
You can only have pointers to blittable types, LOL
This... is not blittable?!
DisposeSentinel
is reference type
it's so silly. it's burst compatable but there's like no way to get that data around in ECS without disabling burst
Well Burst is not a real compiler anyhow. 
Cuz they already exist
I use fixedlists a lot.
wat
Like, a criminal lot.
The Native variants are just wrappers around the Unsafe ones
Ye
oh. no I can't change that
I store them on my components all the time
I mean... yes....
I could review how it's constructed
and try to make a new system
I'm trying to avoid that tho :S
I have a struct. it's burst compatible. how do I move that data from one system to another and have it burst processed in both? I think it's impossible right?
assuming it's not blittable
it seems silly that I cant
I don't think its burst compatible if its not blittable
It just doesn't make sense
0-0
yup
Β―_(γ)_/Β―
like native containers can be used in jobs. structs containing native containers can be used in jobs
it's just so silly
like this is THE FORMAT to pass data around
The data are arrays? Store their ptr in your component
and u just like... cant...
Make sure it is only accessed while it's valid
And you are good
NativeArray.GetUnsafePtr()
but that's like
but that's like... take it from my component into what kinematica needs, let it process, then write it back out to my own, like 3 times per frame
each time I want to access the data
it needs the struct in that format unless I rework it
I guess I want to try and make it happen without reworking this struct
yeah well.. I need a ref to the struct that contains the native container
there's really just no other way is there
But its a shitty way imo
I used that to run managed stuff on Unity's worker threads
the only other options are to do it without burst, or to rewrite a bunch of kinematica to use IComponentData compatable data
π€·π»ββοΈ
i mean
Unity is just weird xd
That's how i pass the PhysicsWorld currently to my unmanaged stuff cuz those stupid native arrays π
Lolll
ISharedComponentData Question - is the ABSENCE of the shared component also a value for chunking purposes, or is it the same as default?
Well I have to make a bunch of cached Action<T> s
For managed stuff I wanna run on Unity
Via multiple threads
Cuz I don't think its a good idea to use TPL threads in-conjunction with Unity's worker threads
The TPL can't account for those additional threads
I wish I knew good way to safely tie entities to managed space (e.g. UI).
- also googles to see how to best store strings ... *
I think they can - though I think they plan on improving it? Check out the procedural dungeon project
Thank you Timboc
99% sure absence is different
cause the architype would have to change
I think so, too. Archetype is a good argument for that.
Can you use SharedComponents in bursted IJobChunks? That was the biggest issue why I never used them
are you trying to load multiple instances of a subscene? cause u cant do that
since there's only ever one, you can just "hard-code" the offset into the subscene however you like
Wow - good to know. Why?
And no...
More like procedurally generating Subscenes. But they share a lot in common.
Untrue I think
@warm panther the idea is you want to load from disk into memory once, then replicate instances frrom memory
Yes but editing is a pain if each subscene has a different place of work while you cycle them (60+ small moons, each with their own little buildings, labels, etc.)
do you'd have prefabs in a subscene, load the subscene (which loads the prefabs into memory) then instantiate the prefabs
Can't I use a subscene as a prefab? But... that's more relevant for ships rather than places.
I was planning on using a subscene to create all my prefabs.
(prefab entities, that is)
loading a subscene multiple times would load the data multiple times from disk. I dont think that's what you want
so I could see and edit them kind of like an inventory of the stuff I have (as a dev, not player).
Generally not. Thanks for the heads-up.
so I've got like these "room" subscenes
so it loads the subscene and waits for the room entity to show up
then there's a prefab referenced on there and I instantiate that
when I unload the subscene all my prefabs are unloaded, for example
the prefab is inside the subscene
That's pretty close to what I need for initialization. that feels like a clean, if indirect, approach.
it seems to be working so far
cool
dats muh subscene
prefab is entity converted already
so subscene loads into prefab entity, and I can just instantiate
Currently wondering how to get to the entities of the children of a GameObject/Transform in conversion. Probably I need to look at the parents instead and tell the child's authoring compnents to do stuff differently depending on whether they are in a different environment (to use an old MUCK term)
there's a component it adds... I forget which direction it goes
You just call conversionSystem.GetPrimaryEntity on the child gameobject
During conversion. Children are guaranteed to be converted first.
Ah cool. But does that entity have the ComponentDatas?
Wait.
Childen converted FIRST?
That would even make sense in a twisted way.
And would make my workflow simpler. I'll try it...
In authoring, do you have any techniques to flatten your hierarchies?
e.g. I have "smart" gameobjects that hold data and behaviours for editing and conversion, and have a "dumb" child that holds the mesh etc. But really that could just collapse into one entity for all intents and purposes.
I have like a hundred of these, some simplification still to happen as I convert monobehaviours but... for semi-procedural generation at edit time, this makes sense for me.
Thankfully in my games I haven't needed hierarchies beyond a single child. The transform system in ECS is too complicated for my brain
Yeah writing the targeting, animation, firing, and aiming code for arbitrary turrets was a brain melter, but I am happy, albeit with a head full of warm solidified slag now.
Can I "stop" converting an entity in IConvertToEntity? Or rather, fuse two of them (one being the current one)... hmm.
For authoring it seems like you already have a system that works. I was trying to come up with a way to set up authoring for a chunk based Minecraft clone and it basically broke my brain. Especially with the horrible/nonexistent scriptableobject to entity workflow right now it just doesn't seem practical for me
There is a ConvertToEntity (Stop) Monobehaviour
To stop conversion along a hierarchy
Yes it works, but it's not clean. Cleaning it twice doesn't make much sense though / some things can't be cleaned before the things are actual entities. Like, the orbit motion etc. Currently a monobehaviour, will go into a system with just a dash of data (orbital elements) rather than the huuuuge overhead of line renderers etc; each of which could be just lightweight entities doing just that one job. (rather than a monolithic GO managing them all)
Yeah I use that but it would mean I'd have to manually replicate from the sub objects what I would want in the parent one. (e.g. the right 2 columns - they are a prefab that contain an imported object, something unity's mesh importer won't let me flatten - but let me check again)
Perhaps this 5+ year old asset is just garbage though.
And I should look for something cleaner for prototyping. I'll see if I can modify it with a custom importer though.
Because I process the meshes automatically in external tools, I need that "mesh<->prefab" connection to be deterministic and intact.
(not in this case, but many other cases)
Do they really need to be separate gameobjects if they're ending up on the same entity anyways? Can't you just have all your authoring scripts on one gameobject?
This is what my asset toolchain gives me, but I can't do it for those ancient asteroid assets π
Yes there's no authoring script on "46_5 (Clone)" and the contained "object"
But they will still become 2 entities.
The heavybomber example becomes 1 entity.
But it's fbx/blender. Maybe I can in a python script change the .obj files into something more recent, I need to write to some channels that .obj doesn't support anyhow (vertex color, among them, and I need 1 or 2 more UV channels)
But... rabbit holes after rabbit holes.
I'd rather learn ECS more than keep writing tools which I know how to do kinda well by now π
Yeah I can probably just use bpy and convert these in 20 lines of python code.
It sounds like you could be using ConversionSystems too to keep things cleaner if you aren't already
Yes I want to move to these, but tried it yesterday to add a SCD to all children / linked entities in a group, and for the love of god, I could not get it to work.
So I made it into an InitializationSystem.
Just remember you need to call conversionSystem.GetPrimaryEntity to get the converted entity for any gameobject/child and it should work. Though things break fast if you're trying to rely on conversion ordering between anything that doesn't have a parent/child relationship
I guess it's possible but too much work for me
/**
* Creates Shared Bubbles on each entity that has a Bubble component, and all entities in its Liked Group, if any
*/
[UpdateInGroup(typeof(GameObjectAfterConversionGroup))]
public class CreateSharedBubbles : GameObjectConversionSystem
{
protected override void OnUpdate()
{
Entities
.ForEach(
(VesselAuthoring input) =>
{
var entity = GetPrimaryEntity(input);
var bubble = DstEntityManager.GetComponentData<Bubble>(entity);
var buffer = GetBufferFromEntity<LinkedEntityGroup>(true);
if (buffer.HasComponent(entity))
{
var children = buffer[entity];
foreach (var child in children)
{
DstEntityManager.AddComponentData(child.Value, new Bubble() {id = bubble.id});
DstEntityManager.AddSharedComponentData(child.Value, new BubbleShared() {id = bubble.id});
}
}
}
);
}
}
This doesn't do what it says. π
But the Bubble is there.
So only the LinkedEntityGroup isn't there (yet)
Rather than iterating the linkedgroup, iterate the gameobject transform and call getpeimaryentity for every child
Sorry typing on phone
I guess I just have to leave them as managed, leave the entity queries WithoutBurst and just try to ensure I do any significant work inside a burst job after I dereference managed things
what was the issue with storing pointers to the kinematica structs?
pointers to unblitable objects don't work in unsafeutility
so I have no mechanism (unsafeutility/gchandle) to get a pointer into burst code
unless that pointer is to a blittable type, which is not my requirement
like I can get an IntPtr I guess
but I can't convert that into a c# object
I could maybe use "unsafe" in burst? I dunno if that works but unsafe has it's own overhead. it's not something I want to do every frame I don't think
ahh okay, if it was just the native containers that you needed, and maybe if it was just a list, you could just grab the pointer and treat it like an array.
yeah, like I think I can rework the data. it's just cause it's in there already, I'd have to change the internals
and I don't want to deviate too far from the package, in case it changes and I wanna upgrade
pretty much everything in unity ecs is using 'unsafe', i wouldnt worry about it
hmm ok maybe it's worth a try then. I assume whatever* is blittable?
it appears to be... no errors on basic tests...
assuming whatever is unmanaged yeah
i mean it's a pointer so it should be 8 bytes regardless rite?
we'll see I'll try it
this time check in BEFORE i start
XD
yeah, you're right it would refuse to compile if the struct was managed π
anyone here use VS Code for their unity dev? any limitations compared to normal visual studio?
yeah ok that's what I thought
code is great for typescript, so much more lightweight than VS, but havent used it for unity. I've been forced to use rider for the last few months and now its my fav for unity dev.
what makes it your favorite?
also does it have decent git integration (submodules & branching functionality)
main reason I'm wanting to move from VS is git integration being so fucking terrible
not sure, i use perforce or gitkraken but rider has heaps of extensions available so id be really surprised if it wasn't well integrated.
ok
just go cmd for git
hahaha
i've had heaps of problems with VS updating in unity, when i rename files or open files it tries to open new instances of VS rather than refresh the existing one, hangs during debugging stupid stuff like that, really slow operation. Rider seems a lot more lightweight the unity integration plugin seems more solid and you get resharper/dotpeek integrated.
imagine having like a company daemon that monitors for like vs code or github desktop and just emails u when someone uses it
hmm yeah I had all those issues
good to know
never really used resharper. dotpeek is just like... MSIL right?
yea
im watchin this now. looks neat: https://www.youtube.com/watch?v=ld7ubGmxL7A
pretty much all the IDEs got their refactoring features by copying resharper its been around for a while now, but i tend to use it for the member renaming, extract method, extract interface those kinds of things.
yeah ok
vscode for Unity is pretty decent, intellisense can screw up if OmniSharp updates (so if you go with vscode, I'd say lock the version of Omnisharp that works for you, updates for Unity support comes in after official releases)
good to know thanks
nope can't make a pointer to those kinematica types
you were right
rip in pepperonis
can I just make a struct, mark it as [BurstCompile] and call a method on it? does that work?
yes
hmm that's pretty okay... I can do my managed stuff in my entity query and just do the main work on some local struct with burst
you can put it on static functions too so you don't need a struct, depends what you need
oh, neat
that could be okay
with the entity queries everything is componentdata or local variables anyway. no need for instance members
should work
thanks
Question: I get two Trigger Events in my job for each collision between a Collider whose response is "Collides" and a Collider that Raises Trigger Events.
If I set the body to not "collide" with the trigger, then I get none (even though the trigger would collide with the body) - I think that's because of how collision filtering works.
How can I (reliably) know which entity was the trigger, or - even better - ensure only one event is raised?
[BurstCompile]
private struct TriggerEventSystemJob : ITriggerEventsJob
{
[ReadOnly] public PhysicsWorld PhysicsWorld;
[ReadOnly] public ComponentDataFromEntity<BubbleData> BubbleData;
public EntityCommandBuffer commandBuffer;
public void Execute(TriggerEvent trigger)
{
var tagsA = PhysicsWorld.Bodies[trigger.BodyIndexA].CustomTags;
var tagsB = PhysicsWorld.Bodies[trigger.BodyIndexB].CustomTags;
//We only care for open space triggers (both 0) right now
//TODO: Other trigger events, such as docking cones, radio ranges, etc.
if (tagsA != 0 || tagsB != 0)
{
return;
}
var entity_a = trigger.EntityA;
var entity_b = trigger.EntityB;
//We touched an instance, let's enter it
if (BubbleData.HasComponent(entity_a))
{
commandBuffer.AddComponent(entity_b, new BubbleEnter(){id = BubbleData[entity_a].id});
}
else if (BubbleData.HasComponent(entity_b))
{
commandBuffer.AddComponent(entity_a, new BubbleEnter(){id = BubbleData[entity_b].id});
}
}
}
I wrote it this way because you can't know which entity is which.
I think the physics collisions almost always raise 2 points
just cause of how the formulas work
Oh, points cause events?
that's my understanding yeah, each collision point will cause shit
So if I have 2 mesh colliders, there could be... a lot of events?
Wow.
I should write that system to not use collisions. π
I dunno, should still be like 2 I think
It passes both entities to the Execute so if that gets called twice for the same entities that's definitely a bug
That would kinda break the point of trigger events or not?
Imagine having one compound collider with overlapping colliders and getting 20 trigger events because of that
Weird.
It does get called twice for the "else if" in the last branch. It happens in 2 consecutive frames.
So no surprise my speed was 10000x instead of 100x (there's a speed boost involved)
Hmm.
return
(filterA.BelongsTo & filterB.CollidesWith) != 0 &&
(filterB.BelongsTo & filterA.CollidesWith) != 0;
So yeah definitely can expect up to two events even with 1 contact point contact.
Oh it's a trigger, there are no contact points.
mmm, if you don't want to change the original you can make another struct of the same size and layout, that excludes the managed members and cast to that instead. I do this all the time for ECS classes like dynamic buffer headers etc that are set to internal
hmm interesting. i might try that later
Wait my problem... if it's 2 consecutive frames, I think I just have my entity not "move" quickly enough, or be considered. Thanks for being my π¦

so all this time refactoring... I decreased my perf cost by 0.02 ms
π€
So with subscenes, what's an alternative to calling DstEntityManager.Instantiate? Seems like instantiating a copy of the entity causes the GUIDs to be the same and I'd like to get a copy of the entity and Unity would throw an error π€
how do I go about setting dependencies between Jobs of particular Systems? I thought the [UpdateAfter/Before] attributes took care of it but I'm still getting an error requesting I set up the dependencies, and the Dependency property within systems is protected
how do I go about setting dependencies between Jobs of particular Systems? I thought the [UpdateAfter/Before] attributes took care of it but I'm still getting an error requesting I set up the dependencies, and the Dependency property within systems is protected
@opaque escarp
You can do it how the physics package does it - public GetOutputDependency/AddInputDependency methods so other systems can position their dependencies around your system as needed
It kind of sucks but it works
ty
is the order of the OnUpdate invocations guaranteed and determined by the [UpdateB/A] attributes?
How do I run something exactly once for a system?
protected override void OnCreate()
{
var query = GetEntityQuery(typeof(BubbleData));
var array = query.ToComponentDataArray<BubbleData>(Allocator.Temp);
foreach (var data in array)
{
bubbles[data.id] = data;
}
}
That Componentdata array is empty during OnCreate.
Okay I solved it...
public class BubbleManagement : SystemBase
{
public static NativeArray<BubbleData> bubbles;
protected override void OnCreate()
{
base.OnCreate();
//Our open space "bubble"
RegisterBubble(new BubbleData() {scale = 1000d});
}
public void RegisterBubble(BubbleData bubble)
{
if (!bubbles.IsCreated)
{
bubbles = new NativeArray<BubbleData>(256, Allocator.Persistent);
}
bubbles[bubble.id] = bubble;
}
```
And using this system in the other system that actually is responsible for collecting the data.
(a Conversion System)
you can try to override OnStartRunning() although if BubbleQuery has 0 entities and then has 1 entity again, OnStartRunning() would run again
There's an additional OnStopRunning too if you need that also
Works, thank you π
One less dependency. And once I figure out how to deal with new bubbles and their life cycle, I can properly build that in this system.
hey guys. i try to figure out how i can access my nativearray in readonly with the Entitites.forEach method. with this code:
public class ComputeAccelerationJobSystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
float dt = Time.DeltaTime;
NativeArray<ParticleComponent> particles = GetEntityQuery(ComponentType.ReadOnly<ParticleComponent>()).ToComponentDataArray<ParticleComponent>(Allocator.TempJob);
JobHandle handle = Entities.ForEach((ref ParticleComponent particle, ref Translation translation, ref ParticleAccelerationComponent particleAcceleration) => {
for(int i = 0; i < particles.Length; i++)
{
particleAcceleration.acceleration = 1f * particles[i].velocity; // no real calculation.
}
}).Schedule(inputDeps);
handle.Complete();
particles.Dispose();
return handle;
}
}
i can run it with 93 particles. with more i get this error: "IndexOutOfRangeException: Index 93 is out of restricted IJobParallelFor range [0...92] in ReadWriteBuffer."
i have kind of a idea whats going on, but not realy.
what refactoring did you do
instead of looping through all of my 6 x 3 panels.
then do validate -> if yes -> move.
I instead mapped it to a NHM -> validate -> if yes -> move.
since nhm is faster
and I only shaved off 0.02ms
uuugh
Let's say I have a Timer component, and after it reaches 0 I remove the timer and add a Complete tag component. Is there a way to batch this remove and add operation? At the moment I just use an ECB and add/remove individually
or is there a better way of handling such a thing
Happy new year dots devs
how many 6 x 3 panels were you looping through?
ECB is a very good way to do this sort of thing in low numbers since they bursted the ECB playback, it used to be terrible. You can setup a query, and then pass that into RemoveComponent if memory serves, but it can be slower unless you have like thousands of removes to do all at once.
how would I go about using a query, since I only want it to operate on things that have Timer values of less than 0?
I mean its 6x3 so 18. So im looping through 18 panels just to validate if my move is validated
@opaque escarp if you don't want to check inside the system job, add a tag TimerLessThan0 so you can do WithAll<TimerLessThan0>()
although you would need to check for it somehow
another job maybe
well how do I add a TimerLessThan0 component en mass then, seems like kicking the can farther down the road haha
@opaque escarp with an ECB
you could store off the entities to a list, and then use the removecomponent(nativelist), im not sure if its faster though
I'm using the ECB right now
that's the way ^^
all right, if it's the best then
I'm pretty sure using the NativeList thing would be the same speed, since ecb should operate in a similar manner yeah?
but with NativeStream or summat
it depends what you want to do, each could be better for different cases
probably best to test it, they can do some weird stuff internally
all righty, thank you
struct Timer : IComponentData
{
public double start;
public double value;
}
public class TimerSystem : SystemBase
{
protected override void OnUpdate()
{
var total = Time.ElapsedTime;
Entities
.ForEach((Entity e, in Timer timer) =>
{
double elapsed = total - timer.start;
if(elapsed >= timer.value)
{
SetComponent<Timer>(e, timer);
}
}).Schedule();
}
}
What about something like that
I know it looks weird but
If you have other systems with a ChangeFilter targeting your timer, they will only run when the timer elapses, assuming nothing else writes to it
ChangeFilters are something I haven't looked into, I'll do so now, ty
I guess they would also run when your timer starts though...
So in your timer reacting systems you'd maybe have to double check the current time against the start time as well
I am having a problem where my struct has 2 output values. One is a NativeArray<int> and the other is a NativeList<int2>. Neither is disposed of until after I complete the job. I can get the values of the NativeArray<int> but the NativeList<int2> always has a length of 0. If you search for PROBLEM: it will take you to the 2 debug.log lines where I check the size of the list inside the struct and it is positive and after completing the job where the length suddenly becomes 0. Can't figure out why https://hastebin.com/mezirelove.cpp
Disable burst and put a debug log inside the loop in CalculatePath to verify it's doing what you expect
Well I log the path length immediately after calling CalculatePath, it is greater than 0
Oh, I see. path = CalculatePath(pathNodeArray, endNode); You're assigning your output to a temp container that you pass back from CalculatePath
Pass the path into CalculatePath.
Ah I was wondering if the Temp was the problem, but my other list is a TempJob (maybe TempJob is the one to use to keep the values?) I will try right now
The length you're seeing from the first debug is the path you're passing back from Calculate Path. That is a different container than the one you passed into your job.
Oh Temp vs TempJob are different contianers
Not exactly. When you call new NativeContainer, you're creating a new container. You can't just assign that to your original container and expect them to merge somehow
Does CalculatePath become a void then? And I just pass the path variable?
Yeah that is typically how you do it
That DID IT!
Awesome I would not have been able to understand that, not used to programming like this but need the speed
Thank you!
var a = new NativeArray<int>(1, Allocator.Temp);
var b = new NativeArray<int>(1, Allocator.Temp);
b[0] = 10;
b = a;
Debug.Log(a[0]);
You're basically doing that and expecting it to be 10
Ah, the edit you made makes more sense
I was about to say, I am setting the values of the list first
Hahah yeah
I mean you can certainly assign a variable that points to one list to instead point to another list. The point is that they are two different lists
Oh I thought this was the order it all came out in ```
FinalPath = new List<int>();
TempPath = new List<int>();
TempPath[0] = 1;
FinalPath = TempPath;
Basically if you're dealing with a native array inside a job and you want to get values out of it you need to assign the values directly to the native array, or copy them from another array. By doing path = CalculatePath(pathNodeArray, endNode); you're just assigning your second array to a local variable
If you did path.Copy(CalculatePath(pathNodeArray, endNode)); that would also work
Ok so I would need to copy if I had to get another list
Yeah
It was all just from breaking out the function for populating the path
I'd like to implement my own attribute like [GenerateAuthoringComponent], to do so in a custom way. Is that plausible or do Attributes like that use features that are not publicly available?
That's... not really how that works?
If you need a custom conversion/authoring, there's an interface for that
What is your use-case?
at the moment I have a system set up that uses generics for various things. At the moment I have to use many attributes in order to get things to run properly, like [assembly: RegisterGenericJobType...] and such, multiple times all for what would be the same type argument. This would also include having a custom authoring component be generated, since it would be the same as other like-components (but different from the default GenerateAuthoringComponent behavior). Ideally I'd like all these things to function from a single attribute, but as it stands I'd have to have a large code file I just dump all the boilerplate in for every time I need a new thing
A class inheriting from MonoBehavior could have some of the boilerplate in that particular file
yeah at the moment I have an abstract authoring component I inherit from with some relevant overrides. The other attributes are the ones I'm a little more interested in. Also because at the moment even after using RegisterGenericJobType you still have to have a concrete (non-generic) implementer, which I'd like to automate
okay, simplifying things. Right now I need to do this every time I want to have an affectable component
[assembly:RegisterGenericJobType(typeof(ModJob<MoveSpeed,FloatMod>))]
[assembly:RegisterGenericComponentType(typeof(BaseStat<MoveSpeed>))]
[assembly:RegisterGenericComponentType(typeof(ModElement<MoveSpeed,FloatMod>))]
[assembly:RegisterGenericComponentType(typeof(Mod<MoveSpeed,FloatMod>))]
the question is, is there a way of creating my own attribute that will do all of that in one Attribute, such as [RegisterElement<MoveSpeed,FloatMod>], or does that require access to internal things?
I'm trying to figure out how to get a jobsystem to execute on IJobParallelFor and it's not looping or manipulating data
Wondering if anyone could help me with a simple test case for DOTS? I'd like to instantiate a large number of (simple) entities in parallel (basically, entities with x/y int co-ordinates). All of the tutorials and examples I can find go as far as telling the entity manager to create stuff serially, usually in a Monobehaviour update. And I can't figure out the syntax for job handles for this particular task.
Or is it intended that you instantiate them sequentially but update components in parallel?
The only way to create entities in a job is via ExclusiveEntityTransaction. Basically you create everything in a separate world and move it all over once it's done.
In most cases I think you're probably better off just using the batch create functions of EntityManager
I see. Thanks!
In that case, I kinda have the real thing I was after - I've got a function for Bresenham's line algorithm for my tile map, but I'd like to try and recreate it in a job system to see what kind of performance gain I'd get from parallelising it. I'm curious how long it'd take to run, say, 10,000 raycasts across my int[,] tilemap compared with a (burst compiled?) Job doing a similar thing. The algorithm's really simple, but I have no idea how to write the data back and forth between the job!
Would you mind giving me any pointers off the top of your head?
I've never done anything physics related in burst, from what I've seen it's annoying to get working. I can tell you if your data is an int[,] you need to collapse that into a 1D NativeArray in order to use it in a bursted job
I was just thinking making the tile grid into a flat array anyway! Coincidentally
I don't think this would actually use any physics functions, though
it's just integer addition, then returning an array of indexes
Then yeah I would expect you to see a huge performance boost if you convert your data into a flat array and use the math functions from Unity's math package
In combination with burst
If you're using any Vector2/Vector3 you should convert those to float2/float3 as well to get the most benefit from burst
And as for passing data back and forth from a job, you need to use Native Containers. You pass a native container into a job, populate it, then when the job is done your container will have your values back on the main thread, where you can access it or pass it to the next job as needed
I see there's now NativeList as well as NativeArray, when I looked in a few years ago there was only NativeArray
is it worth using one over the other?
There's also NativeHashMap, NativeMultiHashMap, and others. You just use whatever you need for the job. Obviously if you need an expandable container you can't use a NativeArray for that
Hey! I have a question about the animation rigging preview package. I was diagnosing some issues where it was using a huge chunk of cpu time. One interesting thing that I found was that cpu time was the same both when the jobs threading is enabled and when itβs not. Is this intended or something thatβs going to be addressed later down the line?
Each container has the expected trade-offs you'd see in a non-native version of the container - NativeArray is generally the fastest but not very flexible, and so on
I think I can guess the array length beforehand with a^2 + b^2 = c^2 actually
@zenith wyvern any chance you could point me to the most up to date example of IJobParallelFor syntax you're aware of?
I'm kinda guessing at the right language here
The docs seem to have a good example https://docs.unity3d.com/ScriptReference/Unity.Jobs.IJobParallelFor.html
it's scheduled in a Monobehaviour, does that affect performance at all?
You can also use "IJobFor" which I guess is meant to be the first choice for that kind of thing
Not necessarily - but in that case you need to make sure you call JobHandle.ScheduleBatchedJobs when you want to actually start the jobs you've scheduled
Otherwise it won't start your jobs until you call Complete on them, meaning your job wasn't getting any work done in the meantime
so you don't think there'd be a difference between ijobfor and ijobparallelfor?
And don't forget the [BurstCompile] attribute on your job struct to make sure it's actually bursted
I don't think so, but I don't know for sure. I think IJobFor is just a simpler API
that suits me!
hah. conceptually, turning a 2d array into a flat array is simple. but my brain is sure taking its time
I usually use y * width + x to convert from a 2D index to 1D. If your container has different sized rows/colums you could just use NativeMultiHashMap but it's going to be way slower.
I just had to stare at it until my brain caught up it, haha
so I'm reading through the IJobFor page
i'm confused as to whether it's giving me three alternatives ways to run the job, or three steps i need to complete to run it
with
job.Run(position.Length);
then
JobHandle sheduleJobDependency = new JobHandle();
JobHandle sheduleJobHandle = job.Schedule(position.Length, sheduleJobDependency);
then
JobHandle sheduleParralelJobHandle = job.ScheduleParallel(position.Length, 64, sheduleJobHandle);
It's just showing the 3 different ways to run the same job
Yeah
hm, job.ScheduleParallel doesn't autocomplete
instead I get the option of job.Schedule<>
with whatever this is https://imgur.com/a/UmRC8BZ
Are you sure you've included using Unity.Jobs; in the file where you're scheduling the job?
yes, it's in
JobHandle and all that show up fine
oooh no i got it
i'm an idiot
i made it an IJob not an IJobFor π
okay, I'm nearly there - I'm just not sure how to allocate the array of ints it's writing to
hello, I am new to unity dots, and have been watching tons of material and documentation to learn to use this entities components system. I just noticed changes where you must manually add the package via git include within the Unity editor now-- to that effect which version of Unity is most stable or intended to be used with DOTS/2d.entities/tiny build examples/packages? I cannot locate this, I don't trust "it works with any version above <insert_version_info>", what version do most of you use when working with DOTS/2D DOTS packages now?
I got this:
For dots in general 2020.1 minimum. For Tiny I think it's like 2020.1.3 or something, the getting started post says the exact required version
ok thank you I will look for this post
I assume that means I can't use a native list?
For writing in parallel you want to use the ParallelWriter wrapper for your container. So you get the wrapper returned from list.AsParallelWriter and pass that into the job instead
It's a little more complicated if you don't know the exact size of the list when you're passing it into the job though
So you can use a list either way, but do you know the exact size when you're passing it in?
maybe I should just describe what I'm trying to do more generally so I don't confuse myself any more
I'm passing in the map dimensions, two tile ids (representing a flat array index), and finding the tile IDs between them. and I'd like to output those tileIDs in a list
I think I can guess the size of the list before the job but i'm not entirely sure
Well you either need the exact size or you need to make the list at least large enough that it would not have to resize itself while your job is running
I think it's math.Ceil(sqrt(x2-x1)^2 + (y2-y1)^2)
Actually I guess you could use NativeQueue instead
I think that wouldn't require you to know the size?
I'll try it
But then if you need random access after your job you'd have to copy it into an array afterward
can you dequeue from either head?
Nope
queue.ToCopy should just be a memcopy if you need to go that route
i've never heard of it
It's a wrapper around the container specifically made for writing to containers in parallel jobs. Basically a way for unity to prevent people from doing crazy stuff like trying to read and write to the same index of a container from separate threads
I see - how do I use it? what namespace is it under?
It's just a function on the container - list.AsParallelWriter(), queue.AsParallelWriter(), array.AsParallelWriter(), etc
So like
var list = new NativeList<int>(10, Allocator.TempJob);
var writer = list.AsParallelWriter();
var job = new ParallelJob{List = writer}.ScheduleParallel(10, 8, jobHandle);
hm. so if I initialise a nativearray, it should have a asparallelwriter() in its autocomplete?
I must be missing a namespace
I have Unity.Collections
OH it's for lists, not arrays
Oh yeah apparently NativeArray doesn't have it, every other container does. Weird
Or the indexer
it says I can't apply indexing to it
I also probably should be passing in a block of lists, anyway ...
Yeah I guess you need to use AddNoResize
I sure hope it doesn't need to resize!
If by block of lists you mean a list of lists - native containers can't contain native containers
but going back to my use case - my goal here is to end up with lots of different lists of ints
representing these lines
Hmm, it kind of sounds like you might want a NativeStream? It's a bit complicated though for your first dive into jobs
it is a bit - I thought it might be a reasonable step up from 'update positions of these projectiles'
on the other hand, I'm just trying to parallelise one function, I thought I might have a chance
There's not much docs on them but it sounds like it might be what you want: https://github.com/needle-mirror/com.unity.collections/blob/master/Unity.Collections.Tests/NativeStreamTests.cs
Basically you can write an arbitrary number of values to an index, then read them back after
before I get to that, I think there's one other problem here
which is that I'm only allocating one native array (or list or stream)
but I'd like to allocate one per job
should I be allocating the array in the struct?
is that allowed?
You can allocate a temp container in the job, but you can't get that container out. If you want data from a job you need to pass a container in. Also you should try to minimize how many jobs you're scheduling as much as possible, this is why you generally want to use a single container in IJobFor if possible
A lot of times people come in with performance problems and it turns out they're scheduling 1000 jobs at once - not a good idea
IJobFor is already doing the job of splitting the work onto multiple threads based on the batch size you give it
you get what I'm trying to do, right? like, basically coming up with a bunch of rays fired along a 2d map. it could form the basis of LOS or Visibility in a roguelike, for example
how would you set it up to do that with jobs?
or would you not bother
(jobs/dots/etc)
My roguelike I'm making is full on ECS - I just do my fov/pathfinding each on their own thread/chunk with burst, and it's plenty fast for me, even with a lot of enemies. But that's just me, depending on what you're doing you might really need to maximize performance
for example, right now in my prototype I can do 10,000 bresenham rays for 15 units in 8ms. which is fast, but it sounds like jobs should be faster
oh, that's cool!
If you want to really go hard you could use ECS and have each "ray" be an entity then let ECS do the job of splitting all the work up nicely for you
the thing is, i'd like to have lots of units - and this kind of experimentation now is important so I can set some goals/expectations
you know, can I do a fast FOV for 10 units? 100? more? at 60fps? etc
and it seems like 100 units all shadowcasting at the start of an update cycle would be much faster in parallel than sequentially
There's an example of my naive solution with a few thousand enemies doing FOV checks
oh wow
Runs pretty well, and that's with pretty naive fov - not making much effort to parallelize, just letting ECS handle that and running it in burst
I converted a really nice C++ version I found online, let me see if I can find it
i'm trying to see if it involves raycasting/bresenham or something to that effect
This was the original http://www.adammil.net/blog/v125_Roguelike_Vision_Algorithms.html
cos ideally I could peek at your notes and then I wouldn't ahve to bother you π
It's entirely custom from what I could see
oh yes that's one I was going to try at some point
I'll pastebin my C# version
One second
As you can see I'm not using jobs at all - like I said above I just run it in burst and it Goes Fast
And ECS handles all the parallel job stuff for me
how fast is fast?
so wait, you're not using jobs, but the ECS parallelises it anyway?
Well I mean I'm not using any jobs within the algorithm itself. And yeah - ECS will parallelize across chunks of entities
so is my problem that I'm just coming at it from a naive interpretation of what jobs/ecs/dots etc is used for?
I haven't done any profiling on it - but you can see from the link to my forum thread that it runs pretty well even in the editor
With thousands of monsters
Well the way I think of it is - Burst makes stuff go fast, and ECS makes you write your game in a way that helps burst go fast
And also forces you to nicely separate stuff and think about how your computer is using your data
But don't get me wrong, there's a lot of downsides. It's still early. And honestly Unity should be compensating me for the carpal tunnel I have from writing all the boilerplate it requires
oh boy do I feel that
I think I need to mentally switch gears for now - I've been hopefully bashing my head against ECS all day now - but would you mind terribly if I asked you some more roguelike ECS questions in the future?
in spite of the fact that I didn't get to do what I wanted, it feels like the closest I've come to it in unity's ECS so far
I don't mind
cheers
are there any hard limitations when working with DOTS then? if you intend on selling a game made as a 2D rpg with tables and data, or maps, you mentioned having to know the size of arrays, can you not work with dynamic resizing lists in DOTS? or do you just offload data as binary files and just use lists or fixed arrays as temporary data holders?
have a good one!
You can use resizable lists all you want, you just can't resize a list inside a parallel job. You can resize all you want inside a single threaded job - up to some limit based on cache size
oh parallel job is threading?
Jobs can be run on a single thread or multiple threads or even the main thread, based on what you need
oh nice
hmmm I wonder if there is a way to instantiate an array at runtime in a single thread, resize it, but then move that to a parallel job thread for work
there isn't really any hard limits, but there are a lot of unfinished things that you will have to work around/with to get what you want out of it
using it as a core simulation, logic, networking, has been plenty easy and enjoyable for my game
but getting the hybrid setup right has been the pain point, so make sure you pick one way and double down on it
yes of course, all of the native and ecs data structures can be moved around from main thread to job threads and back. you have to make sure you pay attention to reading/writing when in job threads (it will warn you)
its much easier than you might think as well.
How can i capture a local variable within the lambda function of entitites.foreach?
public float SomeVal;
void override OnUpdate()
{
float someVal = SomeVal; // You can use anything in OnUpdate within the lambda
Entities.ForEach(...=>{
//use someVal
});
}```
does that help? Basically anything in the Update can be captured by the lambda.
Writing out a value you need to use a native container or nativereference though
so every variable in OnUpdate is captured automatically?
yup
ok thanks. but then im back to my previous problem with this error: "IndexOutOfRangeException: Index 0 is out of restricted IJobParallelFor range [93...101] 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."
any tip why this is happening?
Have a link to the code? If I had to guess. I'm expecting you're doing something maybe like
void override OnUpdate()
{
NativeArray<float> someVals...;
Entities.ForEach(...=>{
var thing = someVals[i];
}).ScheduleParallel();
}```?
When you call ScheduleParallel a job is created for every chunk - the number of entities in a chunk will depend on the size of the entities. Say, for example 93 entites can fit in a chunk, job A on thread 1 will iterate indicies 0-92, job B on thread 2 may then be doing the rest (93-101) - that error I guess is saying that the second instance of the job is accessing an index of the array out of this range. Which I think should be fine as long as you're not writing to it - you just need to explicitly say you're only reading from it:
```cs
NativeArray<float> someVals...;
Entities.WithReadOnly(someVals).ForEach(...=>{
var thing = someVals[i];
}).ScheduleParallel();```
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
float dt = Time.DeltaTime;
NativeArray<ParticleComponent> particles = GetEntityQuery(ComponentType.ReadOnly<ParticleComponent>()).ToComponentDataArray<ParticleComponent>(Allocator.TempJob);
JobHandle handle = Entities.WithReadOnly(particles).ForEach((ref ParticleComponent particle, ref Translation translation, ref ParticleAccelerationComponent particleAcceleration) => {
for (int i = 0; i < particles.Length; i++)
{
particleAcceleration.acceleration = 1f * particles[i].velocity; // no real calculation.
}
}).Schedule(inputDeps);
handle.Complete();
particles.Dispose();
return handle;
}
}```
I only need ReadyOnly access on the NativeArray particles.
First thing I see is your lambda has ref ParticleComponent particle - that's asking to write to ParticleComponent
which is the same type as the nativearray you're passing in
oh... just found out i need to pass in the in components last...
public class ComputeAccelerationJobSystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
float dt = Time.DeltaTime;
NativeArray<ParticleComponent> particles = GetEntityQuery(ComponentType.ReadOnly<ParticleComponent>()).ToComponentDataArray<ParticleComponent>(Allocator.TempJob);
JobHandle handle = Entities.WithReadOnly(particles).ForEach((ref ParticleAccelerationComponent particleAcceleration, in ParticleComponent particle, in Translation translation) => {
for (int i = 0; i < particles.Length; i++)
{
particleAcceleration.acceleration = 1f * particles[i].velocity; // no real calculation.
}
}).Schedule(inputDeps);
handle.Complete();
particles.Dispose();
return handle;
}
}
but still the same. or did i need to remove particlecomponent completly from the lambda?
sorry I just noticed you're also using the out of date JobComponentSystem - swap that out to SystemBase - and yea, remove the particlecomponent completely from the signature
When you swap to SystemBase your OnUpdate will no longer have the inputDeps argument and you won't need (by default) to pass it to schedule
one important question... how can i see the version i'm using? ^^ cant find it as installed in the packet manager.
do you have enable preview packages enabled in your preferences? It doesn't let you add the package but once it's installed it should show up along with the version number
ahh... i had to enable "Show dependencies" .
ok. i can get rid of the particlecomponent in the lamba. but in the i end, i need two NativeArrays.
NativeArray<ParticleComponent> particles
NativeArray<Translation> particlesPositions
what i cant get rid of, is the translations. but i think there was a way to know the index of the current entity in the native array?
ok thanks @amber flicker . seems like i got it working.
oops sorry, missed the message above until you pinged. Nice one π
A question on click detection in DOTS: how do I filter out clicks on UI elements and entities that aren't part of the camera's culling mask? All the online examples I found just use physicsWorld.CastRay, which works for detecting a clicked entity but it goes right through UI and selects invisible entities. I tried setting CollidesWith = (uint) Camera.main.cullingMask in the CollisionFilter but that doesn't seem to do anything.
(I'm using a hybrid system where UI elements are GameObjects)
I guess you're using Unity physics for the raycasts? In which case you'd be mixing two physics systems - the dots one and the traditional one - they know nothing about each other.
I haven't done it but I'd expect your options to be either:
a) create entity/unity physics colliders/representations for every UI element or
b) do a traditional Physics.raycast pass for UI before Unity Physics raycasts
esp b) if you expect UI to always be on top
Yeah, right now I'm doing if (EventSystem.current.IsPointerOverGameObject()) to detect UI elements
Still doesn't help with the culling issue though
hmm can't you just set a static or singleton property when that's true? Or am I missing something?
The culling? My issue is that the raycast detects hits on layers it's not supposed to
ah I think I misunderstood.. ok so the issue is, just with the pure dots physics stuff, the raycast doesn't seem to respect the camera culling layers right?
Yes
Don't you set the layers on the camera raycaster component?
I haven't touched physics at all yet sorry - I'm not sure how the dots objects would know they were on a certain layer - i.e. I'm not sure that information gets converted? You might have to set their collision filters on conversion or something? #outofmydepth
The draw layer is in RenderMesh
Whats a good way to create a octree that is useable in a job? so far i create it just with a nodeclass, containing its childs. but i think that isnt going to work in a job. i think i need to create a native array of all nodes, which contain the indices of its childs?
It's definitely there and if it wasn't, camera culling wouldn't work at all
so when you inspect an entity via the debugger, there's a collision filter or whatever setup with the correct layer?
My issue is, from what I understand you're supposed to set Filter on RaycastInput to determine collision layers, yet it doesn't seem to work
Yeah
When I set Filter to 0 it disables collision detection entirely so clearly it does something, the question is why is my input not working
In your original question you said it detects an entity but goes 'right through UI... where UI elements are GameObjects' so I'm pretty confused - you're saying those UI elements have dots representations? They're converted with physics colliders?
Nah, I solved the UI thing with the code bit from earlier
There's two separate issues here
Let me make some screens to illustrate
So this is my game UI. Issue #1 is that if I click the UI element (where it says "Tree") the raycast goes right through it and selects the tree behind it. This is solved by adding if (EventSystem.current.IsPointerOverGameObject()) to detect the GameObject UI element
Issue #2 is I'm using an isometric camera with multiple levels and I'm using camera culling layers to hide levels above the currently selected (i.e. if the camera is on level 2, the culling mask includes only UI, level 1, level 2)
When I go down a level, it is properly culled by the camera, yet I can still click the tree on the upper level
So the issue is, I set the Filter for the raycast to use e.g. layers 8 and 9 (for level 1&2) but it still collides with entities on layers 9, 10, 11
var colFilter = new CollisionFilter
{
BelongsTo = (uint)Camera.main.cullingMask,
CollidesWith = (uint) Camera.main.cullingMask
};
var rayInput = new RaycastInput
{
Start = origin,
End = origin + Camera.main.transform.forward * RaycastDist,
Filter = colFilter
};```
collision filter doesn't have anything to do with camera culling mask
it's part of the physics material
you'd have to check which entities are culled and set those entitity's collision filters first
How would I do that then?
if you select the tree entity in the entity debugger you should be able to see the value for the collision filter
i think with physicsmaterial it might not be on the entity, they do weird stuff
oh wow, that's not great. I mean, thinking about it, as a property of a physics material it makes some sense but I wonder how that works with blobs and whatnot behind the scenes.
seems you'd have to copy the physicscollider, set a different collisionfilter and replace it
https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/UnityPhysicsSamples/Assets/Tests/Restitution/SpawnBouncyRandomShapesAuthoring.cs
for example with restitution but should be same with collisionfilter instead
fucking blobassets
yea ideally you'd set them to equivalent of the camera culling layers on conversion and not change at runtime by the looks of it?
seems you can modify it directly too without copying but gotta be careful with that since default setting is to use same collider for multiple entities if they're the same during conversion so you'd be modifying them all
damn this makes me remember what i hate about new physics, unity just expects all your colliders to never change
I'm not actually converting, I'm instantiating all my entities manually
But yeah, not change it at runtime is not an option
Stuff can move between levels which updates the culling masks
blobs + runtime... good luck π
this post has some code with changing directly by dereferencing the pointer https://forum.unity.com/threads/toggling-collision-events-via-script.851761/#post-5619643
should be fine if they're all unique from instantiating manually
I really hope they come up with some kind of safely mutable blob thing..
and a better blob asset store or something... it's super unfriendly for anything but subscenes / association with anything other than a gameobject
Speaking of manually instantiating, I've noticed MeshCollider.Create has a CollisionFilter parameter. Anyone know what that's about?
As for my raycast, I might just be better off comparing hits vs the layer mask manually
If it were me, I would avoid changing colliders at runtime. I'd maybe just add the Disabled tag to an entity when it changes level and ignore all the layer stuff.
The solution I have in mind is take all the hits on the raycast, foreach them and check against the layer in RenderMesh
I'm sure that could work. It's just that if you want to raycast against what you can see.. why not just disable what is hidden and let everything do what it's supposed to. Unless you have a reason for it to exist even when it's not visible obviously.
Well yeah, stuff on other levels is still active and should still have projectile collisions and such
ok yea in that case... sounds like you wouldn't want to be messing with collision layers necessarily either
Damnnn... sometimes i start to hate data oriented programming... still cant decide how i actually construct my combat system and there no examples. I have a player as an entity and his weapon as an entity. Player has an inventory that references his item-entities. Player clicks on mob, player should start to attack that mob. The problem is that the player and his weapon are seperate entities... The inventory items should get notified about the attack to deal damage or to execute unique logic :/