#archived-dots
1 messages ยท Page 212 of 1
๐ค does not seem to give me the option to update
older unity version then
ah, okay.. I wonder if thats where this problem is coming from
okay, made some progress- that error has disappeared now ive updated unity and all packages,
getting a new error when i try and build through the windows build config asset however:
Build BuildConfig failed after 1.35s.
Editor's active Build Target needed to be switched to StandaloneWindows64 (BuildTargetGroup Standalone). Please wait for switch to complete and then build again.
^ ignore that. didnt see the last part there ๐
protected override void OnUpdate()
{
Entities.WithAll<MoveForward>().ForEach((ref Translation trans, ref Rotation rot, ref MoveForward moveForward) =>
{
trans.Value += moveForward.speed * Time.DeltaTime * math.forward(rot.Value);
});
}```
is there any way i can iterate over every second-third entity, alternating between all of them over 2-3 frames instead of all of them every frame? ๐ค
๐ thinking like a DOTS natural
but not really ๐
but if you use schedule parallel you get them all updating in different threads
breaking them up between different frames could be done with 2 different ways
use a tag component (different tags per different frame
or the new WithFilter lets you provide a native list of entities that the Foreach will use
also there a ton of issues with that code
im mostly just trying to figure out how to get the max amount of entities on screen, doing "something" at once
not sure if the tag solution would work well for what im trying to achieve by the end though
๐ค
You can use Time.ElapsedTime- include entityInQueryIndex in your foreach and discard indices based on the elapsed time
not sure what you mean there Sark, could you give me an example to work with?
var time = Time.ElapsedTime;
Entities.ForEach((int entityInQueryIndex, ref Translation translation, ..etc)=>
{
if(!((int)time % entityCount) == entityInQueryIndex) return;
// Do whatever
}
Something like that
That would run over your entities in order over time
what is entityInQueryIndex?
i always thought it was just a int thats always the same for a entity?
It's just in the index of the entity for the given query. So it will always go from 0-Total#OfEntitiesIntheQuery
yea ok so how does that work with your time if above
that would mean you only ever loop over every entity 1ce
Yeah I added a modulus to fix it
am I still applying WithAll here? because I now have an error:
Not really a sensible way to do it since you can't rely on the order of your entities, but it's a fast rough way to do what you want
yea you had a tone of errors in your code @sullen mason ๐
cant have a component in WIthAll and also in the Foreach parameters
Can you show the ForEach again?
previously, it was:
Entities.WithAll<MoveForward>().ForEach((ref Translation trans, ref Rotation rot, ref MoveForward moveForward) =>
{
trans.Value += moveForward.speed * Time.DeltaTime * math.forward(rot.Value);
});```
i just tried to shoehorn the int in there ๐
Entities.WithAll<MoveForward>().ForEach((int entityInQueryIndex, ref Translation trans, ref Rotation rot, ref MoveForward moveForward) => {
});```
And yeah what roy said, you don't use WithAll if your component is already in the query - it's implied that the component is required
@ocean tundra it was actually working (the first example) ๐ค
your also missing Run, Schedule or ScheduleParaell
Is this in a ComponentSystem?
yep
oh yea thats the old stuff
damnit ๐
use SystemBase instead
Read that page, it will explain how to write systems. It's all very detailed and up to date
sweet, thanks again ๐
partial class MovementSystem : SystemBase
{
private EntityQuery query;
protected override void OnUpdate()
{
var entityCount = query.CalculateEntityCount();
var time = Time.ElapsedTime;
Entities.ForEach((int entityInQueryIndex, ref Translation translation, ref MoveForward moveForward) =>
{
if(!((int)time % entityCount == entityInQueryIndex)) return;
}).ScheduleParallel();
}
}```
looking better? ๐ค
getting closer
you need
Entities.StoreEntityQuery(ref query) or something like that
ah rgr. explains my error
the example they have provided:
private EntityQuery query;
protected override void OnUpdate()
{
int dataCount = query.CalculateEntityCount();
NativeArray<float> dataSquared = new NativeArray<float>(dataCount, Allocator.Temp);
Entities.WithStoreEntityQueryInField(ref query).ForEach((int entityInQueryIndex, in Data data) =>
{
dataSquared[entityInQueryIndex] = data.Value * data.Value;
}).ScheduleParallel();
Job.WithCode(() =>
{
var v = dataSquared[dataSquared.Length - 1];
}).WithDisposeOnCompletion(dataSquared).Schedule();
}```
in Data data
what is this?
magic
should mine be in MoveForward moveForward?
its a further optmization
Eh, dots is super complicated, it takes a long time to grasp everything. Don't expect it to click immediately
jesus, just got "something to work", immediate performance increase with the whole schedule parallel
private EntityQuery query;
protected override void OnUpdate()
{
var entityCount = query.CalculateEntityCount();
var time = Time.ElapsedTime;
Entities.WithStoreEntityQueryInField(ref query).ForEach((int entityInQueryIndex, ref Translation translation, ref Rotation rotation, ref MoveForward moveForward) =>
{
//if(!((int)time % entityCount == entityInQueryIndex)) return;
translation.Value += moveForward.speed * math.forward(rotation.Value);
}).ScheduleParallel();
}```
okay, im now here
acceptable?
well MoveForward could be in instead of ref
rgr,
and your not using delta time ๐
the commented out statement caused nothing to happen
still should follow that rule
and using delta time caused an error
"get_time" cant be called inside ScheduleParalle,
only WithoutBurst or Run
yea
so that var time = Time.deltatime
then you use that time
cant use any globals or things inside the foreach
the sight of 100,000 cubes moving across the screen is oddly satisfying
haha yea
last time i tried this was a few years ago, dont think i could get 5000 ๐ค
if(!((int)time % entityCount == entityInQueryIndex)) return;```
so, this line really isnt working at the moment... though I have no idea what "time" is
you probably need a seprate elapsedtime
hi this isnt a DOTS question but i'm looking for an advanced developer and dont see a channel on this topic. What happens if i import some assets that use Addressables and use the asset in my scene but do not import the Addressables package? i'm able to build and run and it looks fine, and i dont see any errors even in the logs. Specifically i'm using the AR foundation Onboarding UX assets which use the Localization package.
is the addressables package included as a dependency somewhere?
in the original project but i exported the folders and imported them into my own project
the folders include one named AddressableAssetsData
Entities.WithStoreEntityQueryInField(ref query).ForEach((int entityInQueryIndex, ref Translation translation, ref Rotation rotation, in MoveForward moveForward) => {
translation.Value += moveForward.speed * dTime * math.forward(rotation.Value);
}).ScheduleParallel(); ```
will this only iterate entities with those components?
Yes. You should also make Rotation an in parameter in this case as you dont write to it
got it. i seem to gain no performance from splitting the statement into two separated by an extra component ๐ค
why would you split it?
yeah I wouldnt think that makes much of a difference
Did anything change about bool not being blittable? It seems like I can just use it in components without unity complaining?
you can use it, the question is just whether it makes sense. if you are using bool in a component, I would think twice whether this is the right design and there are no alternatives
depending on your use case, there are multiple options available
how can I get a random float inside a lambda expression? ๐ค
Sure wasnt thinking about a specific implementation here. I was just wondering how they managed to make bool work. Also I cannot find any mention of this change. Looking for blittable bool just yields outdated workaround solutions.
I guess boolean is still not blittable in c#, but it works as a field in ECS components due to some internal logic voodoo ๐ haven't paid much attention to it, but there are no mentions of it anywhere in changelogs
hm, according to at least their own version history, bool has been supported since version 0.1.0 in IComponentData ๐
how versions,ECS can in unity for LTS
Trying to use System.Guid with Burst and it is complaining a lot about managed vs unmanaged code. And yet, it hasn't complained (yet) about a struct I have that is just 2 guid variables. ??
is networking with DOTS any harder than normal?
Trying to free memory from NativeArray with NativeArray.Dispose and get
InvalidOperationException: The native container has been set to undisposable and cannot be deallocated. How do I free NativeArray memory?
Which allocator did you use ?
Allocator.Persistent, theres no documentation on allocators
https://docs.unity3d.com/ScriptReference/Unity.Collections.Allocator.html Doesn't describe any differences between them, how would I learn what they do?
use Temp or TempJob
Is there documentation on those?
I dont remember if they go in depth in the manual on this specific point
Basically Temp is for the frame
Temp doesnt work at all and throws errors
TempJob is around 4 frames so use it with jobs
TempJob gives me the same error as Persistent
persistent is self explanatory
Persistent isnt, how do you free it?
To me it seems like the API isn't even finished or documented yet they released it anyways.
usually you dispose a Persistent on systemBas.OnDestroy()
How though, NativeArray.Dispose gives errors like I mention above.
yes, because experimental tech
It's not experimental anymore though, they are shipping actual API's like https://docs.unity3d.com/ScriptReference/Rendering.AsyncGPUReadback.Request.html with NativeArray's now.
Yeah right some parts are becoming more stable, like Burst and Jobs.
Soo anyone know how to create a persistent NativeArray and Dispose it?
Mind sharing some code ?
could be you're tryig to dispose although job isnt finished
things like that
you can also only clear it if you need
In Awake
In OnDestroy
Used by AsyncGPUReadback each frame, which should be unused in OnDestroy?
And even then you cant stop AsyncGPUReadback requests all you can do is wait for it to finish, waiting in OnDestroy wont work because Unity wont be processing GPU calls.
Sorry I'm not knowledgeable with AsyncGPUReadback
I don't know of one but I definitely don't know close to everything. someone else might know
I think there's a Stop component or similar
So let me get this straight, the only way to use NativeArray without errors is to create a new one every frame with Allocator.Temp? Like there's no way to allocate a NativeArray once and re use it for multiple frames? It's so bad for garbage collection...
perfectly fine to allocate persistent and destroy it e.g. ondestroy - haven't read much of the above though sorry but there's nothing wrong with using one single persistent instance
just got to be careful dealing with statics
@amber flicker Then why do I get errors?
try instead: if(narray.IsCreated) narray.Dispose();
Related to DOTS - I was doing some reading in preparation for trying out the Job system for the first time recently. I saw that only NativeArray is available by default, but ECS adds other containers like Native queues and dynamic lists. Is it possible to use those advanced container types from ECS without fully embracing ECS?
It is created I check in my rendering code before reading the array
yes - they're in the collections namespace
I still need to install ECS package though right?
There's nothing wrong with the code you showed - I guess there's more code you're not showing or else that bool changes within the lifetime of the app
Don't think so - just Unity.Collections
Like I said its possible the async read request is not finished in OnDestroy, but Unity doesnt give you a way to wait for it in OnDestroy because no rendering code is updated/run during that.
So I get why Disposing of the in use NativeArray would cause errors, but annoyed that Unity doesn't provide anyway to handle this.
Could you cover this by in the async callback doing if(!narray.IsCreated) return ?
Theres no async callback, it simply checks if the request is done every frame.
I can confirm though, it actually doesnt throw errors about 1/10 times when the async request is done.
I don't understand... you're not creating an array every frame right?
No like I said above its allocated once in Awake with Allocator.Persistent
If you put something on hastebin or similar I'll take a look but I'm missing some understanding of the issue
Hmm they say GetData isnt possible but I can access the NativeArray by array indexing just fine
That also doesnt mention the Dispose error I'm running into
Here's some of my code
if (asyncReadbackSupport)
{
asyncRequest = AsyncGPUReadback.RequestIntoNativeArray<float>(ref narray, renderTexture);
}
//AsyncGPUReadback.RequestIntoNativeArray
}
if (asyncReadbackSupport)
{
if (asyncRequest.done)
{
if (asyncRequest.hasError) Debug.Log("error");
else Debug.Log("test " + narray[0]);
readFrameDelay = 0;
// Debug.Log("done");
}
}```
It's not the same question ?
I'm not sure it depends if GetData is the same as directly accessing the native array like I do at
outputs in console with different float values, so it seems like if GetData doesnt work then direct access does?
But why would they be different?
Like I said before it seems like this API is unfinished, Unity devs themselves aren't sure what is and what isn't
wait are you overwriting your asyncrequest with the same narray?
renderFrame isnt true until the last asyncRequest.done = true
So it overwrites the request but only after its done
Aren't you supposed to read with asyncRequest.GetData() when .done ?
ANyway that might not be the problem
But I would fetch as it's expected
nativearray isn't affected by garbage collector btw
If its really a NativeArray you shouldnt need GetData, it should just be there in native memory...
i dunno about that api specifically, but isn't unity itself responsible for disposing the array returned by getdata?
NativeArray = custom allocated memory, it does not get garbage collected like .net managed memory does
that's why you need to manually dispose
@trail portal looks like a recent bug https://forum.unity.com/threads/asyncgpureadback-requestintonativearray-causes-invalidoperationexception-on-nativearray.1011955/
I think it disposes on error, but you should be responsible otherwise ? don't know really ๐คทโโ๏ธ
ah yea looks like you are responsible for RequestIntoNativeArray according to that link
Well RIP guess its not possible then
Yes I repeat my statement, this API is not ready.
Also seems to just randomly crash my editor when using AsyncGPUReadback, but thats unrelated to NativeArray's.
And looks like also there's a completion callback.
How do we handle "dependencies" between entities ? I have a mob which looks like this : Entity{ Mob, ..., Localisation{ name:"Wolve", ... } and a popup entity which looks like this : Entity{ Popup, Localisation{ popupTitle:"Select action on $", ... }... The problem is the following, as you can see, theres a placeholder in the popup title, the $ which is quite important. Because i wanna change its title quite easily ( reusing that popup for different entities ). And thats the problem, the spawned popup should use the "localisations" from the entity it was spawned from. How do (could we do) that ? :/
@stone osprey you want compoA form entityA get access to compoB from entityB ?
Can I have a Singleton that is defined by two components? (I have a value component and would like to have a tag that makes this entity the one whose value is relevant; but I'm struggling at reading a single value from
GetSingletonEntity<Tag>)
EntityManager.GetComponentData<FloatingPosition>(GetSingletonEntity<TagFloatingOrigin>());
I'd really like to not go through the EM here.
a singleton is a singleton...it's a pattern to get one object instance (and only one) for a class...i dont understand what u want
@night venture Not really... i want that entity A uses data of Entity B in general... Like theres a entity acting as a "Name provider" and one that is the "Name receiver"... in this case the mob is the first one and the popup the second one
If it's a struct component you can just do GetSingleton<Tag>()
do you have a system to make the "relation" between them?...i mean, when and how the popup is shown?
Oh I see what you mean
The tag is an empty struct. ๐
@night venture Theres a "SpawnPopUpOnClickSystem" i wrote ^^
Alternative is to make a system that at some point copies the value into a singleton component. This is what I currently have, and it's nontrivial because of some timing issues, and also requires a standalone entity to hold this component (or duplicating a double3 data on an already pretty large entity)
I guess you could write an extension method that does that
then, iiuc, it would be simple to entityA.getComponent<A>().gime_me_a_string and call entityB.getComponent<B>.setstring(). isnt it?
Entity has a GetComponent extension now? How? ๐ฎ
No, the extension method would be for SystemBase
Just to easily wrap that behavior in a simpler call
But well... i should ask my questions in a different way : I want an entity ( Mob), which spawns on click a Popup. That popup should show the name of the entity which "created" the popup. How would you do that ? ^^
And it should be pretty flexible*
What is this sorcery? ๐
Is the issue here that the call is ugly or do you have performance concerns or something?
Yeah not the prettiest line of code up there.
I don't know, am I not introducing yet another sync point by speaking to the EntityManager?
manager.GetComponentData<type>(entity)
sorry, wrong destination
Both.
It's not like a "structural change" sync point where it's forcing all jobs to complete - since you're only reading components it would only force jobs to complete which are writing to those components. But thinking the call is ugly and trying to avoid reading on the main thread are two different problems, which are you worried about?
Call isn't THAT ugly.
@warm panther i could try helping you if you explain me what Can I have a Singleton that is defined by two components? is
Only one entity exists that has both component A and B; as opposed to only one entity that exists with component A.
Since this is composition over inheritance, singletons can -semantically- be defined by presence of multiple components, if you so wish.
If an Entity loses component B or component A, the singleton is gone and systems that require it won't run anymore.
Wat.
A singleton is anything of which there is only one instance.
I guess my deeper issue here is, what does GetSingleton<ICD> do under the hood that makes it acceptable over all the other ways like GetComponentDataFromEntity<...> with a query; especially when there really is only one entity.
let me explain first, ok?
you said "Only one entity exists that has both component A and B"
then, the singleton is the entity, not the component
@night venture That is possible... but it is actually pretty inflexible ๐ฎ There must be a smarter way to create a popup which uses the data of a mob
why inflexible?
But Unity's implementation after some digging expressly disallows this type of composed Singleton.
Wait you mean the code you posted where you get the tag entity then get the component via that entity isn't working?
So that answers my question, which is sad, but I guess this won't be a performance issue where I need to use it.
@warm panther please, focus. you want an entity with compA (lets call it heart) and compB (call it brain). if one of those is deleted, entity should die, right?
think in popup.showmessage(mob.getname()) would this work for you?
No that works fine, but the Tag COULD be on an entity that has no FloatingPosition ICD, and that would mean I'd have to... I don't know. ๐ Because there is TryGetSingleton but not TryGetComponentData.
No. We still have a heart or a brain, but no "functioning human" singleton.
There is HasComponent
And if I give it a new heart, you know, this is a surgery, we have the singleton again ๐
(getting an omega man vibe here)
Moar ugg ๐
you always hade the human, but sometimes is not functioning...still, dont know whats ur problem
I'll just ensure the tag is never somewhere it makes no sense.
Yeah you dont get it at all, sorry.
for example, i could foreach.has_brain.dont_have_heart
Entities.WithAll<brain>.WithNone<heart>.Foreach <-non-working humans
I don't know, I've met some pretty heartless people who claimed to have brains
Concrete examples:
- I have space ships, these have a position
- I have a tag, this is the focused ship and camera centric origin for the renderer (used by my own TRSToLocalToWorldSystem)
- now, that tag only makes sense when it exists on an entity that has a position, and that tag also only ever exists once.
- if I focus another ship, the tag gets removed from one and added to the other.
- the system that does the camera centric rendering then calculates the data from the new "origin" singleton, which is that other ship.
you are making a "current selected ship" tag?
Yeah and a singleton entity is defined as there is exactly 1 entity in that Query's entity count. That's what Getsingleton assumes and probably optimizes for; but it cannot work on a query that has 2 required components, AND still return a component you care about.
I don't really see a "problem" in that example
It's more complex than that, but yeah, for all intents and purposes, I am doing that. But I don't care at all about the selection tag, I care about the data that is associated with this. But I don't want to copy the data into the selection tag - it's a double3 and there will be more; and this is actually one of the biggest entity types in my game already.
take a deep breath, please
Great. So only ugly code, no problems. That's what I wanted to know; given I found out I can't use sugar like GetSingleton<T,U> or something.
sorry, whats the actual issue with the concrete example?
Ugly code.
I need to ask the EntityManager for the ICD after asking the System's GetSingletonEntity to get me the Entity.
If I want to ensure the data that selection actually cares about exists on the tagged entity, I am out of luck (I have to ask the EM again - hasComponent?)
so your question problem is "I have a "current selected ship" cpomponent, i apply on unique selected ship..."
Can't you just do a ForEach that includes your tag
By your own description it would only match one entity
i think he's looking for "a better/more efficient way"
you could use the chunk.HasComponent to process that particular tag?
Probably not. The chunks I am processing are all entities with a floatingposition, I need to extract the one I care about first.
In the end it's 3 lines of code but this derailed into a discussion whether a Singleton is still a singleton if it has more than one component.
๐
so the problem is you dont like/looking for something better than entities.withall<selection_tag>.foreach ?
whats the issue making a query that specifically includes the tag? i guess id need to see more code to understand why your trying to avoid entitymanager ๐คท
var position = EntityManager.GetComponentData<FloatingPosition>(GetSingletonEntity<TagFloatingOrigin>()).position;
var floating_to_local_to_world_job = new FloatingToLocalToWorld()
{
origin = position,
RotationTypeHandle = rotation_type, CompositeRotationTypeHandle = composite_rotation_type, TranslationTypeHandle = translation_type, ScaleTypeHandle = scale_type,
NonUniformScaleTypeHandle = non_uniform_scale_type, CompositeScaleTypeHandle = composite_scale_type, LocalToWorldTypeHandle = local_to_world_type, LastSystemVersion = LastSystemVersion
};
I look for something better than the 1st line, ideally with the semantics of a singleton:
-> having the tag on an non-floating entity means there is no origin.
(or being disallowed to place the tag, but that's probably against ECS principles)
talking about the first line only, that's probably the best way to do it, although i wouldn't use a singleton
That seems like the right way to do it to me. If you wanted to avoid syncing your data on the main thread you can replace the GetSingleton stuff with a Job.WithCode where you pass in a NativeReference to retrieve your origin data that you then pass into the next job(s)
you could use cdfe inside the job itself, but at the end of the day I think you're already doing the preferred way
But the system also:
RequireSingletonForUpdate<TagFloatingOrigin>();
And I will say although it might seem ugly it is very easy to understand what you're doing with that code which is worth something
I agree.
then, nothing more to say...3 people gave u the same feedback xD
did you want to avoid tying the system to requiring the singleton? could just make an if hassingleton statement
And it will guaranteed crash if there's a bad Singleton entity configuration, which is good.
a bad singleton configuration is bad xD
I wanted to avoid interfacing with EntityManager, assuming it would create one of those dreaded Sync points.
My previous solution copies the data, but that's actually worse and that's how I got here ๐
two things, could move the system into a specific systemgroup that has other sync points, use cdfe inside the job, or just shrug and not worry ๐
@stone osprey I wouldnt do UI nor Localization with dots. At least not this year ๐
So it begins... ๐
By removing 1 system and 2 writes, and several lines of code (net), I now resolved my annoying race conditions that caused the origin to jitter because it could be updated at the wrong time.
Not counting this lengthy discussion here, this was most economical. ๐ Thanks all, though, it was important to explore the intricacies ๐ฆ
@karmic basin Oh i dont use dots for UI ๐ Only for the UI's DATA. Not for rendering it etc.
Wow ShareX melts when capturing from that screen. This runs at 120 fps, never mind the video.
@night venture The problem i see in this solution is... that its hard coded and runs every frame...
Its just not flexible
not really...you can trigger that operation on the body of the event
inside SpawnPopUpOnClickSystem
couldnt u?
Hmmmmmm.
The RequireSingletonForUpdate somehow makes the system show up as only working on the origin entity. I'll use a TryGetSingleton instead but that's unexpected.
Really interesting insight... this may be editor only, because the rest does move.
Ah duh.
There's an archetype selection field at the top
So works as expected. ๐ Progress!
Also, 69 matching entities, nice.
glad to hear.
@night venture Well i think im just gonna do it like you said... cant find a nicer way. Probably this is also "clean" :
Entity{ Mob, Localisations{ name:"Wolve" }, OnClickPopUp{ popUpType : "type", localisations : ...}}
OnClickPopUpSystem then "copies" the localisations component into the "OnClickPopUp" component which gets processed by another system to make the popup spawn. The popup gets a copy of that
Besides that im struggling with another issue.
fair enough ๐
I have the popup and the mob. A click on the mob opened the popup. When i click the popup, i wanna make my player run to the mob. Sounds simple... probably i made it a bit too complex. But for the future i probably dont just wanna run to the mob that spawned the popup. So i thought about splitting it up like this...
public struct OnClickMove{
public enum Who{ CLICKER, CLICKED, BOTH }
public Vector2 position;
public Who whoShouldMove;
}
public struct OnClickMoveToEntityThatWasClicked{}
Entity{ PopUp, OnClickMove, OnClickMoveToEntityThatWasClicekd }
Entities.ForEach((Clicked, OnClickMoveTo, OnClickMoveToEntityThatWasClicked, PopUp) => {
// Determine the entity that was clicked, copy its position into the OnClickMove
});
Entities.ForEach((Clicked, OnClickMoveTo) => {
// Make entity move to position
});
Is this too atomic ?
So i kinda thought about a "OnClickMove" struct... which contains a pos... and when its combined with "OnClickMoveToEntity" we copy the entity position inside it to make the entity move to that position.
This could be extended in the future... so for example if we wanna move to a random location upon click we could simply have something like this Entity{ OnClickMove, OnClickMoveRandom} and a system which generates a random position and copies it into the OnClickMove
Is this too complicated ?
@stone osprey believe it or not. this could be handled on a similar way as what @warm panther was doing
add a tag (empty component) to the mob you are clicking [ie: focusing]. trigger a system to move player to entity_position_which_has_focus_component
Isnt that what im doing in my example above ? My tag component is "Clicked" and the only difference here is that i have a "OnClickMoveTo" and a "OnClickMoveToEntityThatWasClicked"
I actually just wanna know if its too atomatic to have a "OnClickMove" that stores a vec2 and a "OnClickMoveTo..." which defines where we wanna move and copies that location inside "OnClickMoveTo" ๐
So kinda like a consumer/producer
I'm not storing the position, but moving to (focused) entity position.
Ah i see ^^ but in general im just confused about one aspect
There so many damn ways.
xDDDD
let me give you my personal advice after years of coding
do it any way...it doesn't matter if good, perfect, chunky...
you'll always have time to improve it
otherwise, at the end of the day, you wont have anything
talking about crappy things: Another newbie question!
my tile can have either a road or sidewalk component.
if it's a road, material.color (not an sprite yet) would be black.
else, if its a sidewalk, would be grey.
ie: component implies color + component change material color
whats the correct way to do this?
What i actually mean is... We could either have one huge component OnClickMoveTo{ exact definition of where in which case }
Or we could split it up... like OnClickMoveTo{ pos } and OnClickMoveToPositionProvider{ ... }
So how do we decide what a component should contain ? When do we split them ? When do we merge them ?
do it any way. once is working, if you want, analyze and try to make it simpler.
knuth rules!
The disadvantage with huge components is... that they are mostly to inflexible. What if we wanna move to a random location ? Well we need to edit the component and add new functions to it or whatever.
We could also have only specialised components like OnClickMoveToClickedEntity and without having a OnClickMoveTo
But i have no idea where it makes sense to have which one
in my esperience, linux binary approach is the best
do one thing. tiny, simple, even dumb...but do it fine
Do you guys have any idea how can I remove some things (children objects or classes from MB)
before conversion happens?
im using
public class PlanetAuthoring : MonoBehaviour, IConvertGameObjectToEntity
a job that moves from A to B is much better
no idea, sorry. i do not work with conversion yet
Whats a linux binary approach ? xD
do one thing. tiny, simple, even dumb...but do it fine
So just splitting every component till its atomic ?
to sum up...
Thats tiny, simple and will do it fine
+1 for We could also have only specialised components like OnClickMoveToClickedEntity and without having a OnClickMoveTo
@stone osprey look, here i got an example....
quoting myself:
talking about crappy things: Another newbie question!
my tile can have either a road or sidewalk component.
if it's a road, material.color (not an sprite yet) would be black.
else, if its a sidewalk, would be grey.
ie: component implies color + component change material color
whats the correct way to do this?
my brain just come out with a "probably bad" idea: a job which, depending on each component, set material.color.
it would be a pita...like if(road) color=black, if(sidewalk)color=grey
and that's propbably not even ECS correct
but, once done, i can improve it as much as i want
so...i'll give it a couple more minutes to someone come and tell me the CORRECT way, or ill do that monkey-code and keep moving forward
Hmmm... im always looking for a beautifull and flexible way. But i somehow get the feeling that theres never one. I just wonder how "big" game developers do this. Because when i watch at their code, it always feels "perfect". Minecraft bedrock is a great example. They are using an ECS and theres a wiki where they exposed their components and their data... and it makes perfectly sense how they did it.
are you getting paid for your game coding skills?
No xD
once you do it, you'll have learned enough to do as they ๐
Thats true ^^ but they still need some criteria's i guess. To split components up or to determine what components they need for what tasks. Furthermore im a ... how you call it in english... a "perfectionist". I hate it when something ugly or inflexible.
thats why, since a few minutes ago, i'm telling you what im telling you: do it. doesn't matter if its good or bad.
having SOMETHING is probably ahead than 90% of people
it took me years to learn that
and you can always come back to it
that's why ECS is awesome
systems are decoupled
or should be
and now...TileColorSystem xD
think of writing drivers for an embedded system. you want to be able to rewrite them but some times it is about getting the job done
and like, optimization code can get insanely UGLY but it does a way better job than what your beautiful code might do
Well thats understandable :/ I also get the feeling that sometimes scripting makes more sense. For example in my "OnClick" example above, it would be way easier to just execute a callback that determines that happens upon clicking that entity... like OnClick{ Action<Entity,Entity> onClick } and then we could hook a method, lambda or interface in it to execute the logic. Because such "do something upon click" logic is pretty hard to convert into data
Positions, Transforms, Players, Mobs, Stats even Buffs are all data... but probably its just not so clean to convert "OnClick" logic into data.
Yes of course... but the data changes are often hard to express as components. Like you have a wanna make a entity teleport away upon click... its probably easier to express them as callbacks instead. But thats not ECS like
click->trigger job(system) to move object
do you remember my question about how to set color on tiles...?
ugly as fuck, but already working and i can move forward:
public class TileColorSystem : SystemBase {
public void colorize() {
Entities.WithAll<RoadComponent>().ForEach((ref RenderMesh mesh) => {
mesh.material.color = Color.black;
}).Run();
Entities.WithAll<SidewalkComponent>().ForEach((ref RenderMesh mesh) => {
mesh.material.color = Color.grey;
}).Run();
}
protected override void OnUpdate() {}
}
perhaps tomorrow, i'll try improvements
Hmmm... ok, probably i still need to learn that its about to get things done. Not about over engineering the code till you can sell it as a NFT
from the bottom of my heart...one on the most valuable lessons u can get
Entities.WithAll<RoadComponent>().ForEach((ref RenderMesh mesh) => {
mesh.material.color = Color.black;
}).Run();
complains with:
Entities.ForEach uses ISharedComponentType RenderMesh. This is only supported when using .WithoutBurst() and .Run()
Googling a bit, but if anyone know how to solve it, I'll appreciate the paste ๐ @turbid sundial
well...that should work (although it doesnt), but i was wondering if https://github.com/Unity-Technologies/MeshApiExamples described a new way, like using manager.getentities<T>().getsharedComponentlist<>
you need without burst before run
Entities.WithAll<RoadComponent>().ForEach((in RenderMesh mesh) => {
mesh.material.color = new Color(1f,0f,0f);
}).WithoutBurst().Run();
its not working for other issuesxD
your mesh is marked as in
Is Unity Tiny compatible with the main DOTS and its desktop platforms?
I see it's mostly focused on web and mobile and contains some tasty packages like UI and Text which don't exist in Entities package
and im pretty sure rendermesh is a class not a struct
how to set local position in dots?
so no in or ref
btw...do you guys do manager = World.DefaultGameObjectInjectionWorld.EntityManager; on each class? do u setup a singleton? am i missing something?
it complained i cant use ref, but in...i followed instructions xD
@night venture in Systembase EntityManager exsists as a property
in = readonly
ref = read write
for STRUCTS
do you have a whole parent transform setup?
i used ref, but it was complaining...before reinventing the wheel, let me repeat the question:
talking about crappy things: Another newbie question!
my tile can have either a road or sidewalk component.
if it's a road, material.color (not an sprite yet) would be black.
else, if its a sidewalk, would be grey.
ie: component implies color + component change material color
whats the correct way to do this?
think so...but let me sanitize all that manager = World.DefaultGameObjectInjectionWorld.EntityManager; first
@night venture if you are you can use https://docs.unity3d.com/Packages/com.unity.rendering.hybrid@0.11/manual/material-overrides-code.html
else what your doing should work once you fix the parameter
what this page even explains? https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/transform_system.html
@gusty comet btw your not on latest docs
you would think its some dots' version of transform
yea it is a dots transform system ๐
why are they showing these diagrams with different orders? what does it mean
everything that made up the old transform system isnt 100% needed in dots
you can have transforms with only positions (translation)
no scale or rotation if you wanted
i need localposition tho(set)
plus they are explaining how to extend/replace parts of it if you need
yea so translation will be local to parent
@gusty comet yea in your child you should just be able to set translation and that is 'local' space
how/where are you setting it?
yea a bit more then that:P
code?
and your 100% sure your not setting parent translation as well?
ok...going back to the previous message where i refered my previous message and so on:
my tile can have either a road or sidewalk component.
if it's a road, material.color (not an sprite yet) would be black.
else, if its a sidewalk, would be grey.
ie: component implies color + component change material color
whats the correct way to do this?
Im actually invoking a class method which contains:
Entities.WithAll<RoadComponent>().ForEach((RenderMesh mesh) => {
mesh.material.color = new Color(1f,0f,0f);
}).WithoutBurst().Run();
ohh
maybe it worked all along roycon
i jsut didnt realize cus my orbit lines dissapeared kek
but it indeed follows them
@night venture if its not setup for v2 i thought that would have worked, but ive just reread the sharedcomponent doc and not sure you can edit those in a ForEach
since is a memcoppy under the hood
wat
im using hybrid package on a new project i created yesterday...and at this point I'm too afraid to ask... ๐
ok so use matieral overrides
you should just be able to add MaterialColor and it will be happy
to double check if i understood:
[MaterialProperty("_Color", MaterialPropertyFormat.Float4)]
public struct MyOwnColor : IComponentData{}
and selecting MyOwnColor instead of renderMesh in foreach?
Yea that should work
But they're should be a built in one you can use too
No need to create a custom component
SpecularColor?
Materialcolor
BaseColor..i dont see MaterialColor
anyway, withouburst+run and no ref should work and im getting another error, so im going to fix that first
No I don't think we can editor shared components in foreach
I thought we could
But not sure now
I honestly don't use them much
I've only built 1 to split up my rts entities by player
ok....without the material color change(the code above), every tile is created and visible (i setup a default blue)
but, once the code is present, it shouts:
InvalidOperationException: object is not initialized or has already been destroyed
my concern is...how i know, in a parallel world, if objects are created?
i think you may need more code....
for (int i = 0; i < list.GetLength(0); i++) {
for (int j = 0; j < list.GetLength(1); j++) {
tiles[i, j] = EntityManager.CreateEntity(archetype);
//FIXME here cause its like adding default color :P
Material material = new Material(Shader.Find("Standard"));
material.color = Color.blue;
EntityManager.AddSharedComponentData(tiles[i, j], new RenderMesh {
mesh = mesh,
material = material
});
EntityManager.AddComponentData(tiles[i, j], new Translation {
Value = new float3(i, 0f, j)
});
foreach (ISerializableComponent c in list[i, j]) {
c.addComponent(EntityManager, tiles[i, j]);
}
Debug.Log("here OK...");
new TileColorSystem().colorize();
}
}
well you cant new up a system like that
you can create entities like that
tho i would use a prefab rather then archetype, they both do the same thing
isn't better to use buffer...whatever or another system instead of a loop?
meh its fine
this is loading code
you should have some sort of loading screen anyway
yes you can get more performance out of the batch entity manager APIs or using a Entity Command Buffer
but both add complexity for code that probably dosnt need it
if this was every frame then yes, use those
ok...we'll take on that tomorrow
what about the colorize system?
it is a "good" approach?
(beside is wrong)
you can just remove that line
and let the default system creation handle it
it wont run if theres no entities matching its query
but there are...roads are still present
i mean...please, have in mind the objective and the approach
??
my tile can have either a road or sidewalk component.
if it's a road, material.color (not an sprite yet) would be black.
else, if its a sidewalk, would be grey.
yea
im using a system to change color. is that ok?
the system will still exist and run
just as a normal system, not part of this loading code
but let the system do that....oncreate?
??
public class TileColorSystem : SystemBase {
public void colorize() {
Entities.WithAll<RoadComponent>().ForEach((RenderMesh mesh) => {
mesh.material.color = new Color(1f,0f,0f);
}).WithoutBurst().Run();
Entities.WithAll<SidewalkComponent>().ForEach((RenderMesh mesh) => {
mesh.material.color = new Color(0f, 1f, 0f);
}).WithoutBurst().Run();
}
protected override void OnUpdate() {}
}
for systems that do stuff ONCE to a entity a good idea is to use WithAll/WithNone
and a entity command buffer so it only runs once
yea so that will work fine, but it will be setting mesh color every frame
even after its already set it
oh also its not in onupdate
no...that's why is not made every frame, but once
i want to change the color/sprite/whatever once
i wish unitys docs supported contributions
so, it's my understanding to invoke a function who does it
What happens to monobehaviours when authoring/converting?
so you should use the tag / with none pattern
if added component DOTS, destroyed
grab a entity command buffer
in your foreach do your material set
then add a tag component, this tag component should be in your Foreach query .WithNone
Oh
But hes still in memory
kind of "mark as colored" ?
I mean your scene size is bigger with all these monos and their public vars
actually depends on how your converting
ConvertToEntity has a option to keep the GO alive
Subscenes (recommended) will destory, UNLESS you are adding a hybrid component somewhere, in which case will cretate a nice hidden GO
yea exactly
oh a easyier option (but maybe not better) is to grab the existing system and then call collerise
World.GetExistingSystem<SYSTEMNAME>().collorise
that sound ugly...apart from that, it would create a scalability issue if i want my systems to setup several things...one "colored", another "decorated", another "...".....
there might be a better option
@night venture its actally a very common pattern in DOTS
I still havent figured out how to remove child before conversion happens
how are you converting?
Authoring
i mean subscenes or converttoentity
Latter
theres a stop convert or something like that
Oh
the same but reversed makes much more sense: create the entity with "to_be_colorized" component, and let the system do his job, removing the tag as the last step. dont u agree?
yup both work
tags dont really take up space
so dont really need to worry too much
is there a way to crate tags "dinamically" without the incredible burden of creating a file, naming it, opening in the editor... ?
nope
dots hates that
all code must exist at compile time
it dosnt even like generics
Can you deactivate entity
yea
theres a Disable? Disabled? Component you can add
BUT from memory it didnt disable children
that may have changed
I need to either destroy entities or deactivate mesh
as far as you know...is there a way to have a system "sleep" until you wake it up or to run a job doing something like....
new SystemBase({}).Run()
im still trying to bypass that "pending_color" tag at all costs xD
RequireForUpdate maybe
There's a require singleton too
That's probably what you want
Do you loading, then at the end create your singleton 'trigger' entity
Your system will 'sleep' waiting for that, it runs, then at the end deletes the singleton
sounds good...you said RequireForUpdate ?
Require singleton
Or something like that
Definitely has singleton in its name :p
And you do that in oncreate
i see...so you are creating the system/object at some moment
and it starts running then...as a trigger
?? You never create the system, unity does that
Your just telling unity that this system has extra update rules. OnUpdate will only be called if ecs meets them
By default all systems have a rule requiring at least one entity to match any Entityquery
ok. ill have a look at this tomorrow after work
Um
thanks as usual, ill let you know my next issues ๐
Psychologist mode
Is it possible to store list of entities in MB and create/destroy them as appropriate? Also from mb
I despawn models when far
you dont really need to worry about that in dots
but if you do want it you should look at megacity/subscenes
using subscenes you can quickly remove/add chunks of a world
it depends on how big/complex your world is
well even if the world is moveing
you still must have some sort of global pos
then you just need to break that up into a chunk pos
and link subscene to chunk pos
the hard part is you might need to hook into the subscene load process somewhere to update the 'actual' pos of all the subscene entities
should be possable tho
Im back with more questions...
I need to calculate damage and resistence.For example theres physical damage, magic damage and resistence in my game.
How would you calculate the damage when one entity attacks the other one ? Do we need a formula or are there other ways ?
well definitly some sort of formular
but also what sort of code pattern do you want to use ๐
simplist to understand is the event entities pattern, gameplay triggers damage somehow, spawns a 'damage' entity, this entity has the initial damage (pre resistance calc) and the target entity
you could also have a 'take damage' component you add to the entity, but this limits you to 1 damage source per frame
or a 'take damage' buffer, which is the same as the component but without the limit of 1 per frame
or you can get more complicated and use things like the event system ๐ on the fourms
personally i like the buffer or the event entity aproch
next how 'dynamic' do you want your damage types to be
easiest to code/understand is FIXED, so you create a magic resistance component, a magic damage component ect and then systems to operate on them
adding a new damage type is a bit of work in that case
For simple stuff the buffer approach is fine, for everything more complicated having entities to indicate damage events is superior in my experience
finally create systems to 'process' the damage, breaking it into some sort of pipeline
Initial Damage === Resistance SYstem ==> post resistance damage === armor system ==> post armor damage == actual damage system ==> health
and dont forget to clean up the data as you go
@north bay my issue with event entities is it can make the dots enities inspector useless
i had a case where i was creating/deleting every frame
so the inspector goes crazy adding/removing and reordering all the entities
Ehh that's fixable if you limit the lifetime of your events to a systemgroup BeginSimulation-EndSimulation, etc
But the raw EntityDebugger entities view becomes useless with +500 entities anyways without using queries
yea true
Wow thats a lot... So wait ^^ So i actually have "PhysicalDamage", "PhysicalResistence" and a damage event entity wich has components to calculate the "real" damage that is getting applied on the defending entity.
So the damage entity basically looks at the attacker stats, at the defender stats and applies a formula to them ?
Are there any examples ? ^^ Whats a more dynamic approach ? What if i want a entity that takes 50% less damage from physical damage ? :)
i dont know any examples
there are definitly more dynamic ways
but i think that would be most performat ๐
the damage entity will be loaded with all the attackers stats it needs and the target entity, keeping random data lookups low
more dynamic is maybe a enum of damage type
you will still need some sort of switch somewhere to split the caculations
even more dynamic would be enum + buffer stuff
so you have a enum of your damage types
and the enum int, links to a dynamic buffer index
those dynamic buffer(s) will be things like resistance buffer
i would just recommend a nice 'simple' start and then expand it as you go
simple = damage entity/buffer... doing direct damage to health component
Thanks :) damn... I could really need a list of possible ways.
What i want is actually the following, different damage/resistence types and need some sort of damage and resistence buff ^^ based on different conditions.
An example is : a mob which takes 50% more physical damage from players wearing a holy armor when its night.
So kinda complicated ^^
And of course the opposite. Some sort of damage buff
yea so on attack you spawn the do damage entity
Figure out the attackers stats somehow (im assuming you have this bit already) and copy them into the attack componet (for fixed damage types) or into some sort of buffer (For dynamic)
then you foreach all attack components
- look up the target entity
- gather its resistances
- do damage caculation
- apply damage
so the 50% more damage example
Attack component: Damage = 10
Attack Component physical damage buff = 1.5
(you could have a intermediate step to sum that, making further cacls easier)
foreach attack
physical resistance = target entity.get physical resistance
damage = (attack.damage * damage buff) / physical resistance
target entity. reduce health (damage)
poor mans sudo code example ๐
Alright, thanks ^^ the final question... Is there any way to automate such an formula ? Or do we need to hardcode it ? xD Because i could actually imagine that some entities use another damage formula ^^
so get it working first
๐
but then yes you could begin to expand it to some sort of enum/int lookup
so intead of get physical resistance
its something like get resistance with id (1)
i find once you see the 'hard coded' structure its simpler to expand/design the 'generic' version
(but dont use actual generics ๐ )
Hmmm... Thats something i dont quite understand. I think the damage calculation does involve multiple damage types.
Like damage = PhysicalDamage + MagicDamage / Resistence...
So if i add new damage types or resistences, i need to update that formula. So i guess theres no way to auto-construct such a formula :/
well you could create 2 damage entities
each with a different damage type
so the caluclations all stay the same (and simple), but each 'attack' could spawn many attack entities
so another example ๐
fire sword attack
spawns 2 attack event entities
Entity 1:
Damage = 15;
Type = DamageTypes.Physical;
Entity 2
Damage = 5;
Type = DamageTypes.Fire;
AddDamageOverTime
{
Damage = 2;
Type = DamageTypes.Fire
Time = 10s
}
DamageSystem:
Foreach DamageEntity
Resistance = GetResistanceFor(damageEntity.Type, damageEntity.Target)
damage = ....
damageEntity.Target.TakeDamage(damage)
That makes sense... But this doesnt solve the "automatic" or dynamic formula issue... So we still need to provide one formula for all our calculations right ? Theres no way around that. So each time we add a new damage time, we would be forced to update the formula ^^ well the more i think about it... The more i assume such a formula is always required.
well not really
the damage formual will always be the same no matter what damage type it is
its the values in the formular that changes
mainly resistance (armor)
so those values (resistances) would be stored on the target entities in a dynamic buffer
Resistance
DamageType = DamageTypeEnum
Resistance = %
you just look up the one you need
and feed the resistance into your caculation
i cant think of a case where you would have a whole separate damage formula
and to a player that would be very weird and confursing
modifiers on your damage is easy to express too
like maybe you want to skip resistance (eg for a critical hit)
you could just add a tag component to your attack event entity
and skip it in the inital damage system (using WithNone)
that will work too if you think up use cases where you need a whole seprate formula
Hmmm... Thats right... Furthermore its not common to add a new damage type like every day. I just know that wow has plenty types. Like poison damage, fire damage, physical, magic, light, shadow and so on. Thats actually pretty interesting.
A way i could imagine is
'
Type: Physical,
Index: 0,
Operator: +,
Type: Magic,
Index: 1,
Operator: /
'
Which produces something like "+Physical/Magic"
i think that would get super complicated but could work
instead of opperator you could also look at function pointers in burst
basicly burst compatable delegates
but start simple!!!
KISS
๐
also enums are magic and can have values that are NOT definned in the inital enum
making extention via mods or something possiable
eg enum damage type
Physical = 1
Magic =2
...
fire = 20
DamageType = (DamageType)888 is valid
Well it would be pretty flexible to add new types. But yeah probably overengineering. I bet WOW just has a huge calculation formula they use... Damn i wanna get an insight into that ^^
Its actually kinda sad that there no articles about that topic. But the enum thing is pretty cool :D i actually avoided them because i thought that they are not extendable ^^
pretty sure theres a reverse enginerred wow server somewere
that will have the caculation in
yea under the hood enums are just a data type
defaulting to int
you can change that too
eg enum DamageType : byte
will take up less space in your components (good thing) but will limit you to byte max value = 255
Well thats really a good think ^^
Lets say we want physical damage attacks deal more damage against entities with magic resistence. Would this be part of the damage calculation formula ? Or would the damage entity "buff"/increase its damage when a magic resistence was detected ?
i wouldnt put this in the damage formula
instead somewhere else
i would modify the resistances
so if physical resistance = 50% i would set magic resistace -(negative) 25% or something
so again you would have some sort of 'pipeline of resistances'
eg
gather up all equipment resistances and skill resistances => into initial resistances buffer => calculate resistance 'fights' ==> final resistances buffer
(wasnt sure what to call physical offsetting magical resistances ๐ )
with dots its great to keep things 'small'
and way easier too
so damage is just that, do damage, all resistances/buffs/modifiers are calculated separably and just 'fed' into the calculations
also that whole 'data flow' thing is very relevant
Hmmm... So we would basically create buffs for the player or mob. Like "Do 10% more damage when you wear a holy sword" and at the same time we would have some sort of buff system for the damage entities "Make physical damage deal double the damage when defender has no magic resistence" ? Thats all i can imagine ^^
Yea probably
As you go and build it after you have the initial bits in you will probably see ways to make it more extendable
But the core you should KISS
Makes maintaining it better
And you can easily extend/swap the 'data' flow if you need using things like with all/with none/ write groups
So i should just start with basic damage, then go with types and a formula, then go with stats buffing and then go with additional requirements like such weird cases where fire damage does more damage to specific entities ? ^^ sounds valid...
Just saw a huge plus with damage entities... You can change them pretty easily.
Like "Entity{ Sword{ damageEntity : 1 }, PhysicalDamage{...}}"
And then having some sort of damage entity "Entity{Damage, PhysicalDamage, MoreDamageIf{ animal, 20% }}" so could even change and add different damage calculations and additions easily.
I never thought its that difficult to add a "cool" and exciting damage system
Am I allowed to access ScriptableObjects from a job?
e.g. can the Job struct or any of the data inside it reference a ScriptableObject? I'm guessing no
Hi does anyone know if itโs possible to add a component to an entity in SystemBase Entities.Foreach ?
Long story short you need to use WithStructuralChanges().Run() if you're doing it in a ForEach
Or use a command buffer
@ornate jasper of course you can
but the question is more like "how do i get a reference to a scriptable object?"
so the simplest (and worst ๐ ) is to use references, and references.Load
the much better way is to use Addressables and Addressable.LoadAsync
You can't use reference/managed types in jobs
but its also a good idea to consider what/why you need this,
As what Sark just said, even if you can get the ScriptableObject, you cant use it in jobs/Foreach and will have to write annoying boilerplate to copy/move data around so you can use it in a Job
its likely a singleton entity will work for most cases of scriptable objects
or some custom converstion code to take a Scriptable Object and spit out entities
Can someone look at this: https://hatebin.com/teqvfdffbf
Very concise and fast read.
I only need to put [ReadOnly] on the NativeContainer fields inside my IJob struct, not on any fields I put in a class that is managing the job execution, right?
@solid rock are you talking about the containing system?
I'm talking about this:
public struct ProcessFluidNetworks : IJobParallelFor {
public NativeList<FluidBuffer> buffers;
[ReadOnly]
public NativeMultiHashMap<int, int> relationships;
public void Execute(int index) {
}
}```
I need readonly there if I want it to be readonly, right?
But I don't need ReadOnly here:
public class FluidJobTester : MonoBehaviour {
public NativeList<FluidBuffer> buffers;
[Readonly]
public NativeMultiHashMap<int, int> relationships;
private void OnEnable() {
buffers = new NativeList<FluidBuffer>(Allocator.Persistent);
relationships = new NativeMultiHashMap<int, int>(500, Allocator.Persistent);
}
private void OnDisable() {
buffers.Dispose();
relationships.Dispose();
}
private void Update() {
ProcessFluidNetworks job = new ProcessFluidNetworks();
job.buffers = buffers;
job.relationships = relationships;
job.Schedule(...);
// etc...
right @ocean tundra ?
i havnt really mixed jobs and monobehaviours but you shouldnt need readonly there
only in the job struct
[ReadOnly]
public NativeMultiHashMap<int, int> relationships;
public void Execute(int index) {
if (relationships.TryGetFirstValue(index, out int neighbor, out var iterator)) {
ProcessRelationship(neighbor);
while (relationships.TryGetNextValue(out neighbor, ref iterator)) {
ProcessRelationship(neighbor);
}
}
}```
Is there any better way of iterating over NativeMultiHashMap values?
Or is this pretty much it?
how do you set the exact facing of a DOTS object via EULER angles?
@solid rock kinda
you can use do... while instead
i had never used that loop type before ๐
I know Angular = new Vector3(rb.transform.rotation.x, rb.transform.rotation.y, rb.transform.rotation.z)
But that just changes the rotation
I want to change exact facing.
what's the diference in your mind between changing the "rotation" and changing the "exact facing"?
Also those x/y/z in your example are quaternion values, not euler values.
Angular is the velocity of rotation
Changing the facing means no rotational velocity, but directly look in a direction.
rb.rotation = <some quaternion>
if you want to use euler angles:
rb.rotation = Quaternion.Euler(x, y, z);
but that's for Rigidbodies
I am not setting rb.rotation
you can also use the RotationEulerXYZ or zyx/yxz components @remote crater
its documented in the TransformSystem of the entities docs
I am using my rb.rotation to try and set facing of a mimic object
I read that
I cant make heads or tails of it
No sample code
rb.rotation is a quaternion
Maybe I can find sample code in the demos...
just take it a little slower, each section describes a scenario, its not like you need to read every combination
whatever you're setting the rotation of should also be able to accept a quaternion
tldr just add RotationEulerXYZ to your entity and set the euler angles there, there are more combos if you want them but you dont need to use them
Who cares about rb anymore. How do I set the facing to be (0,45,90)?
I simply dont know syntax, I'm not dumb
its a component like Rotation, EntityManager.AddComponent(entity, new RotationEulerXYZ{Value = new float3(0,45,90)});
whatis it saying
ntityManager.AddComponent(GameBoardModel.playerEntity, new RotationEulerXYZ { Value = new float3(0, 45, 90) }); //error = Cannot convert from unity.transforms.RotationEulerXYZ to Unity.Entities.ComponentType
Of course I have an E to start
I think it should be AddComponentData.
dif error location
let me post .png
You guys rule btw
for actually helping
Sark, check it out now my funk soul brother: https://www.crystalfighter.com/code/1.png
My entity manager reference is proper
whys it light blue?
Cuz it moves entities n stuff
different color theme?
probs
light blue = valid and clickable to me
Visual studio is kinda weird
but passab;le
Once I have a mimic player, I will enable collisions then world build. I'm excited
Could have something playable in 2 days or so
That's a basic C# error. You don't have an "EntityManager" at that scope so it thinks you're trying to call a static method.
But I do
That same entity manager
five or so lines up
is working
just off screen
share more code please
That linear mimics my player gameobject with entity
So I have velocity mimiced ๐
its clearly not the same entity manager
WOW!
GameboardModel.entityManager
Thats what i get from copy pasting crappy code from eons ago thinking everything was valid
ty bro
๐
If I run this code over and over every 15 ms: GameBoardModel.entityManager.AddComponentData(GameBoardModel.playerEntity, new RotationEulerXYZ { Value = new float3(0, 45, 90) });
Will it keep creating new components?
Bingo!
Works!
it wont be very performant
ty
I know
I only have one object that is player that does this
all the rest is pure dots
My architecture was based on the idea that you always want one function coded, and never two of the same function you update over and over
By constraining it to my player controls, I can change both gameobject player and entity player with same code
Since my game has different play modes
I'm so happy man, you got me over a major tech wall
Been looking at dots for months. I think I finally got it
The funniest part is no one told me about DOTS
I made a post on Unity forum: Anyway I can use Visual Studio to write multithreaded code to unlock cores in unity
and someone directed me to dots. I'm so happy, feels like the universe is smiling at me
If anyone wants free steam keys(game is live now, but not the mmo part yet), pm me
Excuse me people, but...
You can use fixed arrays. Therefore you have to mark the struct unsafe. The field declaration looks like this: public fixed int Foo[6]. The compiler knows itยดs size at compile time and can inline the array instead of storing it on the heap.
This is a thing?? You can have arrays in IComponentData?
Is this one of those things that only 2% of people are aware of, or did I just miss a game changer here lol
guess you missed it ๐ was there since version 0.1.0-preview
generally it is recommended to just look at the source code/source code docs for IComponentData to see what is supported. Even possible without checking out the package:
https://github.com/needle-mirror/com.unity.entities/blob/master/Unity.Entities/IComponentData.cs
oof
I don't know much about unsafe stuff, but my understanding is burst is horrible at optimizing it. I expect you're better off using FixedLists which have been in for a long time
I call it unsafe oriented programming
Using ISystemBase will work that all code inside OnUpdate will be bursted or should create Job and job will be bursted? Also i can't see any ISystemBase systems in DOTS compiler
@half jay you mean public class MySystem : SystemBase {...} ?
This for example. Its available with 0.17 entity package
[BurstCompile]
public struct TestSingleBurstSystem : ISystemBase
{
public void OnCreate(ref SystemState state)
{
}
public void OnDestroy(ref SystemState state)
{
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
}
}
I'm using this:
using Unity.Entities;
using Unity.Jobs;
using Unity.Transforms;
public class CarMove : SystemBase {
protected override void OnUpdate() {
Entities.WithAll<Car>().ForEach((ref Translation position) => {
position.Value.x -= 0.01f;
}).Run();
}
}
dots engine invokes the OnUpdate and my cars move
That's the theory. Though it's extremely limited. For example no lambda's, referring to other systems or use of ECBs. Also anything other than I think IJob/IJobParallelFor/IJobChunk produces an error.
i just want some math calculation and may be Native collection iteration. Mostly without working with any entity
I haven't noticed much of a performance improvement - I'd be curious if you do
And in theory im not need do separate job for ISystemBase. All wrote in OnUpdate will be burstable?
You can also use Jobs.WithCode() lamba inside SystemBase, if you want a bursted job without iterating with entities foreach.
Where do u guys learn from? Id say 2019 and some 2020 vids show outdated dots stuff
in here ๐
- Official manual. It's kept up-to-date. Check pinned messages on this channel. There's a bunch dedicated to those new packages.
- Official samples on github. Also kept up-to-date within days after new releases. https://github.com/Unity-Technologies/EntityComponentSystemSamples
- Official forum. Follow the DOTS subforum from time to time.
- Unite videos from 2019 yeah, like you said they got old pretty fast. You can still grab the concepts and read changelogs to update the syntax.
- A few blogs. Some did a really nice job dissecting ECS when there was close to none docs. Can get old fast too but still enlightening.
- Dig source code. It's open enough to access it.
- Here
I have a moving entity(car) going over a map. I would like to know when the car reaches map's end.
I though using a collider trigger would be a valid approach. Otherwise, please, let me know.
So, to sum up: I though to add a "boxcollider" to an entity, which triggers a job (to destroy the object)
I'm trying not to use conversion neither authoring, so i'll appreciate a pure code approach.
do this approach feel correct to you?
Depends a lot on your game. If the map is a square and you want to check entities trespassing boundaries, the more efficient way is to check distance fro origin and remove when greater than.
Trigger area is more re-usable for other game mechanics once figured out
"A job to destroy the object": how many entities ? only 1 (player car) ? Or thousands ?
Already have a system that moves the cars, which could check if newPosition is out of bounds, but i'll like to deal with collisions, triggering events and so.
about the amount: cars (many). probably hundreds at most...
you think you could give a hand?
You know your game better. Try something, if you're stuck people on this channel will help
trying to setup a BoxCollider on my tile to detect when a car "hits" the end of the map i tried adding a component:
EntityManager.AddComponentData(tiles[i, j], new PhysicsCollider {
Value = BoxCollider.Create(new BoxGeometry {
Center = new float3(0.5f, 0.5f, 0.5f),
Size = new float3(1f, 1f, 1f)
//Orientation quaternion exists here...
})
});
I'm getting: ArgumentException: Orientation quaternion(0f, 0f, 0f, 0f) is not valid.
Do I need to give an "orientation"? what it would be?
quaternion.identity
and that means...?
of course, it works, but i dont know what im doing with that...
a quaternion of 0,0,0,0 is invalid
yea exactly. For the equivalent, you need the identity matrix when dealing with quaternions.
im at https://docs.unity3d.com/2021.1/Documentation/Manual/QuaternionAndEulerRotationsInUnity.html but im unable to understand what a quaternion is
whats the w?
and...identity means "not rotated"?
this might be a bit more involved than you expected.. I'd recommend watching some youtube videos about quaternions (there are many)
i always think of identity as like an acceptable zero value but i personally dont fully understand quaternions ๐
that is what quaternion.identity does internally as well ๐
The same way EntityManager exists as a property in Systembase ...does it physics world? or do I need to =World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>(); everywhere I use it?
@night venture you need to do that everywhere you use it, but World is also a property of Systembase so you can just do World.GetExistingSystem<BuildPhysicsWorld>();
also note that while you can cache the system, you can't store PhysicsWorld so if you are using it in onupdate you need to do buildPhysicsWorld.PhysicsWorld every frame because it modifies the struct
edit: tho maybe getting a ref also works, haven't tried that
Similar to SystemBase being used instead of ComponentSystem, should I use something to replace IJOB ? (trying to learn how to capture collision events) ? Perhaps ICollisionEventsJob ?
I'm looking for a DOTS safe UUID option. System.Guid doesn't seem to be able to cut it. Running into quite a few problems with it (managed / unmanaged code etc.). All the options I keep seeing also just use strings, which, again... DOTS/ECS
I also see EntityGuid, but that seems too specific to the entity system to be used generally
may I know why? considering each entity gets a unique id makes me wonder what you doing...
serialize/deserialize to save to a file. The data needs a uuid, the entity uuid can change because of how we are saving world data and reloading from json - @night venture
Can you give an example of what you're trying to port? IJobChunk is likely the closest to IJob, but you may or may not need that level of granularity depending on the context
I was able to simplify a bunch of systems down to Entities.ForEach when upgrading an old DOTS project
Why wouldn't System.Guid or another GUID generating system work in your use case? Is it due to needing concurrent generation from jobs, or..?
I have a moving entity with an attached PhysicsCollider component and also a static entity(not moving) with another PhysicsCollider component.
I'm trying to detect the collision or handle when the distance to collision (physicsWorld.CollisionWorld.CalculateDistance) is lower than 1f...
Every example i have seen so far is different form the other, outdated, requires unsafe Collider* cast...
PS: Im not trying to port anything, but trying to do it from scratch with "pure ECS".
to serialize entities there's a SerializeUtility that saves the World in binary format. That could simplify your life...if that works for you: https://docs.unity3d.com/Packages/com.unity.entities@0.17/api/Unity.Entities.Serialization.SerializeUtility.html
Gotcha - are you using the DOTS physics package, or just writing ECS code with Unity's regular game object-land physics?
generally physics collider stuff in dots will require unsafe. its just the way it is at the moment
there are not Mudbloods on my code ๐
Which is fine until I want to read the saved data from outside Unity
You would need a PhysicsBody too if it's moving
even for the simplest ones? https://forum.unity.com/threads/ecs-collisions.857725/#post-5657434
I recommend converting from a GO and check what componets are added
and probs a physicsShape
aren't you able to read binary?...xD
do you plan to serialize in json? i made a working test yesterday and would love to share knowledge. im just writing some entities using JsonConvert
i didn't feel it were necessary...seems this could work also:
EntityManager.AddComponentData(e, new PhysicsCollider {
Value = BoxCollider.Create(new BoxGeometry {
Center = new float3(0.5f, 0.5f, 0.5f),
Orientation = quaternion.identity,
Size = new float3(1f, 1f, 1f)
})
});
PS: english grammar: is feel or felt?
Could prolly be enough for a static collider ๐คทโโ๏ธ
well maybe not collision events, but its likely you will need it enabled for collider casts, or getting/setting any physics material
https://docs.unity3d.com/Packages/com.unity.physics@0.3/manual/interacting_with_bodies.html seems it is not needed ๐
Right - so what I would do is create the UID outside of ECS, perhaps a UIDComponentData that you attach to entities that need them. Create a system for it that fills in any freshly-added UIDComponentData with single-threaded, deterministic-if-desired UIDs; then you can safely move those UIDs in and out of your World and trust that they're still unique. ๐
Have you considered using a messaging system to handle this specific case? Handle the collisions elsewhere, and simply create a message when they're detected? Might be closer to what you're after from a code design perspective
In 99.9% of cases... I managed to run into that .1%. ๐ But yes, you could absolutely drop Guid into the system I described if that's what your after. I am inferring that the original issue is that you can't just directly interact with the Guid class from within a Job, which will still need to be resolved in any case.
?? guid is a struct, it should be fine in a job
imho, sounds too much complication to an overlapping collider...im on my first week on ecs!
but yea 99.99% of the time its fine, ive never managed to run into that .1% tho
and even tho i recommended guid im not using it either. instead i give a int ID during conversion
Haha, fair enough! That's the fun/terrible thing about ECS, sometimes it feels more awkward to do it the 'straightforward' way. ๐ You should be on the right track then
guid is too big for me to network, 128 bits is too much when i can get away with less then 32
Sure, but generating the Guid is likely the sticking point https://docs.microsoft.com/en-us/dotnet/api/system.guid.newguid?view=net-5.0 - that would explode if it was run from a Job ๐
yea... never tried making a guid from a job
except it allocates memory - managed vs unmanaged errors. The only way I've gotten it to work is using default(Guid). Even Guid.Empty allocates memory ๐คจ
I was just trying to compare against an UNSET Guid and it was a pain
hmmm thats annoying
Yup, for the reason described above. Unfortunately you're probably not going to get satisfactory results for your situation without writing some extra code to put ECS-friendly Guid generation into its own system
i swear i didnt have those issues
but i guess i wasnt directly using the guid for much
just looking up values from a hashmap
If you just want a quick and dirty probably-unique-thing you could do a hash function based on other attributes, but I wouldn't recommend it for anything other than a 5 second proof of concept ๐
i've used math.hash(void*...) for some stuff since it uses the xxhash32 algo
hey @ocean tundra any experience with PhysicsCollider? im struggling to have this working
would you say authoring is the way to go? (or gameobjects and all that non-ecs will eventually dissapear?)
yea authoring is definitly the way to go
unity has confirmed its the recommended way to use DOTS
gameobjects arent going anywhere, use authoring and save yourself the hassle of fighting it
and they arent killing MBs or GOs anytime soon
๐
at the current rate never ๐ฅฒ
haha yea
anyway authoring stuff also works nicely with subscene conversion
ok...then tomorrow ill refactor to use that. ill probably need your "theorical" help also...
for example: i created a tile map (Entity [,] ) from scratch importing the json file you help me create...if authoring is the way to go, I would rather have to create go from prefabs instead, isnt it?
maybe..
i would probably just leave it as is
your json file stuff is basicly a mini authoring/subscene replacement
can you elaborate a bit?
your json file, is basicly doing the same thing as subscenes
the only way you could 'mix' the 2 is to change your stuff to create from a prefab
but whats the point of that, all your components and data is set from json
well...using tilemap+editor, as you suggested, would also be easier
anyway, that's for tomorrow...today task was colliders, and im failing at the wuery/detection.
and, as a workaround, i tried to check x/ bounds...but encontered an issue...let me explain:
my cars are moving from left to right, increasing position.x
once they reached x>8 it's time to recycle them
but, in the way im doing it, this code is inside a foreach
Entities.WithAll<Car, DriveWestToEast>().ForEach((Entity e, ref Translation position, in Car car) => {
position.Value.x += car.speed;
if (isOutOfBounds(position.Value)) {
CarSystem.CarRecycle(e);
}
}).WithoutBurst().Run();
im sorry xDDDD
no communicating between systems like that
instead you Add a Tag component to your entity
and your car system's Entitys.Foreach has a WithAll<TAG> filter
have you ever used SQL?
sure
๐ no sql is way worse
i think i know how foreach works by now
couple of questions about that
1-if im only reading car.speed....should I use nothing or ref instead of in?
in = read only
ie: does it using in make a copy?
no
in and ref are both 'magic' that dont create a copy
but ONLY for STRUCTS
dont use either for classes
#bUtOnLyFoRsTrUcTs
as i have only spent a few days with ECS, i start to noticed they "switched2 from class (OOP) to struct(DO) as the core concept of the paradigm...isnt it?
mostly yea
much like screw objects and classes and use struct and tags
sturcts are easier to manage their memory manually
you can still use classes
but structs = more performance
and...probably because of my oop background, im a bit concerned about adding a tag to a foreach run onupdate, cause i have to "minimize" what onpudate does
structs=same size...
just use a entity command buffer
structural changes is something to try minimize, but at the same time required
i have a system responsible of spawning (and now recycling) cars
would you have ANOTHER system to move the cars? or it would make sense to have the same system for every car-related thing?
nope more systems
"nope, more systems" or "nope more systems" ? xD
ok...
more systems = better sepration of concerns = easier to maintain and extend