#archived-dots
1 messages ยท Page 64 of 1
good point yeah
most new ppl don't like them by association
some have suggested using the name singleton in entities was probably a mistake
that's good they are just really simple and easy for storing and accessing little bits of data
i used to use kindof fake singletons in oop a lot using a static to only ever get the one existing instance
IMO singletons aren't inherently bad, even in OOP, but they are often used incorrectly
^ definitely
often used in situations in future where it might be nice to have multiple copies
split screen, testing multiplayer, etc
and suddenly you run into issues where you really wish you didn't have this restriction
Yep, especially annoying in testing if you can't properly "replace" the instance with something else
the great thing about dots is it its easy to copy and change data around
are singletons shared by default?
sorry i mean
each world will have it's own version of the singleton
i guess it came out wrong
used to use this approach:
then i'd basically access the instance of the class with like MC_ItemHandler._instance.SomeField
@rotund token I was looking at your spatial map recently, did I understand correctly that e.g. a quantize step of 4 would divide a 16x16 map into 16 "blocks" of 4x4 each?
I only need 2 dimensions!
I was a little confused on how to read the values off of the NativeKeyedMap, do I do Map[Hash(Quantized(position))]?
did you see example i posted on forum
Nope
Promised for ages I'd publicly post my core library and I finally got around to it
https://gitlab.com/tertle/com.bovinelabs.core...
someone asked for one so i threw something together a few days ago
So here's the problem,
I get a couple of hours to do some project work and I have 2 options
a) write documentation and samples for a saving library
b) write an awesome large simulation
i choose b) every time ^_^'
Understandable ๐
no one reads docs anyway ๐คท
I'd love to
So I seem to be able to load/reload my subscene from code which is good, but I'm getting an issue with some stuff after reloads.
It looks like I'm missing something that I need to initialize with the Inputsystem
ObjectDisposedException: Cannot access a disposed object.
Object name: 'The NativeArray has been disposed, it is not allowed to access it'.
is it ok if a system's name doesn't match the file name?
it should be ok
I'm getting weird behavior when calling GetAllUniqueSharedComponents() where it outputs two of the same shared component
thanks!
What's worse is that getting the entity count from an entity with a shared component filter outputs 0
seems easy to if it out
I checked the Entities hierarchy and there are
And should GetAllUniqueSharedComponents() ever output duplicate entries?
can't find anything about it in documentation so probably it shouldn't
Yeah agree
That's expected
Get all unique shared components returns all components the em knows about
Even if it's not attached to any entity
As well as the default shared component in index 0
then it will get all even from prefabs?
If those prefabs have been loaded into entity world I believe it should
I'm not sure why you're getting a second default copy back though
you should get award or like life-achievement for providing this community with better information than documentation 
So checking EntityManager.Exists on an entity that has been disposed throws an error instead of returning false... >_>
and trying to catch ObjectDisposedException doesn't work x.x
its in a mono
so when you dispose your world that reference is now invalid
which is fine, it's just annoying that it won't let me make a new one
it's basically a singleton entity, so it was just making itself
how is singleton entity making itself?
it's a mono on a game object making a single entity to represent something
so why you can't recreate it in new world?
I only destroyed the entity world so the monos stuck around and just lost their references
and i was trying to recreate it in the mono if it didn't exist.
ah and it throws an error on check
what about event on world destruction/creation?
hmmm true I'm already throwing one too
yeah it's strange that it throws instead of returning false
isn't entity just an ID and version?
but we have a new manager, and i'm checking an entity that it wouldn't have.
oh you have a new manager?
whats it throwing then
entity came from a different world or something
yeah
that's why it's strange ๐
yeah because entity index > than the max index this entitymanager has ever created
so it thinks you made a mistake by using wrong one
(which you did)
pshh
i gave it a property entity object, and it didn't have it.
but it didn't give me my boolean
hmm seems reasonable
this is reason #17 i strongly recommend against accessing entity world from MB
I'm not trying to, but at some point you have to
so systems with managed components?
i don't believe that's true
i believe you can write all your data from systems to monobehaviours
and how do you convert a user click
in a system
my input is read in a system to components
mine also
welp i'm noob. I just used a Input Manager
and you should be able to in the system
tried the new InputSystem. didn't know I could do it in a system
make singleton entity from all your fields
managed component / GameObject.Find
anyway this comes from experience.
a project at work does this a lot and it has caused endless problems
This seems like great advice, but i'm so tired it's not clicking. ๐ฆ
strange given that not so long ago hybrid was preferred
not saying dont use hybrid
i'm saying in a hybrid approach, make your data only flow 1 way
the life cycle management of entities vs monobehaviour is really incompatible
(feel free to disregard any general sweeping advice I have. I think it's important to test, experiment and learn from mistakes yourself to build knowledge)
(i will still tell answer your questions and help even if I personally think it's a poor way to do something)
ofc, but I truely appreciate your help. So feel free to give any advice ๐
what would be the recommended way to reading a UI button click from a system?
i generally recommend using UI toolkit these days and I think it works well with systems as you don't need gameobjects etc and can just set it up in the system
however if you prefer ugui or need to use it, i'd probably just write a presentation layer on a monobehaviour and get a reference to that from a system
don't know what is recommended way but I made normal ui events change bool flags in managed component which then are read in a system
i guess another excuse to give UI Toolkit another try. Last time I tried it, it only seemed nice as an editor window
how do you handle events and entity creation?
and do you load ui document from resources or managed components?
i bake them
so managed components
(though there seems to be a bit of a bug in the recent entities when building related to this and the resource not being included)
I've been making my own events and having my UIBuilder buttons fire them and execute them in systems.
and what about those pesky entity creating events?
i don't recall any UI of mine that create entities directly
despite doing this, for the normal non-ui element clicks i was using the InputSystem with entitymanager, which now was the issue
however I'd probably just store it in a queue in the system and play it back on update
(if not just create it on the spot)
probably just EM directly
wouldn't this make a sync point?
sure but how fast is a user clicking UI
and i suspect the events come either start or end of frame anyway
persistant in managed
Im heavily working on mvvm implementation for ui toolkit within ecs, while trying to follow best web design practices
It might be ready as prototype in next couple of days
I already implemented text binding with localization support
and what is really good, I make it built on mvvmtoolkit package
From communitytoolkits
Which is what microsoft recommends to use these days as default
In gui apps
i'm interested to see the flow when you're done and what it adds over uitoolkit bindings (and upcoming bindings)
i do like the idea of this though
Hmm. Is NativeList safe when used in parallel?
reading? yes
writing? it has a parallel variation
the parallel writer doesn't support increasing capacity
doubt there's going to be too much UI requests per frame
you can't increase capacity in parallel
ah, got it
hmm
you can't pass in the enabled bit as well as the value in ijobentity?
private void Execute(EnabledRefRW<FindPath> findPathEnabled, in FindPath findPath)
that's a bit annoying
guess i'm converting this to an IJobChunk
Yeah the second copy is really weird. Worse part is when I call CalculateEntityCount() on an entity query with the default scd filter it returns zero despite me knowing there are entities that exist
The solution for now is to never assign the default scd to any entities so they would be discoverable with an EntityQuery
Hey everyone, my debugging experience in Rider is kind of messed up.
In one part of the UI variables are shown to not exist in the current context and in other parts they are shown to be fine.
Does anyone else have this problem? It makes using conditional breakpoints impossible.
use bottom debug panel
it shows all context variables
yea but conditional breakpoints are broken :/
a lot of debugging is broken because this is not the code that actually runs ๐
ah yes, true ๐
Is it possible to run an foreach only on disabled entities?
WithAll<Disabled>?
iirc you'll also need to set the query option to include disabled entities
EntityQueryOptions.IncludeDisabledEntities
yeah I was looking at that part
that doesn't seem to work foreach (var (isAlivevar, enty) in SystemAPI.Query<RefRO<IsAliveDat>>().WithOptions(EntityQueryOptions.IncludeDisabledEntities).WithAll<Disabled>().WithAll<ShelfIsleStaticTag>().WithEntityAccess()) {
that's the query
Are you sure you have something that actually matches that?
yeah it works without the withoptions and withall it just work on all the entities
Well I would assume it wouldn't include the disabled entities
and there is a disabled component in the heirarchy
yeah I'm just trying to do the opposite
Yes, I was just mentioning it since you said it included "all entities", it should be skipping the disabled ones for the inverse
'ShelfIsleStaticTag' - supermarket simulator? ๐
not quite I'm in the mood to just destroy stuff at the mo
If I want to use a burst function pointer that modifies a dynamic buffer I'll need to pass it as a void* instead of the actual type, correct?
Also, I would assume that's also how I could pass the entire DynamicBuffer and not just the pointer to its internal memory for easier modification, as long as the stack variable is still valid at the point the burst function is called?
WithOptions(EntityQueryOptions.IgnoreComponentEnabledState) it seems like I can't get that part to work
wdym? I thought you wanted to get disabled entities
I do, but it seems no matter what option I choose the disabled entities are not included
foreach (var (isAlivevar, enty) in SystemAPI.Query<RefRO<IsAliveDat>>().WithOptions(EntityQueryOptions.IncludeDisabledEntities).WithAll<ShelfIsleStaticTag>().WithEntityAccess())
{
if(state.EntityManager.IsComponentEnabled<IsAliveDat>(enty))
{
Debug.Log("iscomponent is enabled");
return;
}
Debug.Log("the entity was nearly destroyed");
state.EntityManager.DestroyEntity(enty);
}```
Have you tried with just WithOptions(EntityQueryOptions.IncludeDisabledEntities)?
And see if that matches anything
yeah tried it without the withall and still nothing
I mean it gets all the entities just not the one disabled
[WorldSystemFilter(WorldSystemFilterFlags.LocalSimulation)]
public partial struct TestSystem : ISystem
{
public void OnCreate(ref SystemState state) { }
public void OnDestroy(ref SystemState state) { }
public struct MyData : IComponentData
{
public float Value;
}
public void OnUpdate(ref SystemState state)
{
var disabledEntity = state.EntityManager.CreateEntity(typeof(Disabled), typeof(MyData));
foreach (var (data, entity) in SystemAPI.Query<RefRO<MyData>>().WithOptions(EntityQueryOptions.IncludeDisabledEntities).WithEntityAccess())
Debug.Log(data.ValueRO.Value);
state.EntityManager.DestroyEntity(disabledEntity);
}
}
this works for me
removing the option stops matching the entity
how does that work, your component doesn't inherit from IEnableable
Why should it?
because that's how you get and use enableable components?
Who ever said anything about enablable components? This was about querying for disabled components
public struct IsAliveDat : IComponentData, IEnableableComponent{ } like that
what other disabled entities are there though
that's what I was talking about enableable components which are components you can enable or disable
That's not the same as the Disabled component
Disabled is a special component that unity uses on all queries to ignore a subset of entities, unless you specify it in the option
There is only one Disabled component
(called Disabled)
You can have any number of IEnableableComponents, but they have nothing to do with Disabled
oh I did not know that
It's akin to GameObject.SetActive from the mono world, and the respective FindObjectOfType / GetComponent functions there
too many confusing terms, sorry
In this case specifically the fact that those functions ignore disabled components / objects
It's all good ๐
If you want to query on only your disabled IsAliveDat I don't think that's currently possible
You'll have to query on all and check, not 100% sure though
I'm new to this, so Disabled is added to entities to "disable" everything attached and the IEnableableComponent is a part of a component for "disabling" just that component?
Again, Disabled and IEnableableComponent have nothing to do with each other
yeah that's fine I guess, I hope they do make it so you can query enableable components that are disabled because that would be handy
They are entirely separate concepts
Ok, i'll check docs
Disabled is akin to GameObject.SetActive, while IEnableableComponents are similar to Component.enabled
I guess the easiest way to explain it would be that Disabled removes the entity from all queries, while disabling a single component only removes that entity from all queries that query on that component
hmm, looking at docs and your explanation, my analogy seems spot on
Yes, you are correct in your analogy. I only reiterated due to the previous conversation. You don't need Disabled or anything to disable a component
thanks for that, I'm suprised I haven't come across disabled components in all my time using DOTS
you just need it if you want to prevent the entity to be included in queries (by default)
Disabled has been there since version 0.0 ๐
Oh, or are you talking about IEnableableComponent?
no yeah disabled components, I think I was there close to the beginning, never saw them or a reason to use them ๐
Yes I guess it depends on what you are doing. I'm not using them for anything either atm
I would also take a look at how IEnableablComponent functions internally, since there are some gotchas if you are using IJobChunk
If you are only using SystemAPI.Query and IJobEntity it all pretty much works automatically
I'll probably be fine I avoid IJobChunk anyway to be honest that's to technical for me
It's not that complicated to understand ๐
But with the new IJobEntityChunkBeginEnd interface there is now a lot less need to use them
idiomatic or Entities.ForEach?
the Isystem one
It's not possible with SystemAPI if that's what you are asking
I guess I'll have to use a commandbuffer then thanks
Why does DynamicBuffer.AddRange not accept a NativeArray.ReadOnly 
Thinking about it I could just do the inverse, change the name to isDead and start it off disabled, then enable it ontrigger ๐ค
Is there a reason you are even using IEnableableComponents in this example?
Why not just use a normal tag component
Well because they are supposed to be better, faster plus I want to learn how they work
They aren't necessarily faster, they can also be slower
It depends on how often you plan to change the value
(and what you are doing sounds like a low frequency state change)
the only thing they good for - very quick state switching
I hadn't heard of them being slower, but I think they good for my case I don't want them to persist for any frames
so you don't have to do tons of structural changes all the time
They slow down iteration time for jobs that use them
otherwise, you are processing dead weight
Interesting, no other jobs use the comp so I guess I should be fine
That one job will still run slower compared to using a tag component
It's not going to break your performance or anything but it is important to understand the uses for it imo
I mean slow in jobs is kind of relative, it's all mostly super fast
here's the thing. Let's say you have 5k dead entities and 10k alive entities. Generally death does not happen too often.
So everytime each your job will have to process all those 5k dead entities.
If instead you use dead tag, they won't even be part of query and you can distinguish jobs for dead and alive
with enabled comp you gain perfomance if death happens a lot, like constantly.
with tag you benefit in long term, if death/ressurection does not happen often
it also really affect project architecture
in case dead require specific logic - it's going to be problematic, as query will be same as for alive
I roughly profiled this yesterday actually
There's minimal overhead in the 0% and 100% cases which is nice for short events
Can process the chunks pretty fast
Was pretty happy with results
Well one plus is I avoid a structural change
but 0% and 100% are not very realistic, aren't they?
Depends on use case, I wasn't really going into this to benchmark those cases I just wanted a baseline
Do you guys think binding through VisualElement's name (since, non text elements don't have text attribute) is ok?
๐ค
i dislike that kind of binding but it's very common for CSS to query either by id/name or css class. so, not much options really
True
Well, binding path property is really limited and not even available on all elements
So until unity rolls a better one, I guess that'll do
when i tried VEs I had hopes that it would be different. unity style. i was shocked it is not
best to make a setup that handles changing names. nothing sucks more than a sudden unbound VE because the name changed
Binding only happens once
I don't think rebinding is required anyway
Mostly you bind static stuff
Dynamic is handled by hand
i really need Unity to expose journaling event writing
even if only to mark it as internal, i don't want to duplicate all this code
a lot of my tricky change filter stuff doesn't write proper journaling events
like accessing RO but writing
and i think this will bite me at some point if I don't manually write the correct event
(The actual EntitiesJournaling.Add record is internal however I don't want to duplicate all this code for specific events and risk it breaking/changing on updates)
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
var entities = chunk.GetNativeArray(this.EntityHandle);
// The destroy system opens with RO even though it writes to avoid bumping change filters as we only want to react to external updates
var entityDestroys = (EntityDestroy*)chunk.GetComponentDataPtrRO(ref this.EntityDestroyHandle);
#if (UNITY_EDITOR || DEVELOPMENT_BUILD) && !DISABLE_ENTITIES_JOURNALING
var anyWrite = false;
#endif
for (var i = 0; i < chunk.Count; i++)
{
if (entityDestroys[i].Value == 0)
{
continue;
}
if (entityDestroys[i].Value < 0)
{
entityDestroys[i] = EntityDestroy.Reset;
#if (UNITY_EDITOR || DEVELOPMENT_BUILD) && !DISABLE_ENTITIES_JOURNALING
anyWrite = true;
#endif
continue;
}
this.CommandBuffer.DestroyEntity(unfilteredChunkIndex, entities[i]);
}
#if (UNITY_EDITOR || DEVELOPMENT_BUILD) && !DISABLE_ENTITIES_JOURNALING
if (anyWrite)
{
chunk.JournalAddRecordGetComponentDataRW(ref this.EntityDestroyHandle, entityDestroys, sizeof(EntityDestroy) * chunk.Count);
}
#endif
}```
pretty gross though
i'd also love to be able to extend the events to add my own
but having a look at source it just flat out throws an exception if it isn't an existing enum field
does getting component ptrs from chunk write to journaling?
GetComponentDataPtrRW does
Is anyone getting these type of errors?
A BatchDrawCommand was submitted with an invalid Batch, Mesh, or Material ID. BatchDrawCommand index: 6 (index in range: 6), BatchDrawRange index: 0 This is not supported when rendering with a BatchRendererGroup (or Entities Graphics). MaterialID (0x5) MeshID (0xD) BatchID (0x1)
sounds like you might be passing a null mesh/material or something invalid
but no, i haven't see this personally
Hmm how about this one?
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)```
Maybe fixed in 2022.2.3: https://forum.unity.com/threads/leaked-batchrenderergroup-error-requires-restart-to-go-away.1375359/#post-8716449
Yeah that looks like the common bug
I really don't understand LinkedEntityGroup sometimes conversion adds it automatically and most of the time it doesn't
it adds it to any prefab by default
hmm maybe that's it, its not a proper prefab
nope doesn't seem to be adding it to my prefab, it adds a child buffer but not the linkedentitygroup
basically any call of GetEntity(entity) that is a prefab adds it
also all ghosts have it added in netcode
People's MaterialPropertyAttribute aren't working atm right?
https://forum.unity.com/threads/materialpropertyattribute-hybrid-instancing-stopped-working-in-2022-2-2f1.1386009/
i haven't tried but that's what i've heard from this channel
thanks for that tertle, I'm trying to nail down exactly what
break point in it ^_^ (with open subscene)
it seems like if its already in the scene that's a common factor
you can put a breakpoint to check a subscene somehow, I found out you can't put it in a baker
it should breakpoint fine IF you are doing it with an open subscene
put breakpoint, open subscene
it won't work if you are doing it with closed subscenes because they are executing in a separate process (you'd have to attach to that specific process instead)
yeah I got it working just had to save it first
how to do polymorphism with dots?
for example, a character can cast many abilities on a complex rpg. How to represent all this abilities?
Is using function pointers good?
or a enum + switch?
Represent them with different entities.
one system per ability type?
how does it scales then
what if i have 300 abilities like diablo 2
i have a gameobject with image component inside one of my prefabs..
and during baking it takes a reference to that gameobject in a managed component
but when i actually spawn the prefab entity this gameobject reference points to the original prefab child gameobject..
any ideas what's going on there
Behavior is driven by components and systems. Similar behavior will use similar components.
that doesn't sound very data driven
if you want a game with that many abilities you really need to drive them from data
you should be able to create entirely new abilities without any code once the implementation has been setup
if your designers need to come in and ask a developer every time they want to experiment with an ability, every ones time is being wasted and iteration will be extremely slow
What did you expect it to point at? I think you're leaving out some information here.
yeah i'm trying to figure out how this works as i've barely used managed components or gameobjects at all with ecs so far..
so basically, i decided to make my healthbars as a child of the unit prefab..
previously, my entire unit hierarchy converted to entities, but now i've added in this healthbar which has an Image component
so what i expected to happen was:
when i spawn the ecs version of the prefab, it would maybe spawn a gameobject version of the healthbar with the managed component
but i guess no, maybe it's actually converting the healthbar to an entity, with a managed Image component on it?
Afaik you need to manage the spawning and despawning manually of the gameObject reference.
You can see in the NetCode samples they are doing this for healthbars. Alas they are not using the Clonable and Diposable interfaces they mention in the documentation, but said will fix in future.
yeah i've looked at how they've done that, they have a separate isystem which spawns healthbars at runtime
i was hoping to avoid that extra step but i guess it might be simpler
so basically - the healthbar with Image component doesn't appear to be getting converted to an entity with a managed component, is that the expected behaviour?
You can just create two systems and use it for all companion gameObjects creation and destruction : )
You're just referencing an gameObject here? What did you expect to happen?
yeah i realize that expecting it to spawn a GO is silly, but i guess i expected it to convert the healthbar to an entity with a managed Image component on it, or something ๐
Well ok. So if they are children of the converted object, they would be attempted to be converted as well, but I'm guessing you're using non authored components here. So you wouldn't notice.
so because the healthbar has an Image component, it's basically ignored by baking is that right?
i assume so as i get nothing here:
Afaik Image doesn't have any baking for it, so you wouldn't get anything out of it.
right yeah
it's the first time i've attempted to do this, everything else has been 100% conversion to entities so far
I've only used it for my camera so far, so I'm not too experienced ๐
healthbars previously were managed by a monobehaviour, which grabbed a native hashmap containing all the positions etc
This is the ECS related channel right?
it is
I'm having issues with the Spawner example in the ECS documentation. https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/ecs-workflow-create-systems.html
The prefab won't show up in scene.
I have URP set up and all the settings seem to be fine but the prefab won't show up on scene only game.
Made a forum post if anyone can help. https://forum.unity.com/threads/cant-see-anything-in-scene-view-following-documentation-tutorial-1-0-0-pre-15.1386552/
if you just create an empty scene, with an empty SubScene in it, put a simple Cube in the subscene, and then run it, does the cube show up?
Yes
hmm if you have those 2 things (entities.graphics and a srp installed) it should just work
These are my packages in unity 2022.2.1f1 in case it's any help:
๐ฑ
still on burst 1.7 is interesting
do people not care or not know about break pointing in burst in 1.8?
This is my current list
your kind is not welcome around here ๐
i would suggest removing netcode and just getting a basic implementation working first
I've sparked a civil war 
I'll try that.
i do believe a basic netcode setup should still work fine for you loading an entity in a subscene
but it will be setting up 2 worlds for you
it's a fresh project yeah, ie you don't have any legacy stuff in your manifest or anything
could you show us your project settings/graphics page
Standard URP 3D
as well as the prefab you're trying to convert
i might be misremembering but i think i had an issue with still having hybrid in my manifest or something when porting a project to 1.0
obviously not your issue though
so yeah that definitely looks fine
what's the subscene + prefab (cube)
OH 1 sec are you looking at scene or game view?
yeah
go to preferences, entities
change scene view from authoring to runtime
or something like that
Baking -> Scene View Mode -> Runtime Data?
yeah
It work!
(unity really has to change this default, this has to be at least the 5th time I've seen this issue popup in a month)
Ty, but i dont have artists. Im the developer and the artistits lol
Do you suggest having abilities as many pieces?
Thanks for the help!
Another issue I'm having is a parented prefab freaking out when it's instantiated
It basically falls apart and the cube portion disappears
are your children physic objects
Just 3D primitives
they don't have a collider?
They do
that would make them a physics object ^_^'
I see.
Why would that make the instantiation freak out?
I'll remove the colliders and see what happens first.
Removed the colliders and it works fine O-Ob
dynamic bodies must be root
Dynamic bodies (i.e., those with PhysicsVelocity) require LocalTransform component. Their values are presumed to be in world space. As such, dynamic bodies are unparented during entity baking.
Static bodies (i.e., those with PhysicsCollider but without PhysicsVelocity) require at least one of either LocalTransform, and/or LocalToWorld. For static bodies without a Parent, physics can read their LocalTransform values directly, as they are presumed to be in world space. World space transformations are decomposed from LocalToWorld if the body has a Parent, using whatever the current value is (which may be based on the results of the transform systems at the end of the previous frame). For best performance and up-to-date results, it is recommended that static bodies do not have a Parent.
As such, dynamic bodies are unparented during entity baking. I see
basically unity physics really doesn't want physic objects to have parents
even statics
For best performance and up-to-date results, it is recommended that static bodies do not have a Parent
what did you mean about Clonable and Disposable?
Ahh thanks! I really should read the docs start to finish rather than dipping in when i need to
That's pretty interesting actually
It seems it would be useful for prefabs with managed components on them
HOWEVER.. how could a prefab with a managed component reference an instance of a gameobject if gameobjects have to be manually spawned after baking
ie say you have a prefab that held a reference to a particle system
if i just added an IClonable managed component to the prefab with a reference to the particle system, would it then automatically spawn that particlesystem gameobject when i spawn the prefab at runtime
the example above shows exactly how it does this
UnityEngine.Object.Instantiate(ParticleSystem)
inside clone
or would i have to spawn the particlesystem gameobject at runtime, and then assign the IColonable back to the prefab in hindsight
Clone() is called on Instantiation
so Instantiating a copy of the entity prefab will instantiate a new copy of the particlesystem
hmm ok so that would appear to solve the healthbar problem then
and i take it their netcode sample wouldn't require a healthbar spawner system if their player prefabs had an IClonable added using an authoring component right
i guess i should test this out ๐
so yeah this appears to work
public class Healthbar : IComponentData, IDisposable, ICloneable
{
public Transform HealthBar;
public Image HealthSlider;
public Image StrengthSlider;
public float3 Offset;
public void Dispose()
{
UnityEngine.Object.Destroy(HealthBar.gameObject);
}
public object Clone()
{
var newHealthbar = UnityEngine.Object.Instantiate(HealthBar.gameObject);
return new Healthbar {
HealthBar = newHealthbar.transform,
HealthSlider = newHealthbar.transform.GetChild(0).GetChild(0).GetComponent<Image>(),
StrengthSlider = newHealthbar.transform.GetChild(0).GetChild(0).GetComponent<Image>(),
Offset = Offset
};
}
}
public class HealthbarAuthoring : MonoBehaviour
{
public GameObject HealthbarPrefab;
public Vector3 Offset;
class AuthBaker : Baker<HealthbarAuthoring>
{
public override void Bake(HealthbarAuthoring authoring)
{
var healthbar = authoring.HealthbarPrefab;
AddComponentObject(new Healthbar
{
HealthBar = healthbar.transform,
Offset = authoring.Offset
});
}
}
}
so the initial baked version of the component gets a reference to the actual prefab
then when i instantiate the prefab at runtime, it obviously fires Clone() which instantiates the gameobject prefab and assigns that reference to the new Healthbar component
how nice right
yes indeed
assuming if/when the entity is destroyed it'll fire Dispose and cleanup the gameobject without me having to manually referencing the Healthbar component to do that
@misty wedge think i'll release a free version of my saving library
otherwise it's never getting out at this rate
Is this at all possible.. it's complaining that the job has a non-value field type ( WorldSpaceUI is a managed component) :
public void OnUpdate(ref SystemState state)
{
var ecbSysSingleton = SystemAPI.GetSingleton<BeginInitializationEntityCommandBufferSystem.Singleton>();
var query_worldspaceUI = state.EntityManager.CreateEntityQuery(ComponentType.ReadOnly<WorldSpaceUI>());
new SpawnHealthbarsJob()
{
ecb = ecbSysSingleton.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter(),
worldSpaceUI = query_worldspaceUI.GetSingleton<WorldSpaceUI>()
}.Run();
}
public partial struct SpawnHealthbarsJob : IJobEntity
{
public EntityCommandBuffer.ParallelWriter ecb;
public WorldSpaceUI worldSpaceUI;
public void Execute([EntityIndexInQuery] int entityIndexInQuery, Entity e, HealthbarSpawner spawner, Healthbar healthbar)
{
var newHealthbar = UnityEngine.Object.Instantiate(spawner.HealthbarPrefab, worldSpaceUI.WorldSpaceUIGameobject.transform);
healthbar.HealthBar = newHealthbar.transform;
healthbar.HealthSlider = newHealthbar.transform.GetChild(0).GetChild(0).GetComponent<Image>();
healthbar.StrengthSlider = newHealthbar.transform.GetChild(0).GetChild(0).GetComponent<Image>();
ecb.RemoveComponent<HealthbarSpawner>(entityIndexInQuery, e);
}
}
i did try Query but it was complaining about putting a managed type in the query ๐
the amount of fucking around for the simplest shit is just unreal here
jobs don't support managed data (regardless of burst)
yeah i mean that figures i guess
i don't think Query does either as it compiles to a job right
foreach (var (component, entity) in SystemAPI.Query<CMTransposer>()
.WithAll<CinemachineTransposer>().WithChangeFilter<CMTransposer>().WithEntityAccess())
{
var transposer = this.EntityManager.GetComponentObject<CinemachineTransposer>(entity);
transposer.m_BindingMode = component.BindingMode;
transposer.m_FollowOffset = component.FollowOffset;
transposer.m_XDamping = math.clamp(component.XDamping, 0, 20);
transposer.m_YDamping = math.clamp(component.YDamping, 0, 20);
transposer.m_ZDamping = math.clamp(component.ZDamping, 0, 20);
transposer.m_AngularDampingMode = component.AngularDampingMode;
transposer.m_PitchDamping = math.clamp(component.PitchDamping, 0, 20);
transposer.m_YawDamping = math.clamp(component.YawDamping, 0, 20);
transposer.m_RollDamping = math.clamp(component.RollDamping, 0, 20);
transposer.m_AngularDamping = math.clamp(component.AngularDamping, 0, 20);
}```
( well is codegenned to a job )
okay lemme try this, thanks
Okay thank you sir, that approach is working:
public void OnUpdate(ref SystemState state)
{
var ecbSysSingleton = SystemAPI.GetSingleton<BeginInitializationEntityCommandBufferSystem.Singleton>();
var ecb = ecbSysSingleton.CreateCommandBuffer(state.WorldUnmanaged);
var query_worldspaceUI = state.EntityManager.CreateEntityQuery(ComponentType.ReadOnly<WorldSpaceUI>());
var worldSpaceUI = query_worldspaceUI.GetSingleton<WorldSpaceUI>().WorldSpaceUIGameobject.transform;
foreach (var (spawner, healthbar, entity) in SystemAPI.Query<HealthbarSpawner, Healthbar>().WithEntityAccess())
{
var newHealthbar = UnityEngine.Object.Instantiate(spawner.HealthbarPrefab, worldSpaceUI);
healthbar.HealthBar = newHealthbar.transform;
healthbar.HealthSlider = newHealthbar.transform.GetChild(0).GetChild(0).GetComponent<Image>();
healthbar.StrengthSlider = newHealthbar.transform.GetChild(0).GetChild(0).GetComponent<Image>();
ecb.RemoveComponent<HealthbarSpawner>(entity);
}
}
is it not possible to run something like that in parallel then, because it's using managed components?
you can pretty much use nothing in UnityEngine off the main thread
the reason it had complained about putting managed type in query before i think is because i'd tried like SystemAPI.Query<RefRO<MyManagedComponent>>
whereas just doing SystemAPI.Query<MyManagedComponent> seems to work fine
which, tbf, makes sense
first time using these idiomatic foreach's tbh
have basically been trying to avoid anything other than ISystem with jobs as much as possible
as much as i enjoyed using Entities.ForEach previously
you use it when you need to store managed data
Can you mix it? have a managed and non managed component for same entity?
think is cool. I didn`t knew ECS can access managed data
Yes
you can attach anything to an entity btw
You can just go
AddComponentObject(entity, new MyClass())
Do you cache references to other components like we do in monobehaviour with GetComponent?
ideally you should be trying to stick in the unmanaged world as much as possible
and avoid all managed data as it's going to slow you down a lot
but currently that is not always possible so it's nice to have these options
Yeah, makes sense
Code is tested and working in play mode. However, when building it get this error: Use of possibly unassigned field 'OffsetMatrix'
It's referring to this line: var offsetMatrix = math.mul(math.inverse(partAttachmentData.PartElement.OffsetMatrix), targetAttachedElement.CurrentOffset);
I assure you that the field OffsetMatrix in the PartElement struct is assigned prior to it being read here, that's a guarantee. But why does building throw this? Is there a way to turn off this check for unassigned fields because it's giving me other false positives as well.
Woah, and what does purple color of user name here mean?
Oh, I figured it out, it was because I had methods that had out SomeStruct someStruct.
public partial struct SerializeJob : IJobEntity, IJobEntityChunkBeginEnd
{
[ReadOnly] public CollisionWorld world;
[ReadOnly] public ComponentLookup<NetworkedEntity> networkedEntities;
[ReadOnly] public double timeAsDouble;
[NativeDisableContainerSafetyRestriction]
private NativeList<DistanceHit> distanceHits;
public unsafe void Execute(in WorldTransform transform, in NetworkedPeer peer, in Entity entity)
{
distanceHits.Clear();
Debug.Log(timeAsDouble);
if (world.OverlapSphere(transform.Position, 20.0f, ref distanceHits, CollisionFilter.Default, QueryInteraction.Default))
{
for(int it = 0; it < distanceHits.Length; ++it)
{
ref DistanceHit hit = ref distanceHits.ElementAt(it);
if(networkedEntities.TryGetComponent(hit.Entity, out NetworkedEntity otherEntity))
{
/* Add to buffer */
}
}
}
}
public bool OnChunkBegin(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
distanceHits = new NativeList<DistanceHit>(Allocator.TempJob);
return true;
}
public void OnChunkEnd(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask, bool chunkWasExecuted)
{
distanceHits.Dispose();
}
}```
is this code good for a network serialization system?
It will only serialize entities at 20 meters distance from myself
distanceHits = new NativeList<DistanceHit>(Allocator.TempJob);
should be Temp
surprised it's not erroring?
there is no error
[NativeDisableContainerSafetyRestriction]
maybe because you turned off errors
you can't use TempJob memory inside a job
just use Temp
it's faster anyway
it's for passing data into jobs
you can't pass temp data into jobs
temp data uses a bump allocator per thread
and must stay within that thread
I see
TempJob can survive multiple jobs
But do you think this code is good for a game with like 500 players?
bandwidth is not a problem. My previous game had only 4mbps with 1200 players
you could slice it if it comes to it
updating relevancy every frame is not exactly needed
the only flaw with this is that every ghost needs to be a physics object
what if you create ghost skill effects
etc
anyway it's more of a problem to deal with when you get there
Do you think it can handle like 500 players?
My old engine was handling 1200 to 3000 per server but it was .net core
Provably but I have not tested at that scale
the bottleneck was serialization actually not checking what is near
How many players do your game handle?
bruuuuh, VE's name does not support symbols in name either
๐ค
I guess I can use tooltip for binding
what if you want to use the tooltip
and how do you intend to localize/bind that separate to the value field
yeah
I decided
to only do binding on text elements
it's temporary solution anyway
so... it'll do
works kind of like this:
#LocaleKey:arg1:arg2:arg3
attaches automatically to public Property
so the thing i'm curious about is how you determine what localization table to use for your bindings
so each menu has it's own table?
yeah
so what if i have a character screen with stats
and then a skill screen with stats
both will probablyy want to read from the stats localization table for some bindings driven from data
but the labels etc might want to read from a general UI table
you can use same tables
on different views
I considered
having field
for shared table
but not sure yet
yes but i want to use different tables on same view
if it's required
this is basically the problem i have atm
from project at work, having everything in 1 table is unworkable
I work on click binding
apart from it's super hard to maintain
it completely breaks localization with lag
we ended up doing most of our localization outside the editor in gridly
and just importing it into separate tables in localization package
i don't have a solution for this but what I'd like to be able to do is set the localization table per element
Table:Key
kind of deal
well, the first thing comes to mind
(again this is not how my implementation works at all, but this is what I will strive for eventually)
just have an array of tables
(was just hoping you had a magical fix)
and during resolution of binding
just query them until entry is found
first table with entry will be used
that's about it
how do you handle language changes at runtime
same as you
tableChanged += callback
all right, let's go
click binding is done
all binding keys are separated by ;
spaces are ignored
i really wish i could use LocalizedString
@ is symbol for click binding
instead of redoing the whole thing like i'm doing atm
looking nice
I will do value binding
that's my next step
basically
if I don't want to use localization for some reason
or I want to pass pure text
or I already manage localization internally
binding will be done on string property
so what are your buttons binding to?
yep i know
one sec
public partial class MainMenuViewModel : ViewModel, IRecipient<OpenMainMenuMessage>
{
private NativeReference<Budget> _budget;
private NativeReference<Buildings> _buildings;
private NativeReference<MinionCount> _minions;
public override void OnInit()
{
Messenger.Register<OpenMainMenuMessage>(this);
_budget = EntityManager.GetSingletonStructReference<Budget>();
_buildings = EntityManager.GetSingletonStructReference<Buildings>();
_minions = EntityManager.GetSingletonStructReference<MinionCount>();
}
public void Receive(OpenMainMenuMessage message)
{
Enable();
}
[RelayCommand]
private void StartNewGame()
{
Messenger.Send<CloseScreensMessage>();
Messenger.Send<EnableGameScreensMessage>();
Messenger.Send<UpdateUIMessage>();
EntityManager.AddComponentData(EntityManager.CreateEntity(), new GameInstanceRequest
{
state = GameState.Routine
});
}
}
in fact
I can make it even shorter
so instead of doing my own url system I switched over to Message system of mvvm toolkit
it is really powerful
so these are not asynchronous calls then i take it?
and well optimized already
what?
Send?
it supports async
it support reply
it supports multiple async reply
kek
i mean from the fact that StartNewGame is using EM stuff
I wrote a wrapper for UniTask
oh, it is to initialize internal game logic
can this setup support multiple worlds with separate UI?
you probably aren't interested in this
just curious about the flexibility
hm
it works like this
once world created
init system will query for all authoring views in scene
I should probably change it to being System based, not object based
so for each view found it initializes ViewModel SystemBase
creates all bindings and all
View itself
can be immutable
so as many worlds can be created
and it doesn't even require UIDocument to work
it can be removed/added
and UI will be restored
I don't use subscenes btw for this
I see no point in it
and they don't work with webgl
which is my target rn
I use it for architecture
does it actually build for webgl atm?
yeah
I regularly build
sadly in 2022.2 they broke compiler and building is extremely long
almost an hour
and if I use older compiler - UI toolkit events don't work
๐ฅฒ
hmm my work builds are nearly an hour but its long before 2022
still on 2020
pretty sure it was like burst 1.8
used to be 5 mins tops
but that's a known bug
which is known by unity
yay, time get rid of all this crap
RootVisualElement.Q<Button>("Cancel").clicked += OpenGameMenu;
_submitButton.clicked += OnSubmit;
does that include graphics?
is this something new the added in pre
swear it didn't use to work
no
also good man!
not enough people do this (self included)
entities are only used for modeling
yeah, I even learnt to write tests ๐
here's what MVVM Toolkit messaging is capable of
[UnityTest]
public IEnumerator UniTaskCollectionRequestMessageOkTest([ValueSource(nameof(MessengerTypes))] Type type) =>
UniTask.ToCoroutine(async () =>
{
var messenger = (IMessenger)Activator.CreateInstance(type)!;
object recipient1 = new();
object recipient2 = new();
object recipient3 = new();
object recipient4 = new();
async UniTask<int> GetNumberAsync()
{
await UniTask.Delay(100);
return 4;
}
void Receive1(object recipient, AsyncNumbersCollectionRequestMessage m) => m.Reply(1);
void Receive2(object recipient, AsyncNumbersCollectionRequestMessage m) =>
m.Reply(UniTask.FromResult(2));
void Receive3(object recipient, AsyncNumbersCollectionRequestMessage m) => m.Reply(GetNumberAsync());
void Receive4(object recipient, AsyncNumbersCollectionRequestMessage m) =>
m.Reply(_ => GetNumberAsync());
messenger.Register<AsyncNumbersCollectionRequestMessage>(recipient1, Receive1);
messenger.Register<AsyncNumbersCollectionRequestMessage>(recipient2, Receive2);
messenger.Register<AsyncNumbersCollectionRequestMessage>(recipient3, Receive3);
messenger.Register<AsyncNumbersCollectionRequestMessage>(recipient4, Receive4);
List<int> responses = new();
await foreach (var response in messenger.Send<AsyncNumbersCollectionRequestMessage>())
{
responses.Add(response);
}
CollectionAssert.AreEquivalent(responses, new[] { 1, 2, 4, 4 });
});
took me a while to realize this was a test
I just need a proper wrapper for bursted code
i haven't used UniTask in years
that's the only async supported in webgl ๐
oh yeah that makes sense
(i don't think i've ever played a webgl game let alone developed for it so I'm way out of my depth here)
@misty wedge https://github.com/tertle/com.bovinelabs.saving.free
here you go. I've released a full featured free version of my saving library with only migration stripped out.
I'll get a version on UPM tomorrow and asset store at some point~
I added some of the documentation I have written for it. Covers most of the basics but there's a lot of extra features missing.
Comes with some demos (imported via package manager), though these should not be followed for best practices.
[RelayCommand(CanExecute = nameof(CanDemolish))]
private void OnDemolish()
{
SelectType = SelectionType.Destroy;
}
[ObservableProperty] [NotifyCanExecuteChangedFor(nameof(DemolishCommand))]
private bool _canDemolish;
ngl, can't say I like it too much ๐
a bit annoying I can't store enabled state into command directly
all right
now NotifyValueChanged binding...
I guess those are the only value types I need to support + string
nah
I have to rely on reflection to get Properties
or set them
so
hardcoding generics is the only way I can use delegates
i fixed this earlier by starting
Is there an equivalent to UnityEngine.SceneManagement.SceneManager for baking?
I would like to get access to the current scene name inside a baker.
public override void Bake(SubsceneWorldValidationDataMono authoring)
{
var activeSceneName = SceneManager.GetActiveScene().name;
EWorld world;
if (activeSceneName.ToLower().Contains("physicssimulation"))
{
world = EWorld.PhysicsSimulation;
} else if (activeSceneName.ToLower().Contains("simulation"))
{
world = EWorld.Simulation;
}
else
{
world = EWorld.Default;
}
AddComponent(
new WorldValidationDC
{
World = world,
SubSceneName = new(activeSceneName, Allocator.Persistent)
}
);
}
Worlds exist without scene, so... potentially it won't be possible
Oh well, I'll have to find a different solution then ๐
Awesome! Will definitely check this out soon ๐
what are dots used for?
i looked at that and it didnt tell me mch
I'd say Dot's is used to build highly performant games utilising multithreading and other enhancements easier than has ever been possible with gameobjects
It's a completely different way to code since it is not OOP (Object orientated programing (monobehaviours/gameobjects)) but is instead data orientated
So theres a clear divide between data (Entities just hold data through components) and logic (Systems which go through the data and perform logic)
The way it is designed allows for easy dependency management (is built in for us) so that multithreading is easy
I do wish that would show which library it is working on
I'm not sure if it actually has but i swear the burst compiler has gotten slower
I usually just keep it off if thats possible for you if you don't mind having worse performance in the editor play mode
basically DOTS is a programming/development ecosystem within Unity that moves away from using slower 'managed' memory access and object orientated programming towards data-oriented design using fast native memory access.
that sounds too hard for me
if you are relatively new to Unity and C# then you'll be fine using gameobjects and monobehaviours
But it really does depend on the scale of your game
to be honest i've had this waiting on that final library ( i'm assuming it's my code/assembly ) since 0.51
The way to make it faster is to work out your script dependencies and make use of more asmdefs to split your code up
but that can be really hard to do which is unfortunate
easier if you are networking a game as there is a general separation you can do for scripts (Server, Client, Shared)
yeah i could look at doing that tbh, just curious if it's common with others to have that final lib take a while
it is for me
me too, as of now I just do my thing and ignore it - and sometimes when I enter play mode it takes more than usual, and I realize its because that last lib is still compiling
I suspect its the final player assembly - I agree that more visibility into what Burst is compiling would be awesome
my fps is dying
this isnt really for this channel, just use the profiler to find out whats causing it
physics
well post the profile in #โ๏ธโphysics and ask there for help to optimise it
The terms data-oriented design, object-oriented programming and object-oriented design should be properly defined
DOTS still has interacting objects with both fields and methods so it's still object-oriented really
I think the word oriented gives the hint that it isnt fully one or the other
you don't interact with objects though you interact with data components by using systems
I doubt theres a code base anywhere which is purely data or object programming
hi friends, has anyone encountered an issue where subscene isn't rendered when in game view, but is seen in the camera preview window (the small window in the scene when you click on the camera)?
could it be related to this? #archived-dots message
results in both scene and game views showing nothing
which is better in terms of consistency but not exactly what bothers me as you might imagine ๐
Haha yeah, sorry i'm not sure then beyond that ๐
Does anyone know if "IAspect" derived structs are allowed in the OnCreate of ISystem's? As soon as I start using aspects, for example:
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<PaddleScoreAspect>();
}
I receive ArgumentException: Unknown Type:DotsPong.PaddleScoreAspect All ComponentType must be known at compile time. For generic components, each concrete type must be registered with [RegisterGenericComponentType].
which I can't seem to fix
then it's not supported
keep in mind, aspects is just another codegen sugar
also, it's literally just pointer holder
Seems kinda unfortunate to create the aspect, use it in the update but then having to write it out again in the OnCreate but I kinda temporarily fixed it by adding an EntityQueryBuilder function to the aspect itself.
you can use
RequireMatchingQueriesForUpdate
this will use underlying query instead
also
you can try referencing codegenerated query field
but make sure to check final results
didn't know about that one, seems to work fine
thanks!
basic question but whats the best way to instantiate and set the positions of a bunch of prefabs in an ISystem?
public void OnUpdate(ref SystemState state)
{
PrefabPhysbuffer = SystemAPI.GetBuffer<PrefabPhysicsBodyBuffer>(SystemAPI.GetSingletonEntity<PrefabinatorTag>());
LookupAlive.Update(ref state);
ChildBufferLook.Update(ref state);
LocaltransLookup.Update(ref state);
var theShelfPhys = PrefabPhysbuffer;
new ShelfTriggerEventjob { shelfisAlive = LookupAlive }.Schedule();//state.GetComponentLookup<IsAliveDat>()}.Schedule();
state.CompleteDependency();
EntityCommandBuffer ecb = new EntityCommandBuffer(Allocator.TempJob);
foreach (var (isAlivevar, localtransf, enty) in SystemAPI.Query<RefRO<isDead>, RefRO<LocalTransform>>().WithAll<ShelfIsleStaticTag>().WithEntityAccess())
{
var currPos = localtransf.ValueRO.Position;
var thechildbufferlookup = ChildBufferLook;
var childboofer = thechildbufferlookup[enty];
for(int i = 0; i < childboofer.Length; i++)
{
ecb.DestroyEntity(childboofer[i].Value);
}
ecb.DestroyEntity(enty);
for(int j = 0; j < theShelfPhys.Length; j++ )
{
var current = ecb.Instantiate(theShelfPhys[j]);
var thenewpos = LocaltransLookup[current];
thenewpos.Position = localtransf.ValueRO.Position;
LocaltransLookup[current] = thenewpos;
}
}
state.CompleteDependency();
ecb.Playback(state.EntityManager);
ecb.Dispose();
}```
I've got that currently but the only part that doesn't work of course is setting the position because the ecb needs to be played back first
it seems like I should just avoid the foreach altogether, but then the Query is really useful
I feel like I should just go back to SystemBase for instantiating
just do ecb.SetComponent(current, new LocalTransform{ Position = thenewpos })
Use ISystem unless you need to access managed data, like UI, Input. ISystem can do everything else and is burstable
Just incase you didnt know you can also access the command buffer systems too, via their singleton
You can also send in the child buffer as a query, you shouldnt need the lookup if i'm reading your code right
and you could make it into an IJobEntity so you avoid the state.CompleteDependency();
new ShelfTriggerEventjob { shelfisAlive = LookupAlive }.Schedule(); use dependencies
true, this just the first pass, naive see if anything even works approach
cool cool
is there a good up to date tutorial somwhere on the 1.0 conversion workflow? I tried finding a decent tutorial on how its supposed to be done now, but the whole tutorial space for entities is so fractured that I have no clue what is current and what is not anymore.
that's the one I used
Anyone with knowledge of InputEvent and IInputComponentData? I don't really grasp what is going on behind the scenes when looking at their samples.
i'm no expert but I have a general understanding. do you have a question in particular?
From what I can see the NetCode sample & Rival sample:
Both reset the InputComponentData in their gather systems for non camera rotation, and then read input. Meaning the Set() will always be 0 or 1. I presume there is some hidden accumulation on client side for same ticks here?
They handle rotation of camera differently; Netcode just accumulates += the input rotation, while rival check if there if old prediction tick => set previous accumulated deltas. So either the InputComponentData is reset behind the scenes, or it is not?
if you just trying to understand what's going, i suggest ignoring rival and just following along with netcode samples and/or the new unity car demo. rival does some extra unusual stuff around this for its interpolation.
the whole input stuff is because the network tick rate (usually 60) won't match the actual client frame rate
if the client frame rate is > network tick rate (for example lets go with 120 fps)
then if you were watching a getkeydown event and you used a bool instead of the InputEvent you'd miss 50% of the 1 frame events
Yeah I know that. I found it now. The netcode sample is using actual rotation, while rival is doing deltas.
Meaning that the component never clears on its own, so they are just storing the rotation in it. While rival is clearing for deltas on new ticks.
is using Tag components for events good? if they are rare?
like ChunkChangedComponentTag {}
and add/remove at same frame
or better having a bool on component
bool ChunkChanged
or a hashmap of entities that changed chunk?
this is an age old question
you may as well add in IEnableable as an option
but when you say ChunkChanged - what are you looking for?
chunk is a 2d spatial hash grid
if grid is 32x32 it can add a tag ChunkChanged when the grid the entity is inside changed
like minecraft chunks
i was planning to use physics trigger for it but it does not have trigger enter/exit
So i need to implement trigger enter/exit with spatial hashing
another alternative is simply store 1 of your world chunks per entity chunk (via shared component)
and then simply use the built in ChangeFilter
to know when a chunk has changed
unfortunately, there's really no best way for this
there has been a lot of discussion around events in entities
i wrote a high performance event system 2-3 years ago that was very popular for a time and has been used in published games
though i personally no longer use it (still works)
i have an array of entities that are inside area of interest of each peer.
i need to add and remove from this array based on when entities move between chunks
Do you think it makes sense?
Why i need this array? to do delta compression
for networking?
if you're using netcode, it handles delta compression for you
๐คทโโ๏ธ
i've tested 100,000 ghosts
which is way more than i think they expect to exist
but i haven't tested more than 64 clients
yeah, but the scaling is based on client count
5000 clients with 5000 ghosts cost much more than 100k ghost with 64 clients
it does a good job at network scaling
i'd be more concerned about performance scaling (cpu)
Does not it needs to iterate all entities to compute relevancy all time?
this can`t scale
their focus really seems to be on keeping network usage low
yeah
i can easily handle 100k ghost relevancy on really any number of clients
With spatial hashing, right?
yeah
Do you have delta compression/
from unity?
but yeah i spent a lot of time optimizing this spatial hash map
not actually for networking
i use it for my orca simulation
Can you add spatial hashing on unity networking?
netcode relevancy system is just populate a hashmap with valid entities per network object
i do this via my spatial hashmap
there are definitely areas of netcode that would need a revisit for the scale i think you're trying to achieve
and i think they will do it eventually
but i don't think it's their focus atm
I want to achieve 1000 players per scene
with like only 30 per area of interest
so each player can see at most 30 players at same time
realistically, i think you'd probably just need to test and benchmark it yourself
to find out if it'll meet your needs
and if you're willing to risk waiting for development to fix areas you might identify as problematic
i`m not sure i want to risk
i have my networking library working
with native udp sockets
it can handle it already
determining network stack during pre-production probably up there with important decisions
can be a huge pain to change
i have created 3 multiplayers game with it
yeah if you have a working solution, i'm not sure I would be changing
and i don`t need/want some features of unity networking (like lag compensation)
and they add a lot of CPU
yeah a lot
For spatial hashing i`m using SzudzikPair to map a 2d position to 1d array index
then it is O(1)
it can handle negative numbers too with no waste of positions
{
var xx = x >= 0 ? x * 2 : x * -2 - 1;
var yy = y >= 0 ? y * 2 : y * -2 - 1;
return (xx >= yy) ? (xx * xx + xx + yy) : (yy * yy + xx);
}```
the size of 1d array is prealocatted based on map bounds
yeah i use a preallocated map bounds as well
an annoying restriction at times but it simplifies so much
i need to benchmark that vs what i'm doing
the mapping part is really not my slow part though
but any performance improvement is good
though this looks a bit conditionally to me (hopefully burst can avoid that)
It is good for locality of reference
of chunks
Can you create array of chunks and each chunk/cell has a nativearray of entities?
Or is it not possible?
a NativeArray<NativeArray<Entity>>
you wont be able to pass that into a job
the inner container will not be able to have safety injected
you can just use an unsafe container though
NativeArray<UnsafeList<Entity>>
ok current hashing vs SzudzikPair - 100k entities
pretty much exactly the same
but for my use case my current implementation is more convenient as I can just step walk between neighbours for(var i = current-2; i < current+2; i++)
Do your implementation handle negative position?
why you don`t use NativeMultiHashMap for this?
i do use nativemultihashmap
i have a huge range of extensions on it to make it magnitudes faster for this
i memcpy directly to the internal arrays and calculate hashes / buckets at end
instead of adding each element individually
yeah i offset by half world size
it's pretty basic
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int2 Quantized(float2 position, float step, int2 halfSize)
{
return new int2(math.floor((position + halfSize) / step));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Hash(int2 quantized, int width)
{
return quantized.x + (quantized.y * width);
}```
looks fun ๐
i'm so annoyed at him for stopping the video short
there was so much more ahead to hit!
thanks, it took me long enough, now I can destroy everything ๐ก
are you making them kinematic until collision happens?
those ahead aren't actually destroyable yet
I'm swapping the whole objects basically, when they are standing still they are just 3 meshs and then onTriggerevent I swap that to(instantiate) one where they are all separate entities with physicsbody's
Ah right yeah
not sure if that's the best way but seems good to not have a ton of physicbody's/separate meshs sitting there taking performance doing nothing
Yeah I mean I think with mass removed etc its pretty negligible from my experience, but whatever works for your setup.. I'd say swapping out would be lighter if it's an option for you.
i did something very similar for my wall destruction
it just seems all around more performant, less to render, less to simulate etc
cool, it wasn't sure if I was just unnecessarily optimizing
My simulation i have walls made of individual bricks, which i basically setup as kinematic but once hit they are enabled
yeah I just want to see how far I can push the performance
basically if i have all bricks as fully simulated the whole time, they don't act like bricks ( ie cemented together ) the entire thing will collapse if just some of the bricks are knocked out, so i've had to try and work around that
yeah I've thought about ways of doing that, it seems like the best way
I have a quick novice question.
Is baking simply just converting back and forth between DOTs and Unity?
well it converts the gameobject into entity data
Also is it accurate to think of the subscene used for Entites as just a separate environment? As in it's possible to look at data between them but they shouldn't directly interact?
not really I don't think, subscenes can interact just fine, they are just basically groupings of gameobjects to be converted
I see.
Sorry if I sound dumb af. Haven't touched Unity in a while and I've also never used subscenes.
no worries its all good, I ask plenty of dumb questions myself
In retrospect, if that's the case, then unity should've come up with a better name other than subscene... like EntityBakerGroup, ECSBundle, EntityIngredients?? ๐
EntityKitchen
Just keep going with the baker analogy
EntityOven
all good suggestions but sadly they settled on subscene
my guess is the technology was created alongside the original megacity demo
where it was used to break the scene up into subscenes
to allow streaming them in and out as required, as well as for streaming lods
yep, sounds about right
How do i change fixed time step of dots physics? RN it is always 60fps
chaging here does not works
state.World.GetExistingSystemManaged<FixedStepSimulationSystemGroup>().Timestep = 1 / 20f;
only need to set it once
(per world creation)
but no, there's no config atm unless you create one
it works
Thank you
You are wizard of dots
Everywhere i check for dots tutorial it is different.
SystemAPI.Query, RefRW, ref, in
everyone is doing it different
if your throwing events from systems for UI stuff, do you usually prefer to pass values into the event? or have the registered actions reach out to some static location?
No statics here for sake of multiplayer ๐
{
uint fixedTick = SystemAPI.GetSingleton<FixedTickSystem.Singleton>()
.Tick;
ServerUpdateConnectionsJob serverUpdateJob = new ServerUpdateConnectionsJob()
{
NetworkDriver = NetworkDriver
};
state.Dependency = serverUpdateJob.Schedule(state.Dependency);
ReceiveDataJob receiveJob = new ReceiveDataJob()
{
NetworkDriver = NetworkDriver.ToConcurrent(),
};
state.Dependency = receiveJob.ScheduleParallel(state.Dependency);
struct ServerUpdateConnectionsJob : IJob
{
public NetworkDriver NetworkDriver;
public void Execute()
{
NetworkConnection c;
while ((c = NetworkDriver.Accept()) != default(NetworkConnection))
{
// connections.Add(c);
Debug.Log("Accepted a connection");
}
}
}
[BurstCompile]
public partial struct ReceiveDataJob : IJobEntity
{
public NetworkDriver.Concurrent NetworkDriver;
public unsafe void Execute(in NetworkedPeer peer, in Entity entity)
{
DataStreamReader stream;
Assert.IsTrue(peer.Connection.IsCreated);
NetworkEvent.Type cmd;
while ((cmd = NetworkDriver.PopEventForConnection(peer.Connection, out stream)) != NetworkEvent.Type.Empty)
{
if (cmd == NetworkEvent.Type.Data)
{
uint number = stream.ReadUInt();
Debug.Log("Got " + number + " from the Client adding + 2 to it.");
number += 2;
}
else if (cmd == NetworkEvent.Type.Disconnect)
{
Debug.Log("Client disconnected from server");
}
}
}
}````
Is it wrong?
Why do i need to call state.Dependency.Complete(); after serverUpdateJob.Schedule()?
is not receive job depending on it and running after it?
i`m having this error
but the receive job depends on serverupdatejob and needs to run after it
i have a feeling
NetworkDriver = NetworkDriver.ToConcurrent(),
you just need to cache this before scheduling ServerUpdateConnectionsJob
i believe it's a false positive but I thought most of these had been fixed
uint fixedTick = SystemAPI.GetSingleton<FixedTickSystem.Singleton>()
.Tick;
var concurrentDriver = NetworkDriver.ToConcurrent();
ServerUpdateConnectionsJob serverUpdateJob = new ServerUpdateConnectionsJob()
{
NetworkDriver = NetworkDriver
};
state.Dependency = serverUpdateJob.Schedule(state.Dependency);
ReceiveDataJob receiveJob = new ReceiveDataJob()
{
NetworkDriver = concurrentDriver,
};
state.Dependency = receiveJob.ScheduleParallel(state.Dependency);
uint fixedTick = SystemAPI.GetSingleton<FixedTickSystem.Singleton>()
.Tick;
ServerUpdateConnectionsJob serverUpdateJob = new ServerUpdateConnectionsJob()
{
NetworkDriver = NetworkDriver
};
ReceiveDataJob receiveJob = new ReceiveDataJob()
{
NetworkDriver = NetworkDriver.ToConcurrent(),
};
state.Dependency = serverUpdateJob.Schedule(state.Dependency);
state.Dependency = receiveJob.ScheduleParallel(state.Dependency);
i believe both of these would work
Yes, it does works
Thank you tertle
I think I'm gonna make a forum post about the weird scene loading issues I have. Still have no idea why it's breaking...
i forget what the issue was
It not wanting to load a subscene if it contains an entity that references a game object
Error when processing 'AsyncLoadSceneJob(/StreamingAssets/EntityScenes/6086a43b86fc4d648a3ce1d94c0b822a.0.entities)': The given key 'PoolStaticSprite (UnityEngine.GameObject)' was not present in the dictionary.
I could work around it by storing an addressable string on it instead, and loading the game object that way, but it's very annoying IMO and seems like a bug
Was this in editor or just build
Just in the build
Ah yeah ok
Everything works fine in the editor
Feel like I and a few others had something similar but just referencing managed objects in builds having issue
Yeah that was @rustic rain , baked VisualTreeAssets would break the scene loading too
I don't know if they managed to fix the issue for them, but it also broke for me (but worked for you iirc for some reason)
It also works for Sprite references, which is really odd, considering those are also UnityEngine.Objects
I guess I'll ask on the forums ๐คทโโ๏ธ
Nah I managed to repo it
Ah really? What was the issue
What triggered it?
Just going to wait and see start next entities version does, and if its still an issue make a fuss
I didn't test but I think it was unity versions not entities versions
But that just seems like a bug then and not me doing something wrong at least
