#archived-dots

1 messages ยท Page 265 of 1

rotund token
#

this is just 1 type of system though right

#

you could have 10-50 of these!

rustic rain
#

yeah, but I spam it

#

for every room

#

irrelevant

#

whether I have entities at all or not

#

I can do query check, before actually doing all prep work

#

and I also can add some tags

#

to avoid doing it every update

#

but instead only when required

#

after all, this is all just find target job, which happens occasionaly

#

but it is indeed a question, whether it's efficient way to do that

#

since when I'll have 100 systems

#

and thousands of entities

#

it indeed might be spammed all the time

solemn hollow
#

You might wanna look into chunk components if you havent yet.

rustic rain
#

I think it's already chunk components

#

considering I do query per SharedComponentData

rotund token
#

Chunk components are not the same thing

solemn hollow
#

it might help with filtering entities in your jobs after room for example. then you wouldnt need the sharedfilter

#

because as far as i understand it you dont really want to filter but kind of sort

#

you still want to process all entities in your query with one job.

rustic rain
#

well, my rooms division works based on SharedComponent

solemn hollow
#

yes but as tertle already said if that means you need to schedule each job for each room with the same query but different sharedfilter the performance wont scale. Scheduling is too expensive

rustic rain
#

I see

#

so I do need some smort bursted solution on this

#

I still haven't really looked at tertle's one

#

cause I don't understand it xD

solemn hollow
#

his solution was a way to not loop over all targetable Entities every time you search for targets. Splitting them up in a grid lets you just search neighbouring cells for entities and run your targeting logic on them.

rustic rain
#

I still don't understandh

#

how exactly that splitting

#

and then looking through that works

rotund token
#

it doesnt really matter how you group them i was just providing a suggestion

#

what really matters is just being able to do it in 1 job

rustic rain
#

yeah, that part I get

rotund token
#

if you want to have a not so efficient array of array you could do that

rustic rain
#

I want any solution that is better

#

I just need to understand it first

#

How to do DisposeOnCompletion with IJobEntity?

solemn hollow
#

hmm i wonder if that is a decent way to go about it:
Run a job on a query containing all chunks of all rooms.
Inside the job sort the chunks based on room (acutally this could be maintained outside).
For each room loop over all chunks of that room....

rotund token
#

seems reasonable to investigate

#

there's definitely going to be multiple ways to tackle this

#

and i think the best solution is well obviously going to be project specific, but likely also be something re-usable between multiple systems

solemn hollow
rustic rain
#

ah, yes

rotund token
#

just like other jobs

solemn hollow
#

personally i think the project sounds a little bit ambitious for a first DOTS learning project.

rustic rain
#

it's not my first dots project kek

#

at least, not first learning one

solemn hollow
#

oh ok sry some of your questions tackled some basics.

#

@rotund token have you ever found a decent way to use DynamicComponentTypeHandle?
Id really want to somehow have access to a Component on another entity just based on a ComponentType and avoid generics.

rotund token
#

yes

#

its how i save

#
{
    var components = chunk.GetDynamicComponentDataArrayReinterpret<byte>(this.ComponentType, this.ElementSize);
    var entities = chunk.GetNativeArray(this.Entity).Slice().SliceWithStride<int>();
    entityCount += entities.Length;

    var chunkHeader = new HeaderChunk { Length = entities.Length };

    this.Serializer.AddNoResize(chunkHeader);
    this.Serializer.AddBufferNoResize(entities);
    this.Serializer.AddBufferNoResize(components);
}```
#

is my component specific serializer for example

#

and yeah, avoided the need for generics

solemn hollow
#

But this is deep in unsafe land isnt it? ๐Ÿ™‚ im not sure i can tackle that stuff

rotund token
#

there's no unsafe code there at all i don't think

#

yeah this code has no 'unsafe' code

solemn hollow
#

oh nice

rotund token
#

TypeManager.GetTypeInfo(this.TypeIndex)
to get element size and that's really all i need apart from typeindex

solemn hollow
#

whenever i tried to use it it required me to do unsafe stuff. i probably did sth wrong then

#

how are you deserializing it onto entites? I need to write from a component that has a ComponentType Reference to that referenced component on another entity

rotund token
#

my deserializer uses unsafe code unfortunately for optimization

#

but i basically deserialize onto a hashmap

#

but then i actually just iterate all valid entities and check if save data exists for them

#

then apply it

#
                var entities = batchInChunk.GetNativeArray(this.EntityType);

                for (var i = 0; i < entities.Length; i++)
                {
                    var entity = entities[i];

                    if (!this.SerializedData.TryGetValue(entity, out var srcStart))
                    {
                        continue;
                    }

                    var dst = (byte*)components.GetUnsafePtr() + (i * this.ElementSize);
                    var src = (byte*)srcStart.ToPointer();
                    UnsafeUtility.MemCpy(dst, src, this.ElementSize);
                }```
rustic rain
#

How do I pass dependency on certain component to job?
I still can't figure it out

rotund token
#

pass in dependency handle of the systems should be handling it for you

rustic rain
#

what if I pass nativearrays instead

#

can I do it by myself?

solemn hollow
rotund token
rotund token
#

(it was the code that allowed [SaveIgnore] so it sliced it up)

rustic rain
#
        private partial struct HuggerFindTargetJob : IJobEntity
        {
            [Unity.Collections.ReadOnly, DeallocateOnJobCompletion]
            public NativeArray<LocalToWorld> ltws;

            [Unity.Collections.ReadOnly, DeallocateOnJobCompletion]
            public NativeArray<Entity> entities;

            void Execute(ref HuggerAI hugger, in LocalToWorld ltw)
            {
                int ind = GetClosestTargetIndex(ltws, ltw.Position);
                if (ind != -1)
                {
                    hugger.Target = entities[ind];
                }
            }
        }

        private int kek = 0;

        protected override void OnUpdate()
        {
            kek++;
            if (kek % 60 != 0)
            {
                return;
            }

            HuggerFindTargetJob job = new HuggerFindTargetJob();
            foreach (var starSystem in _starSystems)
            {
                _huggerQuery.SetSharedComponentFilter(starSystem);
                _targetQuery.SetSharedComponentFilter(starSystem);
                if (_huggerQuery.IsEmpty || _targetQuery.IsEmpty)
                {
                    continue;
                }


                job.ltws = _targetQuery.ToComponentDataArray<LocalToWorld>(Allocator.TempJob);
                job.entities = _targetQuery.ToEntityArrayAsync(Allocator.TempJob, out var dependency);

                Dependency = job.Schedule(_huggerQuery, JobHandle.CombineDependencies(Dependency, dependency));
            }
        }

Here's what I try to do rn

rotund token
#

kek

rustic rain
#

kek

rotund token
#

im too tired and tipsy to think about the problem

#

but just aheads up 1 random issue is

                {
                    continue;
                }```
#

this will cause a potentail sync point

#

queries with filters can need sync points to do stuff like this

#
        {
            get
            {
                var queryRequiresBatching = _QueryData->DoesQueryRequireBatching;
                if (!_Filter.RequiresMatchesFilter && !queryRequiresBatching)
                    return IsEmptyIgnoreFilter;

                SyncFilterTypes(); // HI I'M A SYNC POINT```
solemn hollow
#

i wonder if they can get rid of those at some point somehow... i am reluctant to use ChangeFilters because of it rn

rotund token
#

i already chatted to cort on forum about it if you read that thread

#

and had a quick chat with him afterwards as well and i believe the work he's doing on async methods will remove the sync points in future

solemn hollow
#

yep i read it

rotund token
#

for now you can just do your change filtering in the job

#

but yeah i avoid withchangefilter atm

#

i suspect though as it's somewhat tied to enable components it won't be till 1.0 (just gut feeling)

solemn hollow
#

@rustic rain i am sry i cannot see the error either.

solemn hollow
#

but doing it inside the job means i have to schedule the job in the first place ๐Ÿ˜ฆ

rotund token
#

need to sleep, catch you all later. if you happen to have not solved that dependency problem in 12 hours @rustic rain let me know

solemn hollow
#

gn8!

rustic rain
#

Is there a way to assign ComponentData to all entities?

#

in query

#

kind of like AddComponent

#

basically I have EntityQuery and I want to assign all entities in that query to certain component

#

all must have let's say new HuggerAI() component

pliant pike
rustic rain
#

I don't have native array, just query

#

it's fiiine

pliant pike
#

then convert the query to nativearray with query.tocomponentdataarray

#

i think you will also have to use query.copyfromcomponentarray to copy it back after

solemn hollow
rustic rain
solemn hollow
#

yes

rustic rain
#

oh

#

that's great

solemn hollow
#

also there is setcomponent

rustic rain
#

SetComponent doesn't accept query

solemn hollow
#

oh i didnt know it has no batch command. i guess there wouldnt be much performance benefit in that

#

AddComponent always adds or sets the data

cerulean pulsar
#

Is there a recommended way to get the Scene View to match the Game View when using the hybrid renderer? Considering writing back to the GameObject transform when debugging

misty wedge
#

Any idea why this is happening?

ArgumentException: Unknown Type:`Unity.Networking.Transport.NetworkConnection` All ComponentType must be known at compile time. For generic components, each concrete type must be registered with [RegisterGenericComponentType].
#

Ah wait, I think it's just the wrong struct

viral sonnet
#

what's different about DynamicComponentTypeHandle compared to ComponentTypeHandle?

