#archived-dots

1 messages Β· Page 191 of 1

warm panther
#

Adding and Removing is a "rare" event, only once every couple of seconds or minutes.

#

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!

amber flicker
#

@warm panther I may be misunderstanding but how about a e.g nativehashmap in a system that stores your entity->index map?

odd cipher
#

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

warm panther
#

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.

slim nebula
#

is a memoryref of a stack variable an okay thing to do? cs new MemoryRef<PoseSet>(ref idleCandidates),

slim nebula
#

the answer appears to be no

zinc plinth
#

ofc it's not, it's the stack..

slim nebula
#

look I dunno how this magic burst stuff works gawd

#

lol

tulip girder
#

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.

hollow sorrel
#

@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

tulip girder
#

Here Android official site tells me that armeabi-v7a supports Thumb2 Instruction Set.

#

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?

idle glade
#
    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?
deft stump
#

afaik, Unity internally uses jobs.
but they dont jobify your code automatically

stiff skiff
#

I assume you've used the Profiler to check what's really going on?

idle glade
#

no unity stats in game view

#

i will check with profiler

stiff skiff
#

Profiler is always step one when debugging jobs

deft stump
#

you should check the profiler

gusty comet
#

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

idle glade
#

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!

zenith wyvern
#

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

deft stump
#

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.

zenith wyvern
#

There are not two implementations of dots

deft stump
#

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.

zenith wyvern
#

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

idle glade
#

They should have a separate template setup with dots where all packages are preinstalled just like urp and hdrp

zenith wyvern
#

I would agree with that. It's definitely very limited right now

north bay
#

That would lower the entry requirements which unity obviously doesn't want.

zenith wyvern
#

That would be nice but they desperately wanted to get away from letting people easily install preview packages

north bay
#

There is even a Tiny template somewhere

deft stump
#

Does Tiny have Components for UI? All I know that Tiny have but hybrid doesn't are Sprites.

amber flicker
#

Tiny doesn't even have text right? Just sprites?

#

(long time since I've looked)

zenith wyvern
#

No UI yet for tiny

rancid geode
#

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

amber flicker
#

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.

deft stump
#

Can Tiny accomodate, for lack of a better term, game as a service type of game? or is it meant to be casual games?

rancid geode
#

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)

rancid geode
#

but I found it very easy to switch from tiny to hybrid at any time

#

the opposite is more complicated...

amber flicker
#

really useful, thank you. Any video playback? Wondering e.g. how suitable it is for non-game web.

deft stump
rancid geode
#

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"

amber flicker
rancid geode
#

Oh, right, haven't tried anything video-related, so can't help much on that

amber flicker
mint iron
#

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.