#

oh, I see. it doesn't have any type. but you need to get it with a type which could be a variable. is this correct?

rotund token
#

You can use it to get any component type

viral sonnet
#

@rotund token You have a byte Value { get; } in IDynamicHashMapBase. Why is that? Does a DynamicBuffer not work with no variable in it?

rotund token
#

i need the buffer to have size

#

enforcing it to be 1 byte makes the maths easy

#

and i have checks in to make sure someone doesn't add another field increasing size

viral sonnet
#

is this how you expect to set it up then?

rotund token
#

you dont need the field

#

public byte Value {get;} is enough

#

usually i set it up as
byte IDynamicHashMap<Entity,float>.Value {get;}

#

you really don't need to access or view this value

viral sonnet
#

ok funky, thanks! had to write byte IDynamicHashMapBase<Entity,float>.Value {get;} for it to compile.

#

Unless I'm having a brain fart. Any specific reason you don't just return the values* in GetValueArray? you build an array but I don't see the reason without a key.

rotund token
#

It mimics the behaviour of NativeHashMap

#

and you can't just return Values

#

because it might have holes

#

if you've removed elements

viral sonnet
#

ah well, reason enough ๐Ÿ™‚

rotund token
#

why i actually recently wrote a custom NativeLookup container recently

#

which doesn't allow removal

#

allows addbatch and clear only

#

single adds are like 3x slower than nmhm though so you'd only want to use if you can batch add

#

obviously if you know you'll never remove an element you can use the Value field fine

viral sonnet
#

thanks for the heads up. first I need to figure out how this will all work before I start optimizing. currently creating the threat system which puts quite a lot of stress when not done right. and the logic behind it is again quite non-linear, so I hope this works out without slowing everything down. most annoying case is when Player A is fighting Mob B and NPC C is healing A so it generates threat on NPC C.

#

oh and I have never brought this up here but the arbitrary limit of 128 entities per chunk is quite weird and unexpected that will come in 1.0 or smth

rotund token
#

i think dreaming brought up a good point though

#

in practice it's pretty hard to actually have a chunk with more than 128 entities

viral sonnet
#

that's true. although that's just a limit of the chunk being 16k

#

so instead of increasing the chunk size, they limit the entities which is a weird solution for the problem

rotund token
#

like you can only have 45 entities using a basic physics cube

rotund token
viral sonnet
#

lol, good example ๐Ÿ˜„

rotund token
#

in our project at work it's horrible actually, we only have 3-6 entities per chunk

#

yeah definitely planning my own and future projects not to run into that issue

#

want to at least have 16 as a bare minimum

viral sonnet
#

I rather have no enabled components tbh

#

Not sure how much it matters when you'd have like 1k entities per archetype for enabled bits.

#

I just know that having a huge archetype entity capacity does wonders for performance

rotund token
#

if you are simply making giant archetypes and relying on component enabling then you're only going to have 3 entities per chunk like we do ๐Ÿคฃ

#

i look forward to everyone abusing enable bits

#

and their projects falling apart

viral sonnet
#

yeah, I mean, that's not how to use Entities I think.

rotund token
#

i'm just going to avoid giving any advice for a while

#

and let people figure it out for myself

#

not a fight i can be fucked with

#

there are some great uses of these enabled components however i think they're going to get abused just like adding/removing components was originally

viral sonnet
#

hehe, well, somehow we get fucked over because of this feature so ... not sure where I'm standing on this

rotund token
#

people can't seem to handle static archetypes

#

im nearly only going to use enabled bits on tag components

viral sonnet
#

yeah, I know had my difficulties in the beginning but I'm quite comfortable with static archetypes now

rotund token
#

obviously i need to get my hands on a more working copy to experiment and find some patterns

#

but that's currently how i've set things up

#

i already have a few // replace with enable components comments throughout project to switch some tag components over to it

#

which will be nice for keeping my chunks together

#

but apart from that a lot less excited than others

viral sonnet
#

optimized it really hard and that's with LocalToWorld

rotund token
#

yeah see the 128 cap isn't really hurting you there ๐Ÿ˜ฌ

#

even if they doubled chunk capacity still would be below it

viral sonnet
#

yep, it's no use with just 16k

rotund token
#

have you considered just increasing it? ๐Ÿ˜ฑ

viral sonnet
#

I tried in 0.17 but it didn't work so /shrug

rotund token
#

i will say, increasing capacity would destroy us on consoles atm

viral sonnet
#

why is that?

#

because of too many archetypes?

rotund token
#

memory costs

#

you'd be surprised how much memory the storage actually uses

#

and how small old console memory is

#

we thankfully finally got rid of our extra archetype requirements

#

we used to require 2.5-3x

viral sonnet
#

huh, so is it a problem of chunks where not a lot of entities are in?

rotund token
#

then 1.5x for ages

#

and finally we are back to 1x

#

i think archetype counts are ~6k now, reasonably ok considering the mess it is

viral sonnet
#

jesus

#

that sounds like quite a mess to clean up ๐Ÿ˜„

#

how do you even get so many?

#

anyway, I feel like the dev should be able to set the chunk size for every archetype. some should be small, some should be large, there's really no good value for everyone

molten flame
#

Do y'all get long script reload times?
For me its probably 30-60s each time I change a script.

viral sonnet
#

yeah, sometimes burst spazes out or smth

#

usually it's quite fast but then I get hit with like a 1.5min reload

rotund token
#

nah not in my own project, a few seconds usually

#

even at work which is a huge mess is only 25-45s

#

(good cpu though)

molten flame
#

hmmm, I wonder what I'm doing wrong

viral sonnet
#

profile the editor

#

should give you an idea why it takes so long. i never figured it out because it's only happening rarely but when it's happening on every code change it's easier to find out

rotund token
#

recompiled a top level assembly and didn't even see that text

cerulean pulsar
#

What do these do?

rotund token
#

glad you asked ๐Ÿ˜„

#

this is my rollback test scene

cerulean pulsar
#

That's what I was hoping they did. That is a dream

rotund token
#

physics limits this demo too much

#

going to setup like a 250k boids or something

#

(this is 50k physics objects but it starts lagging when too many clump while the rollback only takes ~1ms)

viral sonnet
#

it's so beautiful ๐Ÿคฉ

cerulean pulsar
#

How complicated is the rollback? Can you take a snapshot of the world and have an array of snapshots? Or is there a lot more to it than that?

rotund token
#

it wasn't really designed as a rollback solution

#

it's designed as a saving system

#

i just noticed some discussions on forum about rollback and thought my system would be well suited for it

cerulean pulsar
#

I wonder if the SerializeUtilityHybrid thing still exists

rotund token
#