odd cipher
gusty comet
#

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;
    }
}```
zenith wyvern
#

@gusty comet For an orthographic camera "fov" is the orthographic size

gusty comet
#

jesus thanks, that works. I've been futsing with the camera for hours

zenith wyvern
#

Yeah the documentation is not too good yet

gusty comet
#

Is the docu open source?

#

Like can I PR changes to it

zenith wyvern
#

Don't think so

warm panther
#

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.

warm panther
#

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.

odd ridge
#

so we're not getting disable/enable components by the end of the year are we ^^

spark glade
#

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 πŸ€”

spark glade
spark glade
#

Nvmd, that didn't help 😦

deft stump
spark glade
#

Man, I tried 2020.2 and Hybrid V2 and it's a complete showstopper once again 😒

zenith wyvern
#

How so

dull copper
#

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

zenith wyvern
#

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

warm panther
#

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. oof

#

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.

amber flicker
#

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.
warm panther
amber flicker
warm panther
#

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.

amber flicker
#

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.

warm panther
#

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.

thorny halo
#

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().

vagrant surge
#

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

north bay
#

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

coarse turtle
#

Yea you don't if you casted it to the right pointer type

warm panther
vagrant surge
#

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

warm panther
#

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.

warm panther
#

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.

mint iron
#

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

warm panther
#

Oof.

#

Counterintuitive.

zenith wyvern
#

But you can add it to an entity query can't you

#

So you still have a shared component basically

warm panther
#

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.

warm panther
#

I mean, with foreach? And how can I read it?

zenith wyvern
#

A chunk component is just an icomponentdata

warm panther
#

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)

mint iron
#

not sure but it would only be shared for the entities in that chunk, each chunk gonna be different

warm panther
#

SharedcomponentData kind of does exactly waht I need, but possibly only in the future (they want to make it non-managed)

zenith wyvern
#

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

warm panther
#

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)

zenith wyvern
#

Yeah you have to change it per entity

#

It's very Not Good

warm panther
#

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

amber flicker
#

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?

warm panther
#

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.

amber flicker
#

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?

warm panther
#

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)

amber flicker
#

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.

warm panther
#

Yeah "not" that, but yes.

amber flicker
#

I definitely try and use the query add/remove components as much as possible

warm panther
warm panther
#

As in, can apply the structural change in parallel across ~100k entities?

amber flicker
warm panther
#

(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)

warm panther
#

Is an archetype a class of entities or is an archetype an EXACT combination of IComponentDatas on an entity?

amber flicker
#

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.

warm panther
#

Hmm.

#

So the Archetype of an Entity isn't a property of the entity.

amber flicker
warm panther
#

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.

amber flicker
warm panther
#

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.

amber flicker
#

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.

warm panther
#

Yep.

#

.Run() is probably not going to cut it at scale for me.

warm panther
#

If I get this right, EVERY structural change is ultimately a sync point?

zenith wyvern
#

Yes, any time there's a structural change all jobs are forced to complete immediately

warm panther
#

So that's what the EntityCommandBufferSystems also do?

#

There's no jobs that continue past these barrier systems?

stable siren
#

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);

zenith wyvern
#

Correct - assuming the barrier system actually makes a structural change on that frame

warm panther
#

Because I get a lot of dependency problems

#

wayyyy past the barriers.

#

Weird.

zenith wyvern
#

The non async version doesn't use jobhandles

warm panther
#

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)

warm panther
#

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.

spark glade
# zenith wyvern How so

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...

stiff skiff
slim nebula
#

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?

zenith wyvern
slim nebula
#

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

slim nebula
#

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

zenith wyvern
#

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

slim nebula
#

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

zenith wyvern
#

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

slim nebula
#

ok

zenith wyvern
#

That's what I woudl recommend anyways

slim nebula
#

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

zenith wyvern
#

I don't think you can do that

slim nebula
#

wait what? then how do I get the data out

zenith wyvern
#

You pass in a native container

#

Populate it, then your container has the data from your job

slim nebula
#

ok but, you can't have another system process it later tho rite?

zenith wyvern
#

Yes you can, but you need to pass the job handle along with the container

slim nebula
#

how would I pass the container to something later?

zenith wyvern
#

And pass in the previous job as a dependency to the new one

slim nebula
#

that container can't go into an IComponentData rite

#

so

#

that means the receiver of that data can't use burst right?

zenith wyvern
#

No. You can put it in your system or wherever you want

#

Yes it can use burst

slim nebula
#

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?

zenith wyvern
#
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

slim nebula
#

data[0]

zenith wyvern
#

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

slim nebula
#

so like increment some index then save the index for the reciever to use

#

ok

zenith wyvern
#

Of course you don't need to store your container on a system like that, just put it wherever you want

slim nebula
#

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

winter onyx
#

so does anyone have a working, real, released game using DOTS?

odd ridge
#

not me but there'a a bunch of them

zenith wyvern
#

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

spark glade
winter onyx
#

v good, v good

spark glade
#

Reminds me that I should post as #madewithunity and maybe get a RT πŸ™

slim nebula
#

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?

slim nebula
#

wait what. can you not store a NativeList inside of a NativeList?

#

UGH

#

alt+f4 I'm done

north bay
#

You can store UnsafeLists inside a NativeList

slim nebula
#

hmm what's an UnsafeList do

#

can you store NativeList inside UnsafeList?

north bay
#

No.

slim nebula
#

poo

north bay
#

It's basically a NativeList without deallocation and job safety checks

slim nebula
#

thanks tho. I don't control the underlying structure (or it would require lots of work to change)

north bay
#

So just a wrapper around void*

slim nebula
#

ah nice

#

good to know

#

is there an unsafearray?

#

hmm yeah I dunno

north bay
#

I don't think there is

slim nebula
#

I'm too tired to think of a solution

#

my brain hurts

north bay
#

You can force set the length of the unsafelist to your array size

#

What are you trying to do?

slim nebula
#

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

compact robin
#

So you want a reference to an element in a native array

north bay
#

Ehhh

#

Do the NativeArrays get reallocated or do they stay the same

slim nebula
#

I do also want that @compact robin

north bay
#

You could just store the ptr to the data

compact robin
#

Can you?

#

Unless you pin it, they get moved around I think

#

Like the address changes hmmm

north bay
#

Well you shouldn't store the ptr to the array, but to the data the native array holds

#

Which won't be moved around

compact robin
#

As in the data would move

#

I don't think the array would move

slim nebula
#

so if I make a class component to GC root the struct, then use unsafeutility in unity to get the ptr, will it change?

compact robin
#

Cuz its using unmanaged mem

north bay
#

Unmanaged mem doesn't move anywhere

compact robin
#

Yeah

slim nebula
#

if I add things to the list tho all my pointers could change

compact robin
#

When you add stuff to like a native collection, they get copied into it

slim nebula
#

is there a way to do an unsafe alloc of a struct? or I just do that with unsafelist or something?

compact robin
#

You wanna access the elements right?

slim nebula
compact robin
#

No they don't get moved

#

Its unmanaged memory

north bay
#

Ye if the array on the thing changes you will point to invalid mem

#

And most likely crash

slim nebula
compact robin
#

Oh a list

slim nebula
#

yeah

compact robin
#

Yeah that makes sense

slim nebula
#

ok but

compact robin
#

Then the only way I can think of is using GCHandle to point to elements

#

But that's a horrible idea lul

slim nebula
#

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

compact robin
#

Or just allocating them yourself

slim nebula
#

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

slim nebula
#

can I just be like Allocator.MakeMeSomeBytes(Allocator.Persistent)

compact robin
#

And just write to that pointer I guess

slim nebula
#

ok perfect

compact robin
#

Yes that's what malloc is for

slim nebula
#

I think I have to do that

compact robin
#

But you have to free memory yourself

slim nebula
#

yup

#

I have a .dispose already. I'll just update that to also do free

compact robin
#

Yeah

slim nebula
#

thanks guys. I have a plan for tomorrow now I guess

north bay
#

Are you going to store the data on your IComponentData?

slim nebula
#

the pointer yeah

north bay
#

So you have two pointers there + their length?

slim nebula
#

no. I will have a type safe ref created from the pointer using unsafeutility

compact robin
#

Huh

#

Im confused

#

Ref to what?

#

Each element?

slim nebula
#

ref UnsafeUtility.AsRef<T>((byte*)ptr);

#

the struct I've allocated

#

which contains a NativeArray

compact robin
#

Oh so a ref to a struct which contains the array

#

Cool

slim nebula
#

yeah

#

the struct will be malloc'd

compact robin
#

Right

slim nebula
#

yeah the insides of the struct are blackbox to me

#

but it's burst compatable

#

just not blittable (uses native containers)

compact robin
#

?

slim nebula
#

the data and functions on it work with burst

compact robin
#

It is still blittable if you have a native container in a struct I think

warm panther
#

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?

slim nebula
#

nope

#

it is not

#

well.. sorry

compact robin
#

Well you can't really have pointers to

slim nebula
#

it's not legal to have on componentdata

compact robin
#

Non-blittable structs

north bay
slim nebula
#

but then I can't use burst @north bay

compact robin
slim nebula
#

but sorry my bad it's blittable, it just has nativecontainers so it can't go on componentdata

compact robin
#

Yeah it has to be blittable

#

You can't have pointers to non-blittables, its a C# thing

slim nebula
#

wait what

#

is NativeContainer not blittable?

north bay
#

It is not

slim nebula
#

rip

warm panther
#

Wat.

slim nebula
#

ok so pointers go out the window

#

I dunno what to do

warm panther
#

Native containers ought to be blittable. Not deep blittable, but shallow? *goes to check ... *

compact robin
#

Im confused then

#

How are they used in jobs

#

0-0

slim nebula
#

yeah

compact robin
#

I always thought they were blittable

slim nebula
#

how are they used in jobs

compact robin
#

Too bad my Unity's down

north bay
#

Unity does some magic and removes the dispose handle

#

Which is what makes them not blittable

#

If i remember correctly

compact robin
#

Oops

#

I mentioned it wrongly

#

I meant to say

#

You can only have pointers to blittable types, LOL

warm panther
slim nebula
#

DisposeSentinel

warm panther
#

Yep

#

Derp.

slim nebula
#

is reference type

warm panther
#

Just saw it.

#

Cute.

#

How even XD

slim nebula
#

it's so silly. it's burst compatable but there's like no way to get that data around in ECS without disabling burst

warm panther
#

Well Burst is not a real compiler anyhow. angry

compact robin
#

Why not just roll your own native container that is blittable

#

🧐

north bay
#

Cuz they already exist

warm panther
#

I use fixedlists a lot.

slim nebula
#

wat

warm panther
#

Like, a criminal lot.

north bay
#

The Native variants are just wrappers around the Unsafe ones

slim nebula
#

oh

#

so unsafe ones are blittable?

north bay
#

Ye

compact robin
#

Oh wow there are unsafe ones?

#

Cool

slim nebula
#

oh. no I can't change that

north bay
#

I store them on my components all the time

slim nebula
#

without significant effort reworking kinematica

#

i dunno how it all works

north bay
#

Can't you copy their data into your array?

#

How is the data written to it?

slim nebula
#

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

compact robin
#

I don't think its burst compatible if its not blittable

#

It just doesn't make sense

slim nebula
#

jobs use it just fine

#

burst code works on it just fine

compact robin
#

0-0

slim nebula
#

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

north bay
#

The data are arrays? Store their ptr in your component

slim nebula
#

and u just like... cant...

north bay
#

Make sure it is only accessed while it's valid

#

And you are good

#

NativeArray.GetUnsafePtr()

slim nebula
#

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

compact robin
#

Ok so you just wanna use a nativecontainer, and you need a ref to it

#

🧐

slim nebula
#

yeah well.. I need a ref to the struct that contains the native container

compact robin
#

Yeah then use GCHandle.Alloc

#

And then when you wanna access it do GCHandle.Target

slim nebula
#

there's really just no other way is there

compact robin
#

But its a shitty way imo

#

I used that to run managed stuff on Unity's worker threads

slim nebula
#

the only other options are to do it without burst, or to rewrite a bunch of kinematica to use IComponentData compatable data

compact robin
#

πŸ€·πŸ»β€β™€οΈ

slim nebula
#

i mean

compact robin
#

Unity is just weird xd

slim nebula
#

I learned a lot from u guise

#

so thanks for that πŸ˜„

north bay
compact robin
#

Lolll

warm panther
#

ISharedComponentData Question - is the ABSENCE of the shared component also a value for chunking purposes, or is it the same as default?

compact robin
#

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

warm panther
#

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 ... *
amber flicker
warm panther
#

Thank you Timboc

slim nebula
#

cause the architype would have to change

warm panther
north bay
#

Can you use SharedComponents in bursted IJobChunks? That was the biggest issue why I never used them

slim nebula
#

since there's only ever one, you can just "hard-code" the offset into the subscene however you like

warm panther
slim nebula
#

@warm panther the idea is you want to load from disk into memory once, then replicate instances frrom memory

warm panther
slim nebula
#

do you'd have prefabs in a subscene, load the subscene (which loads the prefabs into memory) then instantiate the prefabs

amber flicker
warm panther
#

I was planning on using a subscene to create all my prefabs.

#

(prefab entities, that is)

slim nebula
#

loading a subscene multiple times would load the data multiple times from disk. I dont think that's what you want

warm panther
#

so I could see and edit them kind of like an inventory of the stuff I have (as a dev, not player).

warm panther
slim nebula
#

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

warm panther
#

That's pretty close to what I need for initialization. that feels like a clean, if indirect, approach.

slim nebula
#

it seems to be working so far

warm panther
#

cool

slim nebula
#

dats muh subscene

#

prefab is entity converted already

#

so subscene loads into prefab entity, and I can just instantiate

warm panther
#

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)

slim nebula
#

there's a component it adds... I forget which direction it goes

zenith wyvern
#

You just call conversionSystem.GetPrimaryEntity on the child gameobject

#

During conversion. Children are guaranteed to be converted first.

warm panther
#

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.

zenith wyvern
#

Thankfully in my games I haven't needed hierarchies beyond a single child. The transform system in ECS is too complicated for my brain

warm panther
#

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.

zenith wyvern
#

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

warm panther
#

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)

warm panther
# zenith wyvern There is a ConvertToEntity (Stop) Monobehaviour

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)

#

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)

zenith wyvern
#

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?

warm panther
#

This is what my asset toolchain gives me, but I can't do it for those ancient asteroid assets πŸ˜„

warm panther
#

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.

zenith wyvern
#

It sounds like you could be using ConversionSystems too to keep things cleaner if you aren't already

warm panther
#

So I made it into an InitializationSystem.

zenith wyvern
#

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

warm panther
#
    /**
     * 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)

zenith wyvern
#

Rather than iterating the linkedgroup, iterate the gameobject transform and call getpeimaryentity for every child

#

Sorry typing on phone

warm panther
#

Hrrm.

#

THANK YOU. That actually works.

slim nebula
#

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

mint iron
#

what was the issue with storing pointers to the kinematica structs?

slim nebula
#

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

mint iron
#

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.

slim nebula
#

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

mint iron
#

pretty much everything in unity ecs is using 'unsafe', i wouldnt worry about it

slim nebula
#

hmm ok maybe it's worth a try then. I assume whatever* is blittable?

#

it appears to be... no errors on basic tests...

mint iron
#

assuming whatever is unmanaged yeah

slim nebula
#

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

mint iron
#

yeah, you're right it would refuse to compile if the struct was managed πŸ˜„

slim nebula
#

anyone here use VS Code for their unity dev? any limitations compared to normal visual studio?

slim nebula
mint iron
#

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.

slim nebula
#

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

mint iron
#

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.

slim nebula
#

ok

deft stump
#

just go cmd for git

slim nebula
#

I do myself but

#

other people

#

heh

#

I prefer command line git myself

deft stump
#

fire them for not using cmd git

#

heh

slim nebula
#

hahaha

mint iron
#

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.

slim nebula
#

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

mint iron
#

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.

slim nebula
#

yeah ok

coarse turtle
#

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)

slim nebula
#

good to know thanks

#

nope can't make a pointer to those kinematica types

#

you were right

#

rip in pepperonis

slim nebula
#

can I just make a struct, mark it as [BurstCompile] and call a method on it? does that work?

odd ridge
#

yes

slim nebula
#

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

odd ridge
#

you can put it on static functions too so you don't need a struct, depends what you need

slim nebula
#

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

warm panther
#

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.

slim nebula
#

I think the physics collisions almost always raise 2 points

#

just cause of how the formulas work

warm panther
#

Oh, points cause events?

slim nebula
#

that's my understanding yeah, each collision point will cause shit

warm panther
#

So if I have 2 mesh colliders, there could be... a lot of events?

#

Wow.

#

I should write that system to not use collisions. πŸ˜„

slim nebula
#

I dunno, should still be like 2 I think

north bay
#

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

warm panther
#

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.

mint iron
slim nebula
#

hmm interesting. i might try that later

warm panther
#

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 πŸ¦†

slim nebula
deft stump
#

so all this time refactoring... I decreased my perf cost by 0.02 ms

warm panther
#

🚀

coarse turtle
#

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 πŸ€”

opaque escarp
#

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

zenith wyvern
#

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

opaque escarp
#

ty

opaque escarp
#

is the order of the OnUpdate invocations guaranteed and determined by the [UpdateB/A] attributes?

warm panther
#

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)

coarse turtle
#

you can try to override OnStartRunning() although if BubbleQuery has 0 entities and then has 1 entity again, OnStartRunning() would run again

warm panther
#

Wow never heard of these.

#

Cool.

#

Feels slightly better.

coarse turtle
#

There's an additional OnStopRunning too if you need that also

warm panther
#

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.

mighty remnant
#

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.

odd ridge
deft stump
# odd ridge 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

opaque escarp
#

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

deft stump
#

Happy new year dots devs

odd ridge
mint iron
opaque escarp
#

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?

deft stump
odd ridge
#

@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

opaque escarp
#

well how do I add a TimerLessThan0 component en mass then, seems like kicking the can farther down the road haha

odd ridge
#

@opaque escarp with an ECB

mint iron
#

you could store off the entities to a list, and then use the removecomponent(nativelist), im not sure if its faster though

opaque escarp
#

I'm using the ECB right now

odd ridge
#

that's the way ^^

opaque escarp
#

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

odd ridge
#

it depends what you want to do, each could be better for different cases

mint iron
#

probably best to test it, they can do some weird stuff internally

opaque escarp
#

all righty, thank you

zenith wyvern
# opaque escarp 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

opaque escarp
#

ChangeFilters are something I haven't looked into, I'll do so now, ty

zenith wyvern
#

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

dull siren
#

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

zenith wyvern
#

Disable burst and put a debug log inside the loop in CalculatePath to verify it's doing what you expect

dull siren
#

Well I log the path length immediately after calling CalculatePath, it is greater than 0

zenith wyvern
#

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.

dull siren
#

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

zenith wyvern
#

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.

dull siren
#

Oh Temp vs TempJob are different contianers

zenith wyvern
#

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

dull siren
#

Does CalculatePath become a void then? And I just pass the path variable?

zenith wyvern
#

Yeah that is typically how you do it

dull siren
#

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!

zenith wyvern
#
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

dull siren
#

Ah, the edit you made makes more sense

zenith wyvern
#

Mixed that up a little

#

Yeah

dull siren
#

I was about to say, I am setting the values of the list first

zenith wyvern
#

Hahah yeah

dull siren
#

I could do that normally though right?

#

ListA = ListB

zenith wyvern
#

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

dull siren
#

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;

zenith wyvern
#

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

dull siren
#

Ok so I would need to copy if I had to get another list

zenith wyvern
#

Yeah

dull siren
#

It was all just from breaking out the function for populating the path

opaque escarp
#

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?

tawdry tree
#

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?

opaque escarp
#

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

tawdry tree
#

A class inheriting from MonoBehavior could have some of the boilerplate in that particular file

opaque escarp
#

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?

grim plinth
#

I'm trying to figure out how to get a jobsystem to execute on IJobParallelFor and it's not looping or manipulating data

last lintel
#

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?

zenith wyvern
#

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

last lintel
#

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?

zenith wyvern
#

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

last lintel
#

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

zenith wyvern
#

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

last lintel
#

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?

zenith wyvern
#

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

queen mantle
#

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?

zenith wyvern
#

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

last lintel
#

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

zenith wyvern
last lintel
#

it's scheduled in a Monobehaviour, does that affect performance at all?

zenith wyvern
#

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

last lintel
#

so you don't think there'd be a difference between ijobfor and ijobparallelfor?

zenith wyvern
#

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

last lintel
#

that suits me!

last lintel
#

hah. conceptually, turning a 2d array into a flat array is simple. but my brain is sure taking its time

zenith wyvern
#

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.

last lintel
#

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);

zenith wyvern
#

It's just showing the 3 different ways to run the same job

last lintel
#

right

#

so the third one is the massively parallel option right?

zenith wyvern
#

Yeah

last lintel
#

hm, job.ScheduleParallel doesn't autocomplete

#

instead I get the option of job.Schedule<>

zenith wyvern
#

Are you sure you've included using Unity.Jobs; in the file where you're scheduling the job?

last lintel
#

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

bold sleet
#

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?

last lintel
zenith wyvern
#

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

bold sleet
#

ok thank you I will look for this post

last lintel
#

I assume that means I can't use a native list?

zenith wyvern
# last lintel I got this:

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?

last lintel
#

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

zenith wyvern
#

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

last lintel
#

I think it's math.Ceil(sqrt(x2-x1)^2 + (y2-y1)^2)

zenith wyvern
#

Actually I guess you could use NativeQueue instead

#

I think that wouldn't require you to know the size?

last lintel
#

I'll try it

zenith wyvern
#

But then if you need random access after your job you'd have to copy it into an array afterward

last lintel
#

can you dequeue from either head?

zenith wyvern
#

Nope

last lintel
#

no biggie

#

sorry, what was that stuff about the parallelwriter?

zenith wyvern
#

queue.ToCopy should just be a memcopy if you need to go that route

last lintel
#

i've never heard of it

zenith wyvern
#

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

last lintel
#

I see - how do I use it? what namespace is it under?

zenith wyvern
#

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);
last lintel
#

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

zenith wyvern
#

Oh yeah apparently NativeArray doesn't have it, every other container does. Weird

last lintel
#

okay so how do I write to this thing

#

addnoresize?

zenith wyvern
#

Or the indexer

last lintel
#

it says I can't apply indexing to it

#

I also probably should be passing in a block of lists, anyway ...

zenith wyvern
#

Yeah I guess you need to use AddNoResize

last lintel
#

I sure hope it doesn't need to resize!

zenith wyvern
#

If by block of lists you mean a list of lists - native containers can't contain native containers

last lintel
#

but going back to my use case - my goal here is to end up with lots of different lists of ints

#

representing these lines

zenith wyvern
#

Hmm, it kind of sounds like you might want a NativeStream? It's a bit complicated though for your first dive into jobs

last lintel
#

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

zenith wyvern
#

Basically you can write an arbitrary number of values to an index, then read them back after

last lintel
#

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?

zenith wyvern
#

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

last lintel
#

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)

zenith wyvern
#

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

last lintel
#

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!

zenith wyvern
#

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

last lintel
#

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

zenith wyvern
#

There's an example of my naive solution with a few thousand enemies doing FOV checks

last lintel
#

oh wow

zenith wyvern
#

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

last lintel
#

that looks super useful, thank you

#

what algorithm are you using for your FOV?

zenith wyvern
#

I converted a really nice C++ version I found online, let me see if I can find it

last lintel
#

i'm trying to see if it involves raycasting/bresenham or something to that effect

zenith wyvern
last lintel
#

cos ideally I could peek at your notes and then I wouldn't ahve to bother you πŸ˜„

zenith wyvern
#

It's entirely custom from what I could see

last lintel
#

oh yes that's one I was going to try at some point

zenith wyvern
#

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

last lintel
#

how fast is fast?

#

so wait, you're not using jobs, but the ECS parallelises it anyway?

zenith wyvern
#

Well I mean I'm not using any jobs within the algorithm itself. And yeah - ECS will parallelize across chunks of entities

last lintel
#

so is my problem that I'm just coming at it from a naive interpretation of what jobs/ecs/dots etc is used for?

zenith wyvern
#

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

last lintel
#

i did, yeah

#

it's impressive

zenith wyvern
#

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

last lintel
#

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

zenith wyvern
#

I don't mind

last lintel
#

cheers

bold sleet
#

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?

last lintel
#

have a good one!

zenith wyvern
bold sleet
#

oh parallel job is threading?

zenith wyvern
#

Jobs can be run on a single thread or multiple threads or even the main thread, based on what you need

bold sleet
#

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

low tangle
#

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

low tangle
#

its much easier than you might think as well.

mighty remnant
#

How can i capture a local variable within the lambda function of entitites.foreach?

amber flicker
#
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

mighty remnant
#

so every variable in OnUpdate is captured automatically?

amber flicker
#

yup

mighty remnant
#

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?

amber flicker
#

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();```
mighty remnant
#
{
    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.
amber flicker
#

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

mighty remnant
#

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?

amber flicker
#

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

mighty remnant
#

one important question... how can i see the version i'm using? ^^ cant find it as installed in the packet manager.

amber flicker
#

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

mighty remnant
#

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?

mighty remnant
#

ok thanks @amber flicker . seems like i got it working.

amber flicker
#

oops sorry, missed the message above until you pinged. Nice one πŸ‘

raven grail
#

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)