it can save anything you want, you just put
[Saved] on the component (and can optionally ignore fields with [SaveIgnore]

#

oh this whole thing started because of a writeup I did on why you should never use that ๐Ÿ˜„

cerulean pulsar
#

Oh haha

rotund token
#

that said, it'd not run into the issues for rollback

#

but it would not perform well

viral sonnet
#

good night everyone o/

molten flame
#

goodnight Enzi

molten flame
rotund token
#

my project looks like this

#

i have a lot of asmdef

#

i know some people have felt like this doesn't help or might even have detrimental effects but personally works for me

molten flame
#

I heard mixed things about doing it that way but clearly its working for you

#

I've got like 2 asmdefs and its not working well for me XD

rotund token
#

1 issue, it's a huge pain to setup asmdef

#

so i made something to do it for me

#

(scroll down a tiny bit for source)

molten flame
#

I saw that, already downloading it lol

rotund token
#

anyway i didn't really do this for the compile time

#

i just like enforcing myself to avoid circular dependencies

#

i feel long term it makes everything much more manageable

#

and in particular modular

#

it's been very useful at times being able to just bring in (or remove things) 1 at a time to track down a bug

muted field
#

how might i make UnsafePtrList readonly as a public property to avoid it being edited from outside of my class

#

unity hasn't provided any IReadOnly intefaces for them ๐Ÿ˜ฆ

rotund token
#

make it private then no one can access it ๐Ÿ˜„

#

anyway only native containers have safety - by using unsafe you're saying you don't want read only safety

#

like unity added NativeArray<T>.ReadOnly for this

muted field
#

ah i see

#

strangely my unsafe ptr list remains length 0 when i add to it

#

very odd

#

even with step through

#

the very next line and it still shows 0

#

any ideas why that might happen ?

#

ah i need to pass the list by ref

#

that fixed it

drowsy pagoda
rotund token
#

yeah wrote this thing like 2 years ago been so useful

#

i tend to just solve any workflow problems i run into

upper tiger
#

how do I convert a float4x4 representing scale into xyz scale?

muted field
#

is this a bug?

rotund token
#

interesting

#

it uses the internal listdata

muted field
#

am i using it wrong perhaps ?

#

because its causes a crash for me

#

seems to give NullReferenceException: Object reference not set to an instance of an object Unity.Collections.LowLevel.Unsafe.UnsafeUtility.WriteArrayElement[T] (System.Void* destination, System.Int32 index, T value) (at <40205bb2cb25478a9cb0f5e54cf11441>:0) on the Add function line

#

even though the contains method worked fine

#

im no expert but i have noticed the contains/add uses void* for the argument not T* could that be causing some issue ?

rotund token
#

it internall stores it in an unsafelist<intPtr>

#

and anything passed in via ptr is converted to IntPtr

#

as far as i can tell your internal unsafelist container is not setup (hence weird length/capacity values)

#

as for contains are you sure it's working? it's never going to contain if the internal container doesn't exist

muted field
#

i dont think it is working some times it returns false other times it crashes with similar error

#

what might cause it to be not setup given i do assign it in the ctor of Node2 (which is a struct)

rotund token
#

you're access a node that the constructor wasn't called

muted field
#

ah damn it im so dumb:

    private unsafe void Awake()
    {
        float2 a = new float2(transform.position.x, transform.position.z);
        var n = new Node2(a);
        _node = &n;
    }
#

i forgot i temporarily localised it

#

how then do you get the pointer to a node on intialisation and assign it to a field member of the monobehaviour class

#

i need to use a fixed statement but not sure on the correct syntax

rotund token
#

you need to allocate the memory

#

all you're doing above is getting the pointer in the stack

#

it's gone as soon as the method returns

muted field
#

yeah thats what i meant by i localised it but not sure how to allocate for it

#

i guess i would need a native array of size 1 ?

rustic rain
#

hmm, if I create ISystemStateComponent in some abstract system as protected.
Will that remain same component in inherited systems?

rotund token
#

i guess the first question is why you need to store it as a pointer

rotund token
#

otherwise it will be unique per generic type

rustic rain
#

I mean for ECS

#

I kinda want to use it the way, so all inherited systems will see it as same component in their queries

rotund token
#

yeah the type is owned by the class it's created

muted field
#

well i have:

Node struct which connects to segment structs
and segment structs which connect to node structs

linked all via pointers

Then i have a NodeGO : Monobehaviour which has Node* member, so I need to have the pointer to the relevant node struct that it is related to, either so i can update its position by the transform or delete or what ever i want to do at the game object level @rotund token

rotund token
rustic rain
#

Well, hopefully they are

rotund token
#

don't believe me then ๐Ÿคฃ

#

(you shouldn't =D)

rustic rain
#

I kind of want to make some kind of Task based AI

rotund token
rustic rain
#

Where every agent does task look up through hierarchy and after suitable task found this task assigned to agent and based on logic from this task, it'll give smaller tasks to agent. Like go to X coordinates and etc

muted field
rustic rain
#

and after this big task is done or time outed, new look up is done

#

hm, is there a way to do component look up on entity through interface?

#

doubt there is

muted field
#

dont suppose you know what alignment means ?

#

no docs on the unsafe stuff so am not sure what it is

rotund token
rustic rain
#

let's say I'll have interface ITaskBasedJob

rotund token
rustic rain
#

which will be attached to components

#

Can I do query based on it?

rotund token
#

no

rustic rain
#

yep, that's what I thought

rotund token
#

thats oop concepts

rustic rain
#

I know

#

But I am kind of trying to find a way to do universal system

rotund token
#

just give them a tag?

rustic rain
#

yeah, I do think rn in a way of tags

muted field
rotund token
#

i mean code that uses malloc

#

plenty of examples to look at!

rustic rain
#

hmm
I do have this idea rn:
Basically I create interface for components, where task weight is required to be defined.
Then on big task look up system I find all those component types, and sort them.
And then for each that task component type I do query loop in that exact sorting order.
If task can is suitable to be assigned to entity - it is assigned, and then it's managed by it's own system, where it gives AI orders to agent, through whatever it wants. And once that task is done, or failed or timed out - New look up is done.

Any thoughts on this? I got a feeling I'm reinventing bicycle xD

rotund token
#

just dont use square wheels

muted field
#

oh damn i didnt realise they had example scripts

rotund token
#

they're not examples they're just usages of the method

#

best way to learn is look at someone elses code who's already done it

muted field
#

yeh trying to find one similar to mine but not sure any one is doing it my way ๐Ÿ˜„

#

maybe my design is wrong

#

this is the general idea of what i'm trying to do for context:

public unsafe class NodeGO : MonoBehaviour {

    private Node _node; // the node data
    private Node* _ptr; //pointer to the node
    public Node* Ptr => _ptr;

    private unsafe void Awake()
    {
        float2 a = new float2(transform.position.x, transform.position.z);

        _node = new Node(a);

        _ptr = (Node2*)UnsafeUtility.Malloc(sizeof(Node), UnsafeUtility.AlignOf<Node>(), Allocator.Persistent);

        _ptr = &_node;
    }
}
#

this will allow me to update node data by moving game objects once i add the function to do so

#

yay it works ! ๐Ÿ™‚

#

@rotund token thanks for the help

rustic rain
#

Is it possible to add component to entity by only having Type?

rotund token
#

yes

#

you get componenttypes from type

#

and you can add ComponentType to entity

rustic rain
#

so ECB can add component through ComponentType?

#

huh

#

that's actually great

rotund token
#

yes

rustic rain
#

now I am trying to figure out, how to determine which entity is supposed to get which Task
Since not all entities for example will have "X thing", to get a task of "Use X thing".

#

Can I break IComponentData by adding managed property?

rotund token
#

what do you mean

#

properties are fine

#

auto properties are just fields under the hood

#

and other properties just point to a field (usually)

rustic rain
#

what if I add a getter to IComponentData which will return some managed type

rotund token
#

that's fine

#

as long as it's not stored on it

rustic rain
#

in this case it'll be array of EntityQueryDesc

#

idk, if it will

rotund token
#

if you want to store managed data on a component you can use a class based IComponentData

#

obviously no burst then though

rustic rain
#
    public interface ITask
    {
        public uint Priority { get; }
        public EntityQueryDesc QueryDesc { get; }
    }
#

Nah, I only want this

#

I will attach it to IComponentData

rotund token
#

as long as you don't actually store a EntityQueryDesc on whatever inherits that

#

it's fine

rustic rain
#

so if I simply add kind of like static getter, it'll fine
gud

#
    public interface ITask
    {
        public uint Priority { get; }
        public EntityQuery Query { get; }
    }

    public partial class TaskLookupSystem : SystemBase
    {
        private struct TaskInfo
        {
            public uint Priority;
            public EntityQuery Query;
        }

        private Dictionary<Type, TaskInfo> tasksList = new Dictionary<Type, TaskInfo>();

        protected override void OnCreate()
        {
            var iTaskType = typeof(ITask);
            var iComponentType = typeof(IComponentData);
            var types = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(s => s.GetTypes())
                .Where(p => iTaskType.IsAssignableFrom(p) && iComponentType.IsAssignableFrom(p));

            foreach (var taskType in types)
            {
                ITask newTask = Activator.CreateInstance(taskType) as ITask;
                tasksList.Add(taskType, new TaskInfo() {Priority = newTask.Priority, Query = newTask.Query});
            }
        }

        protected override void OnUpdate() { throw new NotImplementedException(); }
    }

So far I have this.
Now I need to create a Job that will run through each of those ITask and add to entities it's tasks

muted field
#

how do smart pointers differ in unreal to the stuff we have in unity ?

#

was reading on the forums unity is working on something for the lack of smart pointers but curious what that would be

rotund token
#

well smart pointers are a c++ feature not really unreal

#

languages like java/c# don't usually have smart pointers because you have garbage collector/classes which handle memory for you

#

if you just want something to cleanup memory for you Unity already shipped World/UpdateAllocator as a replacement for TempJob

#

which does not need disposable (instead disposes/gets reused every 2nd frame automatically)

rustic rain
#

Sooo, rn I am trying to solve a problem, of how to determine which AI agent wants which Task assigned.
I see several solutions:

  1. Either I create some kind of algorithm that will automatically on compile create all necessary components for each Task agent might want and it will basically create all unique queries through it, for Task to be assigned.
  2. Or I create one shared component that will hold ComponentType or simply index of component. And then do queries through shared component filter.
    soooo
    What do you guys think any of it is viable?
rustic rain
#

For the part of how AI agent determines the task it wants, I plan on making component with array of tasks types sorted.
And it will run a job, that will go through each one by one, checking through interfaced method, whether Entity can do and wants to do job.
But in this case I run into case, where I either might lack information to determine it or I'd need to do it in sync point

worthy rampart
#

this way you can safely free the memory when the counter hits 0

#

I'm pretty sure I read that blobs use this technique

#

it might have been something else

#

there's also a unique_ptr which doesn't have any reference counting and automatically frees the memory when it goes out of scope

rotund token
#

@rustic rain honestly don't really understand what your doing to provide any advice

#

Are you trying to just build a way to dispatch work to different entities?

rustic rain
rotund token
#

i use a bit field for state

#

with auto registered components

#
                    {
                        return;
                    }

                    // TODO potentially change this to new component filtering when Unity implements this instead of changing architecture
                    if (previous.Value != 0)
                    {
                        var stateComponent = this.RegisteredStates[previous.Value];
                        this.CommandBuffer.RemoveComponent(batchIndex, entity, stateComponent);
                    }

                    if (state.Value != 0)
                    {
                        var stateComponent = this.RegisteredStates[state.Value];
                        this.CommandBuffer.AddComponent(batchIndex, entity, stateComponent);
                    }```
#

unique version basically looks like this

#

or my flag version looks like this

#
                    // ---------
                    // 0 0 | 0 0
                    // 0 1 | 1 0
                    // 1 0 | 0 1
                    // 1 1 | 0 0
                    // ---------
                    // R = !S & P
                    // A = S & !P
                    var toRemove = state.Value.BitNot().BitAnd(previous.Value);
                    var toAdd = state.Value.BitAnd(previous.Value.BitNot());

                    for (uint r = 0; r < toRemove.Capacity; r++)
                    {
                        if (toRemove[r])
                        {
                            Debug.Assert(this.RegisteredStates.ContainsKey(r), $"Trying to remove state {r} that was not registered");
                            var stateComponent = this.RegisteredStates[r];
                            this.CommandBuffer.RemoveComponent(batchIndex, entity, stateComponent);
                        }
                    }

                    for (uint r = 0; r < toAdd.Capacity; r++)
                    {
                        if (toAdd[r])
                        {
                            Debug.Assert(this.RegisteredStates.ContainsKey(r), $"Trying to add state {r} that was not registered");
                            var stateComponent = this.RegisteredStates[r];
                            this.CommandBuffer.AddComponent(batchIndex, entity, stateComponent);
                        }
                    }```
#

so you just set or unset bit in the field and it will automatically add your component etc

#

and each system that reacts to the component registers it + the bit it owns

#
        where T : IStateComponent
    {
        /// <inheritdoc/>
        public abstract byte StateKey { get; }

        /// <inheritdoc/>
        public abstract ComponentType StateInstanceComponent { get; }
    }```
#

with just some abstract properties

#

not sure this is exactly what you're looking for though

rustic rain
#

hmm, could you explain algorithm without code?

#

kind of in short, what it does

rotund token
#

0000
your bit field
0010
adds a component registered in index 1
0110
adds a component registered i index 2
0100
removes component registered in index 1

#

its just how i control agent states

#

(actually its how i control a lot more than just agent states, i use it for UI/game/input etc)

#

basically my version of a ecs state machine

rustic rain
# rotund token not sure this is exactly what you're looking for though

I'm looking for a way, to create an AI with such qualities:
Each AI agent (kind of character) will have it's own defined list of possible tasks (for example characters of kind Robot will do only task in order: "Kill enemies" and "Idle around", while some other agent will do different taskset like: "Heal allies (if they exist)", "Attack enemies" and "Self-destruct if no task".

And this system should be like lego. So nothing is hardcoded, but instead defined by components.

rotund token
#

can they change task?

rustic rain
rotund token
#

sorry i missread

#

the answer to my question is yes

rustic rain
#

Kind of that exact system is used in Rimworld, but it's fully in OOP

#

so I'm way too influenced by wrong thinking kek

solemn hollow
#

Not sure what AI Architecture Rimworld uses but Utility AI is very suited for DOD.

rustic rain
rotund token
#

In video game AI, a utility system, or utility AI, is a simple but effective way to model behaviors for non-player characters. Using numbers, formulas, and scores to rate the relative benefit of possible actions, one can assign utilities to each action. A behavior can then be selected based on which one scores the highest "utility" or by using t...

#

in particular infinite axis utility ai is often talked about being a really good fit for entities

solemn hollow
#

yap. implemented a variaton of it myself. works like a charm.

#

There are alot of talks from Dave Mark in the GDC Vault that are worth a watch.

solemn hollow
#

one of them yes

rustic rain
# solemn hollow one of them yes

yo sir, what was that kind of job you offered to solve my problem with a lot of entities in different rooms?
Smth about chunks

covert lagoon
#

I'm looking at the following code example from https://docs.unity3d.com/Packages/com.unity.netcode@0.50/manual/getting-started.html#tie-it-together:

// When client has a connection with network id, go in game and tell server to also go in game
[UpdateInGroup(typeof(ClientSimulationSystemGroup))]
public class GoInGameClientSystem : SystemBase
{
    protected override void OnCreate()
    {
        // Make sure we wait with the sub scene containing the prefabs to load before going in-game
        RequireSingletonForUpdate<CubeSpawner>();
        RequireForUpdate(GetEntityQuery(ComponentType.ReadOnly<NetworkIdComponent>(), ComponentType.Exclude<NetworkStreamInGame>()));
    }
    protected override void OnUpdate()
    {
        var commandBuffer = new EntityCommandBuffer(Allocator.Temp);
        Entities.WithNone<NetworkStreamInGame>().ForEach((Entity ent, in NetworkIdComponent id) =>
        {
            commandBuffer.AddComponent<NetworkStreamInGame>(ent);
            var req = commandBuffer.CreateEntity();
            commandBuffer.AddComponent<GoInGameRequest>(req);
            commandBuffer.AddComponent(req, new SendRpcCommandRequestComponent { TargetConnection = ent });
        }).Run();
        commandBuffer.Playback(EntityManager);
    }
}

What's the point of this line?

        RequireForUpdate(GetEntityQuery(ComponentType.ReadOnly<NetworkIdComponent>(), ComponentType.Exclude<NetworkStreamInGame>()));

I thought I read somewhere that systems were only updated when Unity/the DOTS runtime/whatever detected that they needed to be.

lusty pewter
#

@covert lagoon
by default systems update when at least one entity exists that matches the components you define in your Entities.ForEach code. in the example above that would be an entity with the components NetworkIdComponent that does not have a NetworkStreamInGame component. This "default" update requirement will be generated automatically. sometimes you might want to run a system if entities exist with other components than the ones you specified in the Entities.ForEach. Then you can do it just like the example above: define a RequireForUpdate to define other conditions when to run your system

covert lagoon
#

But in this case the explicitly defined conditions are the same as the ones deduced from Entities.WithNone<...>().ForEach(...), aren't they?

lusty pewter
#

they have two update conditions: the RequireSingletonForUpdate and the RequireForUpdate. this is done because the default behavior, (that the condition for the ForEach is generated) will be skipped if you specify your own update requirement . so they had to specify the "for each requirement" by hand.

covert lagoon
#

So a call to RequireSingletonForUpdate, or any other Require... method, prevents the implicit generation of requirements?

lusty pewter
#

exactly

covert lagoon
#

Ok, thanks!

rustic rain
#

I kind of assume that will also be case for calculating size/length

#

which I need for calculating capacity of hashmap

rustic rain
#

hmmmm

#

Is that up-to-date way to iterate over NativeMultiHashMap?

                TargetData targetData;
                NativeMultiHashMapIterator<int> iterator;

                if (hashMap.TryGetFirstValue(starSystem.systemID, out targetData, out iterator))
                {
                    do
                    {
                        
                    } while (hashMap.TryGetNextValue(out targetData, ref iterator));
                }
#

or maybe there's more convinient way to do same thing?

desert solstice
#

๐Ÿ‘‹

solemn hollow
#

yes

desert solstice
#

nice, thx

solemn hollow
rustic rain
#

yeah, I looked it up

#

But then I found NativeMultiHashMap

#

and it looks like perfect solution kek

#

if only not this, sadkek

desert solstice
#

You must use Unity Editor version 2020.3.30 with Entities 0.50.
ho ....

rustic rain
#

looks like I need to rewrite it

desert solstice
#

guess i have to downgrade ?

solemn hollow
#

yes or you wait a little bit until 0.51 hits

#

it supports 2021 then

solemn hollow
rustic rain
#

yeah, that's kinda what i meant

#

I never liked struct jobs

#

ngl

#

hmm, maybe I can solve it through foreach loop

solemn hollow
#

foreach is not working

rustic rain
#

why not?

desert solstice
#

mmmm ๐Ÿค” perhaps i should do this on my windows laptop then. trying it on my mac M1 is probably pushing my luck

solemn hollow
#

oh wait im not sure if its not working or if its just not burstable.

desert solstice
#

even on a unity 2020 ? how nice.

solemn hollow
#

well it doesnt run native if thats what you mean but it doesnt matter.

desert solstice
#

well yeah of course it doesn't. but as long as it works (c)(r)(tm)

#

2020.3.34f1 is ok or is it strictly 3.30 ? (can't find 3.30 in the hub)

viral sonnet
#

2020.3.30+ is okay

rustic rain
#

eh, same boilerplate basically

viral sonnet
#

then I don't know what you expected

rustic rain
#

brrruh

#

wait a second

#

Burst doesn't work with SharedComponents?

viral sonnet
#

when the SharedComponent has a managed type it's not burstable

rustic rain
#

hm, it only has int

viral sonnet
#

is it a class?

rustic rain
#

nah, nvm

#

I don't think it's an actual error

#

it's gone after restart

desert solstice
rustic rain
#

just install last version of it

#

and it'll automatically install pretty much all ecs related packages

#

except physics

desert solstice
#

๐Ÿ‘

solemn hollow
#

not burstable atm

rustic rain
#

I see

#

I got stuck with dependecies again

            _gatherTargetDataJob.hashMap = hashMap;
            var gatherDataDep = _gatherTargetDataJob.Schedule(_targetQuery);

            _findTargetJob.hashMap = hashMap;
            _findTargetJob.buffer = buffer;
            Dependency =
                JobHandle.CombineDependencies(_findTargetJob.Schedule(_huggerQuery, gatherDataDep), Dependency);

I need job to run only after gather data job.

#

and it results in this pepega error

desert solstice
#

haaa hybrid renderer doesn't support builtin render pipeline. i don't really have any need for advanced rendering technique. URP then ?

desert solstice
#

great. you guys are being super helpful in this preview maze ๐Ÿฅฐ thx again for the millions times ๐Ÿ˜„

solemn hollow
#

idk why you have so many dependency problems ^^. the base case should be that you just assign each job to the Dependency of the system one after the other.

#

Like
Dependency = job1.Schedule(Dependency)
Dependency = job2.Scheducle(Dependency)

#

and it should work

#

i literally never used combinedependency even once in my projects 0.o

rustic rain
#
            _gatherTargetDataJob.hashMap = hashMap;
            Dependency = _gatherTargetDataJob.Schedule(_targetQuery, Dependency);

            _findTargetJob.hashMap = hashMap;
            _findTargetJob.buffer = buffer;
            Dependency = _findTargetJob.Schedule(_huggerQuery, Dependency);

Same error

solemn hollow
#

really no idea where the error is then. this should be fine

rustic rain
#

I know

#

or maybe not

desert solstice
#

i usually buy as much ram as i can afford. When i bought the Macbook air M1 i was planning to use it for browsing and discording. I didn't expect the M1 to be so good. I'm regretting so much to have only 8GB of ram ... even installing the entities package make it run out of ram ๐Ÿ˜ข

solemn hollow
#

in all the test i saw it didnt really matter. the only point where i have problems is with profiling in unity. its a bug unity is aware of and i think 2021 has a fix for it. Unity errors and says you dont have enough ram to profile... really annoying.

#

i got the 16 GB though

desert solstice
#

ha yes, it works ๐Ÿ™‚

rustic rain
#

I usually add it through manifest.json

#

hmm, now I finally got error that makes sense:

            _gatherTargetDataJob.hashMap = hashMap;
            Dependency = _gatherTargetDataJob.Schedule(_targetQuery, Dependency);

            _findTargetJob.hashMap = hashMap;
            _findTargetJob.buffer = buffer;
            Dependency = _findTargetJob.Schedule(_huggerQuery, Dependency);
#

problem is, do I really have to create a sync point?

desert solstice
signal flicker
#

hey guys, im wondering how i can futher improve my jobs performance

#

so im using the c# job system to write data to a compute buffer to use with a compute shader

#

the job itself is stupid simple,

[BurstCompile(CompileSynchronously = true)]
        private struct SetBuffersJob : IJobParallelForTransform
        {
            [WriteOnly]
            public NativeArray<float4x4> BoneArray;
            [WriteOnly]
            public NativeArray<Quaternion> RotationArray;
            public void Execute(int index, TransformAccess transform)
            {
                BoneArray[index] = transform.localToWorldMatrix;
                RotationArray[index] = transform.rotation;
            }
        }
#

all it does is set the data

#

I am using ComputeBuffer.BeginWrite and ComputeBuffer.endwrite

#
protected override void CalculateSkinning()
        {
            _boneArray = boneBuffer.BeginWrite<float4x4>(0, bones.Length);

            _rotationArray = qBuffer.BeginWrite<float4>(0, bones.Length);
            var nativeArrayQuaternion = UnsafeUtility.As<NativeArray<float4>, NativeArray<Quaternion>>(ref _rotationArray);

            gatherMatrixJob.BoneArray = _boneArray;
            gatherMatrixJob.RotationArray = nativeArrayQuaternion;
            gatherMatrixJobHandle = gatherMatrixJob.ScheduleReadOnly(transforms, 128);
        }
#
protected override void ApplySkinning()
        {
            gatherMatrixJobHandle.Complete();
            boneBuffer.EndWrite<Matrix4x4>(bones.Length);
            qBuffer.EndWrite<Quaternion>(bones.Length);

            //set other buffers to CS and dispatch
        }
#

in order, CalculateSkinning is called for all isntances of this class, then ApplySkinning is called

#
private void LateUpdate()
        {
            foreach(BaseCorSkinning s in instances)
            {
                s.Skin(1);
            }
            JobHandle.ScheduleBatchedJobs();
            foreach (BaseCorSkinning s in instances)
            {
                s.Apply();
            }
        }
#

this is the method that does that

muted field
#

i have a job that does this simple bit of code:

        public unsafe void Execute(int index)
        {
            var path = _currentPath[index]; // native array
            _result.Add(path.A); //unsafe ptr list
        }

but when i read _result back the contents is empty every time, i ran step through and the job was working correctly. is there some attribute i need to use to get ptr lists to work properly?

rotund token
#

what is result

#

is result an unsafe container?

#

if so yes it won't have any values if you read it outside the job

muted field
#

theres no workaround for that?

rotund token
#

@signal flicker what job are we talking about? SetBuffersJob? Because there's not much space to go there. the only thing would be to ensure all transforms aren't under the same parent so it can run parallel.

muted field
#

I did add NativeDisableUnsafePtrRestriction thinking that would fix it

rotund token
#

that doesn't change how a struct works

muted field
#

well thats a spanner in the works then =/

#

my found path is a native array of a struct which contains pointers

rotund token
muted field
#

so the only way to get it back would've been using ref ?

rotund token
#

you need to write it back to something that has fixed memory

#

either a component, a pointer, malloc memory etc

muted field
#

ah ok so even persistent allocator wont be fixed memory in this case?

rustic rain
#

@rotund token sir, is it possible to run those jobs without sync point?

        protected override void UpdateWithBuffer(EntityCommandBuffer buffer)
        {
            int targetCount = _targetQuery.CalculateEntityCount();
            hashMap.Clear();
            hashMap.Capacity = targetCount;

            _gatherTargetDataJob.hashMap = hashMap;
            var gatherDep = _gatherTargetDataJob.Schedule(_targetQuery);


            _findTargetJob.hashMap = hashMap;
            _findTargetJob.buffer = buffer;
            _findTargetJob.Schedule(_huggerQuery, gatherDep);
        }

        private struct TargetData
        {
            public Entity entity;
            public float3 position;
        }

        [BurstCompile]
        private partial struct GatherTargetDataJob : IJobEntity
        {
            public NativeMultiHashMap<int, TargetData> hashMap;

            void Execute(Entity e, in InSystemComponent starSystem, in LocalToWorld ltw)
            {
                hashMap.Add(starSystem.systemID, new TargetData() {entity = e, position = ltw.Position});
            }
        }

        [BurstCompile]
        private partial struct FindTargetJob : IJobEntity
        {
            [ReadOnly] public NativeMultiHashMap<int, TargetData> hashMap;

            public EntityCommandBuffer buffer;

            void Execute(Entity e, in InSystemComponent starSystem, in LocalToWorld ltw)
            {
                Entity closestTarget = default;
                float closestDistance = float.MaxValue;
                TargetData targetData;
                NativeMultiHashMapIterator<int> iterator;


                if (hashMap.TryGetFirstValue(starSystem.systemID, out targetData, out iterator))
                {
//kkek
                }

                if (closestTarget != Entity.Null)
                {
                    buffer.AddComponent(e, new FollowShip() {entity = closestTarget});
                }
            }
        }
#

I really don't get what's up with dependencies

rotund token
#

you''re not passing in a dependency?
var gatherDep = _gatherTargetDataJob.Schedule(_targetQuery);

and you're not writing any dependency back?
_findTargetJob.Schedule(_huggerQuery, gatherDep);

rustic rain
muted field
#

you're assigning the dependency after you've scheduled _targetQuery though

rotund token
#

the error seems to imply you're using EntityManager in a job

rustic rain
#

well, I'm not sure I do

rotund token
#

where's your JobData struct

rustic rain
#

what JobData

rotund token
#

oh wait that's the codegen part

rustic rain
#

hmmmm

#

seems like having SharedComponent

#

IS an issue

#

after all

rotund token
#

oh is that a shared component?

rustic rain
#

yeah

#

kek

#

sadkek

rotund token
#

you cnat use shared components in burst jobs

#

shared components are managed

rustic rain
#

yeah, I got that part

#

so, I can't Schedule such jobs either?

#

hm

#

Do I just make that component non-shared?

#

After all, all it holds is int ID

rotund token
#

you can actually use shared components in jobs

#

just not their value

rustic rain
#

but I do need their value

rotund token
#

you can only use their unique index

rustic rain
#

and what is it?

#
            void Execute(Entity e, in InSystemComponent starSystem, in LocalToWorld ltw)
            {
                hashMap.Add(starSystem.systemID, new TargetData() {entity = e, position = ltw.Position});
            }

I need to know which ID of room is it

#

if I write component itself into hashMap, will that work or?

rotund token
#
public void Execute()
{
    foreach (var chunk in this.Chunks)
    {
        var sharedComponentIndex = chunk.GetSharedComponentIndex(this.SavablePrefabType);```
rustic rain
#

I see

rotund token
#

you could have a simple hashmap that maps unique index

#

to room index

#

then simply look it up

#
            var lookup = new NativeHashMap<SavablePrefab, Entity>(this.savables.Count, allocator);

            var currentMap = new NativeHashMap<int, SavablePrefab>(this.savables.Count, allocator);
            var savableArray = NoAllocHelpers.ExtractArrayFromListT(this.savables);
            var savableIndicesArray = NoAllocHelpers.ExtractArrayFromListT(this.savableIndices);

            currentMap.ClearAndAddKeyBatchUnsafe(savableIndicesArray, savableArray, this.savables.Count);```
rustic rain
#

yeah, whole point of shared component is to hold one int

rotund token
#

i do that in my saving

rustic rain
#

so rn I really wonder, maybe I should just make it non shared

rotund token
#

my shared components have 4 uint

#

but i just build a quick map to make the unique scd index to the unique ID

#

then i can access the shared component unique ID in jobs

rotund token
rustic rain
#

well, I kind of do I think

rotund token
#

alternatively the good old

#

duplicate components

#
    public struct Team : IComponentData
    {
        public byte Value; // 0 is no team
    }

    public struct TeamShared : ISharedComponentData
    {
        public byte Value; // 0 is no team
    }```
#
// TODO MERGE THIS WHEN UNMANAGED SHARED COMPONENTS EXIST IN 0.50

it's a lie

#

need to update to 1.0

rustic rain
#

Cake is a lie

#

yeah

#

so getting index is only possible in chunk job?

rotund token
#

yes all you can get is the unique shared index

desert solstice
#

i have so many compilation error that i think i installed & configured it correctly ๐Ÿ˜„

rustic rain
rotund token
#

yeah not sure you can get it via any of the codegen jobs

#

have to use ijobentitybatch instead

desert solstice
#

but i think i'll give up. the lack of ram is killing me

#

just removing TextMeshPro plugin from the package manager make it unresponsive for 10mn. it seems to be recompiling the entire planet. And my scene is just a camera and a directional light, not even a cube

#

the burst progress bar is there since forever

rotund token
#

did you restart unity after installing burst?

desert solstice
#

no

rotund token
#

its kind of a requirement to restart unity after you change your compiler ๐Ÿ˜…

signal flicker
#

i had a buddy take a crack at it and he gained +50% fps using pointers, but it crashed often (well more often than not) (in fact it only worked once for some reason)

desert solstice
#

last attempt. restarting it. i won't bother you forever just because my laptop is underpowered

shut pewter
#

Hey all

#

Are there any utilities to serialize an Entity (and its components)?
Currently I do something that feels hacky (a system that grabs every component I need), I'd like to know if there's a more standard approach

rotund token
#

that seems reasonable

shut pewter
#

Hmm maybe it is

rustic rain
#

yay, finally

#

made it work

rotund token
#

go with index or just not scd

desert solstice
#

i give up. thank you for the help โค๏ธ

viral sonnet
#

the gist is to schedule jobs for every SCD variant and have the SCD data as parameter for the job(s)

rotund token
#

its a lot of job overhead though if you have a lot of scd

viral sonnet
#

it certainly is. SCDs have their place but most of the times there are better solutions

viral sonnet
viral sonnet
# desert solstice i give up. thank you for the help โค๏ธ

That said, I have a MacBook Pro from a few years ago that I still use for writing out iOS versions. Also has 8Gb. While I don't use it with Burst, I'm very sure it would still run fine. Possible you are having other issues that could be fixed? Too much running apps, low disk space?

viral sonnet
#

Any suggestions for handling deallocations on unsafe containers inside IComps? Seems like I have to save the unsafe container or pointer inside a system state too. Is there a better design?

desert solstice
rustic rain
viral sonnet
#

that's unusual, is this an empty project?

desert solstice
#

but while it compile the system is maxed out on ram

#

yes. sun + camera

viral sonnet
#

did you try deleting the library folder?

desert solstice
#

no

#

i have other computers, maybe i'll try again tomorrow, dunno.

viral sonnet
#

try that, I think something has gone totally wrong in your project. a total restart with the correct packages should work though

rotund token
desert solstice
#

perhaps it would be a good occasion to see if my desktop computer is still working. haven't used it since i bought the M1

#

threadripper + 32GB ram ^^

#

actuallt, haven't used it since covid

viral sonnet
#

blasphemy I say!

desert solstice
#

well it was my video editing machine and there wasn't much to film during the pandemic ๐Ÿ˜„

rotund token
#

Seems like I have to save the unsafe container or pointer inside a system state too. system state
this doesn't work either because quitting play mode won't dispose it (or destroying world etc)

desert solstice
#

it's highly likely that my old GTX960 died of old age during its 2 year slumber

viral sonnet
#

ah, hardware is way too robust ๐Ÿ˜„

rotund token
#

OnDestroy is a bit problematic

#

as if the world is destroyed you can't do queries

#

you kind of need to store them all in the system

#

anyway this is just why i don't do this

#

(this is why i wrote stuff like the dynamic hash map - rather stick to automatic memroy management)

viral sonnet
#

yeah good points. sounds annoying to deal with. hm, I REALLY don't want use a DB

#

haha

#

guess I have to :/

desert solstice
#

what's wrong with using a db ?

#

<angry database administrator noise>

rotund token
#

dynamicbuffer not database

desert solstice
#

ho lol my bad

viral sonnet
#

yeah, I rather put the data in redis than in a DB ... ok jk

#

gonna try with a DB - should have written this in a few minutes and then profile against another solution with a HashMap<Entity, struct> where I can store either a list or hashmap. Let's see how this works out

viral sonnet
#

well, well ... the new threat mechanic puts 6ms on my job to around 13ms with a DB hashmap - I have to say, not bad considering when the naive version of a DB with a manual Contains method and for loop took 8 seconds ๐Ÿคฃ

rotund token
#

nothing like 7 frames a minute

viral sonnet
#

I say thanks again for the DB hashmap. You are always one step ahead of what I need it seems ๐Ÿ˜„ I'm gonna implement a DB hashset eventually. Don't need values in my current case but first I'm gonna test how fast this will go with a nested hashmap in a system

rotund token
#

unitys hashset currently just uses a full nativehashmap

#

you could slightly reduce memory though by stripping values

#

and it just looks nicer ๐Ÿ˜„

viral sonnet
#

lol how lazy is that. gonna roll with the jack dunstan implementation then

#

only thing that bugs me right now with the DB hashes is no inspection ๐Ÿ˜ฆ

#

have you looked into how hard that would be to integrate?

#

eh, I'm a dummy. hashset with no values at all doesn't work. how would you get them back from the hash ... and I need the values eventually

rotund token
#

just need to add [DebuggerTypeProxy] then implement

#
        where TKey : struct, IEquatable<TKey>
        where TValue : struct
    {
#if !NET_DOTS
        UnsafeHashMap<TKey, TValue> m_Target;

        public NativeHashMapDebuggerTypeProxy(NativeHashMap<TKey, TValue> target)
        {
            m_Target = target.m_HashMapData;
        }

        public List<Pair<TKey, TValue>> Items
        {
            get
            {
                var result = new List<Pair<TKey, TValue>>();
                using (var kva = m_Target.GetKeyValueArrays(Allocator.Temp))
                {
                    for (var i = 0; i < kva.Length; ++i)
                    {
                        result.Add(new Pair<TKey, TValue>(kva.Keys[i], kva.Values[i]));
                    }
                }
                return result;
            }
        }
#endif
    }```
#

what the native hash map one looks like

#

i could basically just replicate that for db

viral sonnet
#

awesome

#

thanks, direction is enough, I think I can implement this.

viral sonnet
#

hm, so the current problem I have is that the DOTS debugger sees the DynamicHashMap as DynamicBuffer and I see no way of overriding this

worldly isle
#

The docs have exclude all but no exclude any. I want to be able to say hey give me all the objects that have A but don't have B or don't have C

viral sonnet
#

ForEach WithAny<A>, Exclude<B, C> ?

#

would that work for you?

rustic rain
#

Is Infinite Axis suitable for ECS?

solemn hollow
#

@rustic rain Well any AI Architecture can be done in ECS. IMO Utility AI is just a good fit because its easy to parallize and to have very flexible,robust AI.

rustic rain
#

yeah, I'v seen this thread

#

But I can't really find good explanation on Utility AI

#

xD

solemn hollow
#

you rank the possible Actions based on a Utility function you assign to each action.

#

then you pick the highest Action with the highest score.

#

Now the Infinite Axis Model is just one way to implement that.

rustic rain
#

I just don't understand it enough, since I can't get how it can be applied with unity ECS

#

trying to watch centaur AI vid rn

#

but I have trouble understanding it fully

solemn hollow
#

why it is good with ecs is because you can evaluate all the Considerations at the same time. you dont have to traverse a graph

rustic rain
#

hmm

karmic basin
#

You discovered UAI Yesterday. Just give yourself a few more days and it will click.

rustic rain
#

Could you make some super basic example of it?

#

in ECS

#

In what exactly will be used, what types

#

what kind of job

#

if it can interpreted this way ofc

solemn hollow
#

This heavily depends on how you want to implement it.
I think you can find some infos in the post i linked above. also there are implementations for ECS already. you could look into them. If I were to post examples of my implementation it would probably lead you astray. I had some very specific constraints because of the authoring workflow i wanted. Basically i improved on the Infinite Axis model a bit by making Considerations hierarchical.

rotund token
#

i've never used it, we have our own at work that is a bit differently implemented

#

but if you just want to get the concept of implementation should help

solemn hollow
#

@rotund token i saw in the thread that you had 0.5ms mainthread time for your UAI. Is it all done in one scorer System or do you have a system for each consideration?

rotund token
#

oh my implementation is vastly different to this

#

it is graph traversal

#

but yeah it's a single system / single job

#

hence main thread performance is very quick

solemn hollow
#

hmm i didnt find a way to make that work for my AI. probably possible but out of my grasp

rotund token
#

i have unlimited chained scorers

solemn hollow
#

same 0.o

rotund token
#

all defined via graphs in editor that look like that

solemn hollow
rotund token
#

oh yeah so similar

#

that's cool, haven't seen anyone else implement it this way in entities so far

solemn hollow
#

there are no resources whatsoever for this yes

rotund token
#

i actually wrote this over 18 months ago, i've always wanted to release it but i've never actually hooked up ai to my project yet so it's still proof of concept

#

and it seems to work but until i can verify that it's actually semi-production ready i'm not willing to release something

#

i actually wrote it generic so that it can be implemented in any project

#

you just implement a single interface, and then create your own nodes

solemn hollow
#

i havent ever released anything yet so my biggest hurdle is i dont know when i could. its far from perfect ๐Ÿ˜„

rotund token
#

going from fixed to generic implementation took a lot of effort

#

especially with UI

#

so far i'm yet to see any other AI solution in entities that isn't tied to the project

solemn hollow
#

Mine isnt.

#

i can create considerations in the editor. Codegen creates everything that is needed

rotund token
#

ah nice

#

i actually ended up doing mine with no codegen

solemn hollow
#

then with MakeGeneric i create the needed systems

#

i didnt manage without it ๐Ÿ˜ฆ

rotund token
#

originally i was considering codegen but i managed to figure out a way to do it without

solemn hollow
#

i had a version with dynamiccomponenttypehandle stuff but i wanted to switch to dynamic buffers to store considerations on entities

#

that required codegen afaik

#

i really want to release at some point in time but its probably years until ready. Debugging and Authoring need to be on point

rotund token
#

i have a pretty good debug workflow

#

i can record all AI state every frame

#

then play them back in my graph

#

to show the path an individual entity took

#

every frame

solemn hollow
#

yes i have nothing like that. i can only show considerations live ingame

#

i wouldnt even know how to implement sth like yours. the architecture still has some problems not allowing me to do those things easily i think.

rotund token
#

but yeah haven't touched it in a year except to update to 0.50

rotund token
#

still not sure if that's a good thing

solemn hollow
#

my focus was on authoring. beeing able to stagger considerations to make them more understandbale and more modular. I can reuse calculations alot. In the basic IA model at some point it just becomes a little hard to see what your AI actually thinks

rotund token
#

yeah agreed

solemn hollow
#

like 10 Axis in 1 consideration...

rotund token
#

our designers and even developers have a hard time updating our AI at work

#

for the most part most people except the original author

solemn hollow
#

Well AI is never easy i guess ^^

#

How are you reading data from the world? I got extra systems vectorizing any component i need to a normalized score and safe it on the Entity that scored it.

rotund token
#

yeah do something similar

#

my plan is commonly used components are normalized etc

#

and anything rarely used is just read in the actual job

#

i dont save it on entity though

#

i just have giant arrays

solemn hollow
#

makes sense for alot of values. My problem was vectorizing distance to the target

#

were every entity has its own value then

#

due to this my Agent entities are HUGE atm

rotund token
#

yeah thats something htat is problematic to me

#

and something i'm trying to avoid but i haven't solved yet

#

i really want to minimize entity size unlike the monster entities we have at work

solemn hollow
#

all my buffers already live outside of the chunkmemory but still i only fit 3 entities per chunk^^

#

guess i need to split them up somehow

rotund token
#

yeah thats my work

#

3-6 entities per chunk

#

im going to look at something like the dots sample where the split everything into child entities

#

but then lookup is hugely a pain

#

at work all our considerations etc are their own components

#

but the actual actor itself is still huge with stats, states, etc

solemn hollow
#

hmm damn i need to go soon but its interesting ๐Ÿ˜„

rotund token
#

i'm hoping ~soon i can get back to this stuff

#

i just need to get basics in game to actually utilize some ai

solemn hollow
rotund token
#

my game barely exists

#

i just spend the whole time writing useful tools instead ๐Ÿ˜„

solemn hollow
#

๐Ÿ˜„

#

Its on the tip of my tongue but i cant remember right now. what was the term for when you essentially gather data in a map to read from? kind of like a flowfield.

#

do you have an implementation for that or did you skip it because you can read data fast enough anyways?

#

Is it called InputMap?

#

AAAH its InfluenceMap

rustic rain
#

My head is spinning rn

rustic rain
#

xD

rotund token
#

oh

#

4 editions of the book online for free, last updated dec 2021

solemn hollow
#

ups that was what i wanted to actually link ๐Ÿ˜„

#

the one i linked is the company of Dave Mark. good read too i guess

solemn hollow
# rotund token not sure sorry

I found i didnt need Influence maps because i could just create basically the same data on one ManagerAI and pass the data on to the SubAIs

#

But its more like Infinite Density Influence Maps now.

rotund token
#

yeah i haven't setup anything like that atm

#

but again, i haven't actually got a real game running just test graphs

#

so we'll see what happens when i have an actual game playing around

#

out of interest, what type of entity count are you using?

#

and how's the performance

solemn hollow
#

my mainthread performance depends more on how many diffrent considerations i have since every consideration is an extra system. My thread performance depends on entity count.
atm i run around 100 AIs per frame and around 30 diffrent considerations. On my M1 chip that takes 2.3ms mainthread and 3 ms on workers

#

i have a timeslicer implemented though. so if i wanted i could run insane amounts of entities that just dont think every single frame. alot of games let their Ai think only like 4 times a sec.

#

I am pretty sure that if someone more experienced than me would look over my code it could be sped up like 4 times atleast.

rotund token
#

how does it scale with entity count

#

say you just upped it 10x

#

because yeah the issue i had with our work implementation was that it ended up being too many systems/jobs

#

and didn't perform that well on consoles

#

now i'm not going to have this problem (and most people never will) as who is going to target last gen consoles again

#

but it was still an obvious limitation

#

i had to merge like 10s of systems into mega system

solemn hollow
#

yep i didnt have consoles in mind. wouldnt run on them.
The timeslicer actually also handles the system count

rotund token
#

yeah i mean without the timeslicer

#

like i assume (hope) if you did 1k entities it wouldn't be 23ms main thread?

solemn hollow
#

i havent tested in latest big iteration. ill do and report back to you

solemn hollow
#

but the workerthreads could get quite busy

#

mainthread is only scheduling stuff. no logic at all

rotund token
#

yep what i would expect

solemn hollow
#

i gotta go now. mothersday dinner at parents^^. ill report back

rustic rain
#

hmmm

#

so, let's say I want to implement utility AI

#

I am guessing every time agent is doing nothing - he looks for task

#

and that means each update there's going to be a consideration math

#

that will calculate all possible actions and compare them to each other

#

I don't quite get, where it gets stored (or stored at all?)

#

and how it gets all those random datas for all sorts of considerations

#

Does it require new job for each new task?

#

let's say it does, but then where does all those consideration results go

rustic rain
#

hmmm

#

so for every possible Action in AI behaviour, I add some kind of component with that importance value?

rustic rain
#

oh god, and I definetely would never want to do anything like this xD

#

I want to figure out some kind of dynamic system

#

where you can add ANY new behaviour, even through user mods

#

just by adding new system to assembly

rotund token
#

there's no reason all that above can't be data driven

#

it's basically doing the same thing every time

rustic rain
#

So:
Let's say each Action will have it's own unique system with it's own interfaced component of current value of importance from 0 to 1.

How do I determine which is highest then, without hardcoding job that will look through all of them

rotund token
#

you look through all of them

#

you just don't hard code it

rustic rain
#

hmmm

#

so what if instead of writing value of importance

#

instead I will literally just write that value AND component ID to some other component?

#

which will be only one per agent

rotund token
#

generally you'd do something like

rustic rain
#

that would solve dynamic problem, but will require

rotund token
#

write all the values of id + score to a buffer

rustic rain
#

all those systems to be linear

rotund token
#

then find best score in buffer

#

etc

rustic rain
#

hm

#

hmmmmm

#

or maybe a buffer, yeah

rotund token
#

you can then have layers

#

multiple buckets depending on state

rustic rain
#

but I assume several systems can't write to same buffer at the same time?

rotund token
#

no

#

but you don't do that with components

rustic rain
#

I get it, it's just that it might result in poor perfomance

#

if let's say I'll have 30 different actions

#

and each will have to wait until buffer is free

rotund token
#

all your jobs will be running in parallel

#

it's not like you can magically add 12341234 cores to the user

#

either you have enough entities that you're maxed out or you have so few entities that performance isn't an issue anyway

rotund token
rustic rain
#

So rn I imagine update like this:

  1. I erase all buffers with action importance
  2. Each action system will write it's value to buffer
  3. I determine highest value and add component of it's ID to agent along with some other state component
#

is there even a reason for buffer

#

I guess there is in case I want to do some sort of modification of values

rotund token
#

its useful to have last frame score

#

its not uncommon to use previous frame contributions on current frame

rustic rain
#

hm

#

I'm not sure how to keep track of those contributions

#

in case

#

I don't erase them

#

so I have dynamic buffer
Each update I add new value to it

#

So that would mean data from last update will overlap

#

hmm

#

So if I have ComponentType

#

can I somehow instantiate it

#

hmm, doubt

#

I just thought, maybe I could instantiate it

#

and then get interfaced property from it

viral sonnet
#

hm, so the current problem I have is that the DOTS debugger sees the DynamicHashMap as DynamicBuffer and I see no way of overriding this

#

@rotund token, any idea for this? gonna ask on the forum. maybe they know somethin

rustic rain
#

How do I make a job to clear all dynamic buffers?

wraith urchin
#

Hi guys, it's possible to use dots netcode with relay and lobby ?

solemn hollow
rustic rain
#

oh

#

I didn't realise I could do that

#

lol

#

hmm, I'm trying to figure out how to solve this algorithm

#

I have a tag HasJob which prevents entity from looking for new job

#

but I can't figure out how to get rid of it

#

once job is done

solemn hollow
#

i think you shouldnt have that actually. One of the really nice things about utility AI is that it adapts to changing situations fluently

rustic rain
#

rn it's simplest task:
I assign MoveTarget which makes Entity to go to that position in space

solemn hollow
#

so you kind of want to give it the possiblility to change its mind even after it decided to do sth

rustic rain
#

I'd like that, but first I'm trying to solve the easiest

solemn hollow
#

basically you should split it up into making a decision and executing it

rustic rain
#

make my first algorithm

solemn hollow
#

well that is the easiest way anyways.

rustic rain
#

of simply assigning task

#

from pool of 1 task

#

xD

solemn hollow
#

dont look at it as a task. look at it as a decision

#

and how the decision is then translated into an action can be a diffrent thing

rustic rain
#

hmmm

#

this AI is for simulated NPCs, that live their own life with their personal economies

#

so basically I do kind of need tasks

#

as in

#

agent must go to X point, do Y thing and then do Z action.

#

first task is simple: go to next quadrant

#

around center

#

and getting there uses other subsystems

#

hmmmm

solemn hollow
#

i need the same. I for example have a Decision for GoToTargetEntity and then another one for AttackTarget

#

AttackTarget will score higher as soon as i am in range of the Target

#

that way you get chains of actions

#

but imagine your target dies while the agent runs there. You dont even need to check for that because then another Decision just takes over

rustic rain
#

I do get this point

#

it's good for combat

solemn hollow
#

if you still want actions that cant be interupted you have multiple ways of implementing them. either you give decisions huge "momentum" (they get bonus score if the decision is taken and it decays over time) or you for example implement a statemachine that executes the decision and only takes a new Action if the old one is done

#

no reason to couple Actions to Decisions

rustic rain
#

hmm, is structural journaling is a thing yet?

#

I can't figure out whether my task assigning system works or I simply got bugged loop on task

#

xD

solemn hollow
#

sry havent looked into entity journals yet. shoud be there i think

rustic rain
#

yay, it works

#

now need to add second task

#

xD

sharp nacelle
#

Hey folks. I'm currently trying to upgrade my dots project to entities 0.50. So far most of it is pretty straight forward, but one issue I'm running into is that it seems IJobNativeMultiHashMapVisitKeyValue got either renamed, removed or is no longer exposed. I think it was previously part of unity.rendering and I can still find it in older docs, but no longer in the latest. Is there an alternative I can use to this? I basically need a burstable job that will iterate over a NativeMultiHashMap visiting each value exactly once.

solemn hollow
#

yes i think that got removed. (no idea why) Can't you just copy it into your project from an old package version?

sharp nacelle
#

hm true. I was just wondering if there might be a better alternative instead. I guess there is a reason it got removed

solemn hollow
#

I think i remember someone asking the same question in forum once

sharp nacelle
#

even though this goes over keys it seems, not values

solemn hollow
#

i thought there was another one aswell where they said you should just copy over the old deprecated job into your code.

sharp nacelle
#

hm, I see. I guess I will do that for now, thank you.

#

I hope they will release a replacement for this, though. I feel basic iterator jobs for the native collections should be present for 1.0 whenever that will be ๐Ÿ™‚

#

but anyway, thank you very much ๐Ÿ™‚

solemn hollow
#

@rotund token You asked about the AI Performance if i 10x my units and disable the TimeSlicing:

#

Seems like there is an unoptimized Vectorization going on. there should be no idle time on worker threads. The ConsiderationUpdategroup is where all the AI is happening

#

sry in that screenshot i dont have my mouse over it. it takes 1.98 ms.

#

that is 60 systems. not 30 as i said before. seems my gamedesigner got a bit out of control there

#

so thats 900 entities updating every frame. mainthread: 2ms
Workers: around 6ms (with obvious bug in there)

#

With TimeSliceing / Loadbalancing (not sure what to call it. its kind of both) i had 0 performance difference and i would still update 900 Agents in 30 frames

#

and its f* 60 systems scheduling... i should really look into that.

rustic rain
#

YES

#

it works

#

kek

#

Lezzgo

#

Utility AI

solemn hollow
#

๐Ÿ™‚

rustic rain
#

at least I got a pattern that seems reasonable

solemn hollow
#

im curious what you chose. is your system already handling per Target scoring?

rustic rain
#

it kinda looks like this:
Each agent has buffer with ActionWeight elements which contain ComponentType and weight on current update

for every action I create new system where I have job to set weight, it adds those ActionWeight to buffer which will be read later

Once system chose the action to perform, it simply adds couple of tags: action tag and HasJob tag which indicates, that agent doesn't want to look for job anymore rn.

And each action then determines itself under what circumstances agents will get their action tag HasJob removed.

Meanwhile with those 2 tags, it performs action.

#

kinda like this

#

I like it because it lets me add any new action just by declaring new system, thus any potential user mods will be easy to implement

#

I have a feeling target finding will be huuuuuuuuge pain in future

#

I'll need some kind of huge bookkeeper

solemn hollow
#

yes thats why i was asking. its not that hard to find a working architecture to solve scoring Decisions. the problem (at least for me) was to find a way to score every consideration for each possible target

#

i handle that in hashmaps allocated inside my jobs. with VERY complex cases to handle...

solemn hollow
#

kinda shocked myself tbh ^^

#

that one big hole in my workerthreads is caused by that one consideration beeing authored wrong. if done right its not there at all. What that one long consideration does is vectorizing the distance of 900 agents to about 8k entities lol

#

someone forgot to put a filter in there

rotund token
#

Because unfortunately it is a dynamic buffer I'm just manipulating it to be something else

#

Not sure if the custom IInspect interface would work to create a custom drawer

#

DynamicHashMapDebuggerTypePro

#

Oh this is not for the inspector, it's for your ide inspecting

viral sonnet
#

Oh, I assumed that the dots debugger uses the DebuggerTypeProxy. Does it need another implemenation then?

rotund token
#

you can implement custom inspectors in the dots inspector implementing Inspector<T>

#

however this is just for fields, i haven't looked into how to do it for actual base types (IComponentData etc) or if it'd be possible to override existing behaviour

viral sonnet
#

yeah, the overriding is the real problem sadly :/

#

not sure how to make this work

rotund token
#

think you'd need to edit entities package

#

in particular EntityContainer line 96 is where it's setup

#

unless ๐Ÿค”

#

you know

#

i could probably rewrite this a little to make it work

#

hmm maybe not

#

i'd have to remove ability to remove elements or just leave some holes

#

OR just make the last element in the buffer garbage

#

would hurt performance a bit though hmm

viral sonnet
#

don't bother, it's not that important to screw with the base implementation

#

but maybe I find a way too hook into the debug view implementation of the DynamicBuffer itself

#

a simple check if the buffer is just a byte buffer and redirect to another debug view

rotund token
#

need to edit the package

#

and you wouldn't even need to check for byte buffer you could just check the interface

#
                    Property = CreateInstance(typeof(SharedComponentProperty<>));
                else if (typeof(IBufferElementData).IsAssignableFrom(type))
                    Property = CreateInstance(typeof(DynamicBufferProperty<>));
                else if (typeof(UnityEngine.Object).IsAssignableFrom(type))
                    Property = CreateInstance(typeof(ManagedComponentProperty<>));
                else```
like you'd just inject it i here before IBufferElementData
viral sonnet
#

ah cool

#

seems to me that's not even needed or can be skipped. the final implementation is in EntityIMGUIVisitor.cs in protected override void VisitList<TContainer, TList, TElement>(Property<TContainer, TList> property, ref TContainer container, ref TList value) if (IsDynamicBufferContainer(value.GetType()) && value.Count > kBufferPageLength)

#

or that's just the pager

rotund token
#

this is very old

#

all you need to do now in 0.50 to render a custom struct is inherit from Inspector<T>

viral sonnet
#
                {
                    UnityEngine.Debug.Log("catched");
                    Property = CreateInstance(typeof(DynamicBufferProperty<>));
                }``` I don't get the debug log :/
rotund token
#

did you put it before the buffer line?

viral sonnet
#

yes

rotund token
#

i'd probably add a non-generic implementation of IDynamicHashMap just for inspector convenience if you were doing this

viral sonnet
#

on it, yes the buffer is hit instead. if doesn't evaluate as true

rotund token
#

yeah i don't think open generics can match like that

#
Type g2 = typeof(generic2<>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));```
returns false
> The difference is that open generic types cannot have instances, so one is not "assignable" to the other.
#

but yeah just use a non generic base interface

viral sonnet
#

I was pretty sure there's a way to get the generic one but not a problem, I just use another interface

rotund token
#

i think you need to iterate all the types interfaces

viral sonnet
#

way too much work haha

#

so the needed code seems to be now to setup a class DynamicHashMapBufferProperty and an appropriate container

rotund token
#

have fun ๐Ÿ˜„

#

i find anything to do with the properties package to be a pain

#

like, it's super powerful but it's so abstracted it hurts my head

#

need a phd in it to do anything

viral sonnet
#

I agree, it's like, what is all this?? Does it really need to be this complicated to show/edit some damn values. And all that after my initial cheering where I thought they hooked into the MS DebuggerProxy. How cool would that be if they used that