amber flicker
#

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.

raven grail
#

I am

#

And that's only true for the UI part

amber flicker
#

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

raven grail
#

Yeah, right now I'm doing if (EventSystem.current.IsPointerOverGameObject()) to detect UI elements

#

Still doesn't help with the culling issue though

amber flicker
#

hmm can't you just set a static or singleton property when that's true? Or am I missing something?

raven grail
#

The culling? My issue is that the raycast detects hits on layers it's not supposed to

amber flicker
#

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?

raven grail
#

Yes

zenith wyvern
#

Don't you set the layers on the camera raycaster component?

amber flicker
#

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

raven grail
#

The draw layer is in RenderMesh

mighty remnant
#

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?

raven grail
#

It's definitely there and if it wasn't, camera culling wouldn't work at all

amber flicker
#

so when you inspect an entity via the debugger, there's a collision filter or whatever setup with the correct layer?

raven grail
#

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

amber flicker
raven grail
#

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

hollow sorrel
#

post code

#

how do you set your filters

raven grail
#
                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
                };```
hollow sorrel
#

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

raven grail
#

How would I do that then?

amber flicker
#

if you select the tree entity in the entity debugger you should be able to see the value for the collision filter

hollow sorrel
#

i think with physicsmaterial it might not be on the entity, they do weird stuff

raven grail
#

Yeah there's nothing on the Entity

amber flicker
#

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.

hollow sorrel
#

fucking blobassets

amber flicker
#

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?

hollow sorrel
#

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

raven grail
#

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

amber flicker
#

blobs + runtime... good luck πŸ˜„

hollow sorrel
#

should be fine if they're all unique from instantiating manually

amber flicker
#

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

raven grail
#

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

amber flicker
#

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.

raven grail
#

The solution I have in mind is take all the hits on the raycast, foreach them and check against the layer in RenderMesh

amber flicker
#

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.

raven grail
#

Well yeah, stuff on other levels is still active and should still have projectile collisions and such

amber flicker
#

ok yea in that case... sounds like you wouldn't want to be messing with collision layers necessarily either

stone osprey
#

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 :/