#archived-dots
1 messages ยท Page 44 of 1
why not attach cube before baking?
in scene
that's the only valid option
aside from runtime conversion
I would like to bake children.
Children are already baked tho, like your subscene hiarchry will automatically do a bake of every contained GO. (that includes children)
And the Transform baking system, which should be semi-readable and it will go in and take care of the relationships for you?
For me the baking of the child GameObject doesn't work by default.
However, the parent entity is a prefab which might be causing problems.
I'm setting the position and rotation of the parent like this. But I think this should be fine.
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
foreach (
var (realPosition, transform)
in SystemAPI.Query<RefRO<RealPosition>, TransformAspect>()
)
{
transform.Position = realPosition.ValueRO.Value.Position;
transform.Rotation = realPosition.ValueRO.Value.Rotation;
}
}```
wdym by it's not wokring?
during baking?
The cube position and rotation is not affected by the position and rotation of its parent
I don't get any errors
try to test bake cubes
within cubes
Child transform conversion works fine by my side
Do you also have prefab baking set up like this?
'UnitPrefabHolder' references 'Cleaver ECS' and has this code
public class UnitPrefabHolderMono : MonoBehaviour
{
[Required, SceneObjectsOnly] public GameObject prefab;
}
public class UnitPrefabHolderBaker : Baker<UnitPrefabHolderMono>
{
public override void Bake(UnitPrefabHolderMono authoring)
{
AddComponent(new UnitPrefabDC {Prefab = GetEntity(authoring.prefab)});
}
}
UnitPrefabDC.Prefab is later instantiated
you can't instantiate prefabs in baking
sorry, I don't really get it
No problem. I'll give this another try once I really need child entities.
Right now I can work around it
var prefab = SystemAPI.GetSingleton<UnitPrefabDC>().Prefab;
var clone = state.EntityManager.Instantiate(prefab);
In my screenshot its the hovercraft to the left above the blue terrain
so, you are trying to instantiate a prefab entity which is child of something else?
no I'm instantiating a prefab with a child
but somehow the child is broken
and doesn't move with the parent
does it have linked entity group?
As you can see in the screenshot the parent only has the child buffer
Okay then I'll add LinkedEntity group to the parent
It still doesn't work but thanks a lot for the help anyways @rustic rain and @proud jackal
I'll give it another try once I badly need child entities
How should one destroy an entity instantiated with prefab? I am having a problem where I am destroying the entity of enemy but instead of being destroyed it just moves to (0,0,0) and continues rendering there.
I understand that that entities are actual flat and hierarchy is kept with additional components.
What I do not understand is how to destroy all "child" entities, how do I even get them?
All entities in the LinkedEntityGroup of an entity that gets destroyed are destroyed with it.
is the script a baker or a monobehaviour (awake/start/...)?
In that screenshot, it only shifts at most 393,216 bytes of data every frame, or a 314x314 texture every frame. Basically nothing so I do it every frame.
And yea, i just zero out the Z translation and velocity vectors of all the bodies.
Yeah that's what I was thinking. Just have all 2d objects be 3d objects with 0 Z
[BurstCompile]
private unsafe struct ConstrainJob : IJob
{
public int Linear, Angular, World, Pos;
public NativeArray<MotionVelocity> Velocity;
public NativeArray<MotionData> Data;
public void Execute()
{
var vel = (MotionVelocity*)Velocity.GetUnsafePtr();
// * Fixed zero value.
var zC = 0;
// * Shift pointer to access Z variable of linear velocity and zero it out.
void* destination = (float*)((byte*)vel + Linear) + 2;
UnsafeUtility.MemCpyStride(destination, sizeof(MotionVelocity), &zC,
0, sizeof(int), Velocity.Length);
// * Fixed float2 zero value.
float2 xyC = float2.zero;
// * Shift pointer to access XY fields of angular velocity and zero them out.
destination = (byte*)vel + Angular;
UnsafeUtility.MemCpyStride(destination, sizeof(MotionVelocity), &xyC,
0, sizeof(float2), Velocity.Length);
var dat = (MotionData*)Data.GetUnsafePtr();
// * Shift pointer to access WorldFromMotion (RigidTransform) and then the Z variable of its position.
destination = (float*)((byte*)dat + World + Pos) + 2;
UnsafeUtility.MemCpyStride(destination, sizeof(MotionData), &zC,
0, sizeof(int), Data.Length);
// ! Body motion apparently not needed?
// destination = (float*)((byte*)dat + Body + Pos) + 2;
// UnsafeUtility.MemCpyStride(destination, sizeof(MotionData), &zC,
// 0, sizeof(int), Data.Length);
}
}```
Works so far. I've just been hitting spheres together so my test case isnt the most robust.
public void OnCreate(ref SystemState state)
{
Type velType = typeof(MotionVelocity);
_linear = UnsafeUtility.GetFieldOffset(velType.GetField(nameof(MotionVelocity.LinearVelocity)));
_angular = UnsafeUtility.GetFieldOffset(velType.GetField(nameof(MotionVelocity.AngularVelocity)));
Type datType = typeof(MotionData);
_world = UnsafeUtility.GetFieldOffset(datType.GetField(nameof(MotionData.WorldFromMotion)));
//_body = UnsafeUtility.GetFieldOffset(datType.GetField(nameof(MotionData.BodyFromMotion)));
Type rigType = typeof(RigidTransform);
_pos = UnsafeUtility.GetFieldOffset(rigType.GetField(nameof(RigidTransform.pos)));
}``` The pointer offsets are obtained by reflection at the creation of the system to ensure minimal hardcoding. I hardcoded the Z offset of the float3 though, I think that can be safely assumed.
That seems like overkill. Since I'm using entities I just did
partial struct ConstraintJob : IJobEntity
{
// Require ZConstraint Tag for querying
// entities for job
void Execute(Entity e,
ref LocalToWorldTransform tf)
{
var pos = tf.Value;
pos.Position.z = 0;
tf.Value = pos;
}
}
Might also want to zero out the XY angular velocity or else your object will start rotating and flipping.
Also, LocalToWorldTransform is not supported with DOTS Physics.
I have a list.addnativerange extension which is much faster
i solved it by keeping a cached version of the list inside the system instead of using the dynamicbuffer as a cache. is that a bad idea?
Whatever works
your extension is in your core package?
I also have a way to get access to internal list array without allocations and can reinterpret that to a native array
To allow me to write direct with no allocs
ill have a look through those. i bet they come in handy. i didnt ref your assembly so i havent discovered your extensions yet
Atm im trying to get the NavMeshModifiers to work with something other than the default agent... I dont know how i can get the agentID from the NavMeshModifier :/
The only way to check if the modifier affects an Agent is this: public bool AffectsAgentType(int agentTypeID) { if (m_AffectedAgents.Count == 0) return false; if (m_AffectedAgents[0] == -1) return true; return m_AffectedAgents.IndexOf(agentTypeID) != -1; }
And it requires me to know all AgentIDs beforehand. Is there some way to get a List of all AgentIDs available?
but that isnt available at bake time right?
It is
Navmesh getsettingscount
Then just navmesh getsettingsbyindex
(typing on phone in bed)
And each settings has agent type id
so even if i didnt bake a navmesh for an agent it still has its settings?
Yes
thank god
This is just reading the settings you setup in the nav mesh window
Id like to confirm that it works but unity is crashing/hanging constantly today :S
exactly what i needed though! i really dont know how you have an answer to everything..
works perfectly fine now!
One last question remaining about Navmeshes:
As far as i understood i need a NavMeshData per Agent. But its fine to add all those NavMeshData to one NavMeshDataInstance?
Yeah you need to build 1 mesh per agent type
As for the setup can't remember syntax sorry, it's a bit confusing in both naming and setup
how do I update code that used UnsafeList to UnsafeList<T>? Unity Collections deprecated typeless UnsafeList and one of my libraries uses it ๐ฆ
interesting, what's your use case?
you could somewhat replace it with nativestream if you need something typeless
though it's not the same
i just use nativelist<byte>
with a tiny wrapper/extension
yeah the asset is "Obi Fluid" and it's because I'm trying to port the project to 2022.2 and entities 1.0 ๐ฆ
where T : unmanaged
{
data.AddRange(&value, UnsafeUtility.SizeOf<T>());
}```
seems like it's not a drop-in replacement thing to get rid of UnsafeList eh
entities has this internally
unsafe struct TypelessUnsafeList
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
public AtomicSafetyHandle m_Safety;
#endif
[NativeDisableUnsafePtrRestriction] public byte* Ptr;
[NativeDisableUnsafePtrRestriction] public int* Length;
public int Capacity;
}```
but that ain't too helpful for you
yeah I will just contact the asset author for support and see what I can do to help them, thanks!
yup that's the crappy thing about upgrading unity "ahead" of my assets ๐ฆ
Is schedule granularity not a thing anymore?
Can't find it on IJobChunk or IJobEntity
Huh, that's kind of a bummer. I had a few things that would have benefitted from it
yeah but tbh worrying about it means your high-level architecture is somewhat funky ๐
Eh, it's not that crazy. For example, pathfinding scheduling benefits from it massively
Especially on CPUs with a lot of cores
if you really need it, then there's always ParallelFor eh
Yep but that's a massive amount of boilerplate compared to IJobEntity / IJobChunk
agreed, hope that's on their roadmap to bring more codegen goodies everywhere!
yeah i had a few usages of it as well
was nice to schedule 1 navmesh generation per thread for example
or to ensure pathfinding was split evenly and not having a huge spike on 1 thread because all entities from 1 chunk decided to find a path on the same frame
i don't use it enough to really care though
the couple of cases i can deal with a bit of extra boilerplate and just use an IJobFor
I hope they also add the ability to set a shared component filter on an IJobEntity back in, it's so much more boilerplate now
Need to re-define the query each time. Might as well just use IJobChunk at that point...
A lot of the utility that Entities.ForEach had in general is gone now, I hope that gets added back in
e.g. fetching the auto-generated entity query into a variable
do you do a lot of setsharedfilters?
think i might have used it once ever on EFE
IJobEntity not good for padding those code coverage numbers ๐ฆ
i was like, i'm pretty sure i've completely tested this system but it's only 57% coverage i'd expect 95%
oh yeah, IJobEntity alternate paths....
oh i can probably add Temp to the exclude path
maybe that'll avoid them
yeah that works
I use it for the weird world system I use, not sure if you can remember.
For example I'll have an entity that is a "world", and each voronoi cell is an entity that belongs to that world, and has a shared component that points to the world so they can find them, and I can more performantly access data about that cells' world in an IJobChunk
How else would I know what world a voronoi cell belongs to
are you iterating all worlds and scheduling separate jobs?
with the ability to access unmanaged shared components in jobs i find little reason to do this now
hence the curiosity
I don't see how that changes it? My grouping component is also unmanaged
Or do you mean early-outing?
(based on the state of the shared component)
(instead of using a shared filter)
^ this type of thing, each chunk i get in a IJC will always be the same world
so i can just execute in the same job in parallel instead of scheduling a bunch of jobs 1 after the other
The only real thing I use it for atm is this situation:
I'll trigger some world generation step by adding a tag to the "world" entity, and then I need to iterate over all voronoi cells belonging only to that world, ignoring all other cells. I could also add a tag to all the relevant entities, but I think that would be slow
yeah
The other approach which avoids the filter is just iterating over all cells, checking the shared component, and early outing for the entire chunk if nothing needs to be done
Probably less code that way, but would only really work for IJobChunk
so you want like an overload for schedule on IJobEntity or something?
e.g. new MyJob().WithSharedComponentFilter(...).Schedule()
so basically how it used to work for Entities.ForEach
from a vague understanding of how the source generators are setup atm i can understand why this isn't supported
Yeah it sounds difficult
it'd probably be easier if it was just in the schedule overload
I'd take either ๐
I've only looked at the source-gen bits very briefly
im sure it's doable either way, but who knows
i'd kind of like a with query out
personally
This?
yeah
Yeah I also miss that. There's a few nice utility things that were lost in the transition
honestly that'd mostly solve the filter option as well
not as clean
but much cleaner
Yeah re-defining the query for an IJobEntity each time feels really wrong
systemapi.querybuilder is pretty clean for passing queries to ijobentity
but i think it's error prone
thats what i don't like about it
Error prone in what way? If you change the signature of Execute?
yeah
Yep
they might never look at the scheduling code
and realize it's using a different query
Some other things I'm also really excited for are structural updates in Query, and support for code-gen'd type handles with SystemAPI
or just some obscure case where someone edits the job and someone edits the query in separate pull requests
Yeah I can see that causing issues real quick, especially since you also need to correctly define the read and write permissions on the query the same was as the IJobEntity
at least the error message is pretty clear if you mess it up, still very annoying though
the larger my team gets, the more i value reducing ability to make mistakes
definitely
where I work we mainly use python for stuff, and it really annoys me that it's so difficult to enforce certain things
the one thing i really want to focus on next project is code re-use
the number of different id, grouping, etc systems in our project is ridiculous
people just don't realize a solution already exists
Yeah that's something I'm kind of struggling with ecs, I usually just write a completely seperated system with all jobs only used by that system
although there usually isn't a huge deal of overlap in how they work, so I'm not sure how that would even work
I also try to put "smaller" operations that could be re-used inside of an already existing job instead of scheduling it separately since scheduling overhead used to be an issue...
@rotund token I was planning on writing a graph based ability system soon, but I'm not entirely sure how to go about storing the logic of the actually executable graph node.
My first idea was to store them in a blobarray, and each node knows the index of the next node. But the scheduling issue is then that a single job will be running all node-types, meaning it would need to grab a lot of component lookups.
The other idea was to have a job per graph node type.
Any tips?
thats basically how i do my ai
except i didn't use blobs because i found it too painful to setup
first idea
but also i like the ability to edit graphs at runtime which is a bit more painful for blobs as well
The thing I was having trouble with is that an ability can basically be anything, so in theory it would require all component lookups for all things that it could modify
so yeah i just serialize factories to disk and generate the graph in oncreate (or when it changes for runtime updating for testing)
yep my ai system is generic
so anyone can extend it with any component
its kind of a graph based utility sytem
But a single job runs the update logic for all components?
What if a component needs to lookup another component?
public float Score(in EntityContext<T> entityContext, ref T context)
{
fixed (Scorer<T>* scorerHeader = &this)
{
var scorer = (void*)((IntPtr)scorerHeader + UnsafeUtility.SizeOf<Scorer<T>>());
return this.header.ScorerType switch
{
(short)Core.ScorerType.Default => UnsafeUtility.AsRef<DefaultScorer<T>>(scorer).Score(in entityContext, ref context),
_ => context.CustomScorers(this.header.ScorerType, new Scorers<T>(scorer), in entityContext, ref context),
};
}
}```
every single one of these is <T> : unmanaged, IContext
and all the component handles are passed in the context
so it's re-usable in any game
^ they can also add custom nodes via this
in the EntityContext?
nah in ref T context
entity context stores default info about the current entity processing
where T : unmanaged, IContext<T>
{
internal Graphs<T> Graphs { get; set; }
#if UNITY_EDITOR && !BL_AI_DISABLE_DEBUGGER
internal AIDebugger AIDebugger { get; set; }
#endif
public RandomReference Random { get; internal set; }
public Entity Entity { get; internal set; }
public int EntityInQueryIndex { get; internal set; }
public int EntityIndexInChunk { get; internal set; }
}```
And the component defines which type of lookups it needs somehow?
you just implement a struct
e.g. if I need to know the health of another entity
and put the handles/lookups/whatever you want
How are those populated? Reflection?
no
you just implement the system
where T : unmanaged, IContext<T>```
For example
{
/// <inheritdoc/>
protected override AIContext CreateContext()
{
return new AIContext
{
Translations = this.GetComponentTypeHandle<Translation>(true),
Observations = this.GetBufferTypeHandle<Observation>(true),
};
}
}```
i have this little sneaky
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual GenericResolver<T> GenericResolver { get; }```
property in the base
that is enough to get burst/il2cpp to not bitch about generics
I see, and the T in AISystemBase is what is passed as the context to the component?
yeah context is everything
where T : unmanaged, IContext<T>
{
void InitChunk(ArchetypeChunk chunk, int batchIndex);
float CustomScorers(short scorerType, Scorers<T> scorer, in EntityContext<T> entityContext, ref T context);
void CustomActions(short actionType, Actions<T> action, in EntityContext<T> entityContext, ref T context);
float CustomOptionScorers<TOption>(short scorerType, OptionScorers<T> scorer, in EntityContext<T> entityContext, ref T context, in TOption option)
where TOption : unmanaged;
}```
allows adding custom nodes as well as data
Are the type handles stored or is CreateContext called for each update?
(the one thing i haven't got working here is full generic sharing for il2cpp, for some reason it just won't play nice even if i explicitly define all types)
yeah so i have updated it to 1.0
If I had a dollar for all the people who use a scripting language for projects with complex dependency graphs....
but i haven't updated the samples so its still creating them per frame
don't worry I hate it too
but there's no reason that needs to happen
Looks very cool @rotund token , and also gave me a few ideas for my stuff, thanks
i wrote this like 2 years ago
and it's kind of just sat here
it was amazing at the time
i also found like 4 really deep obscure burst bugs
I don't think I've even used ECS that long ๐
im coming up on 5 years i think
so basically when it was announced? ๐
march 2018 i think it was releasedish?
i think like a month or so after it was released
Tertle is literally the person i keep seeing in unity threads when i look up info on ECS
Thanks for all your contributions
i find there are enough experienced users now I'm not really needed
I still have trouble wrapping my head around writing generic code for ECS, so this made it a bit more clear
Btw, what is the actual output of your AI system? That's something I've been wondering with ECS generics, since you'd need to somehow signal other parts of the code to do stuff, e.g. with a component tag or something
usually it just sets a bit field
to determine state
and other systems take it from there
Looks like you pre-define actions (looking at the short actiontype)?
but really it can do anything
set targets etc
i try to avoid putting the update logic in there
like my move routine won't exist inside my AI
it'll just set the, follow target flag
and the AI will just check next frame current state, if it wants to change etc
Would you say your AI system works like a sort of AI API?
that other entities use in order to manage their own AI behaviour?
How do you avoid the managed interface type when running the job?
what do you mean? the T is restricted to unmanaged
Yes, but you'd need to store the result of AISystem.CreateContext somewhere right? And that can't return a struct
unless you do some unsafe stuff
i don't see why not. i have layers built on top of the AI and also use it for things like observation/scanning. you can assign as many graphs as you want per entity and each graph can have different tick rates (1/60, 1/10, 1, 10) etc
what do you mean?
Create context returns a struct
protected abstract T CreateContext();
{
Context = this.CreateContext(),
AIUtilityGraphs = this.aiUtilityGraphs,
EntityHandle = this.GetEntityTypeHandle(),
AIHandle = this.GetBufferTypeHandle<AI>(),
Seed = this.GetSeed(),
ChunkFirstIndices = chunkFirstIndices,
#if UNITY_EDITOR && !BL_AI_DISABLE_DEBUGGER
DebugWriter = this.eventProducer.CreateWriter(),
#endif
};
this.Dependency = job.ScheduleParallelByRef(this.aiQuery, this.Dependency);```
literally pass it straight to the job
Context = this.CreateContext(),
Ah, it runs a job for each defined component?
you usually only implement 1 AI system
in theory you could implement more
but there's not much reason to
you can attach multiple AI graphs to an entity
{
/// <summary> Gets the key to the graph. </summary>
public int Key;
/// <summary> Gets the number of frames between updates. </summary>
public int UpdateEveryXFrames;
/// <summary> Gets a value indicating whether the AI is enabled. </summary>
public bool Enabled;
/// <summary>
/// How many frames before the AI should update again.
/// To avoid updating all AI on the same frame, if you are instantiating AI from code this should be set to a random value.
/// e.g. Random.Range(0, ai.UpdateEveryXFrames) + 1
/// AI in a subscene are given a random value during conversion.
/// </summary>
public int FramesBeforeNextUpdate;
}```
Ah, and CreateContext creates the shared context for all custom components?
it's a buffer
has everything
Ah, ok. That's why I was confused. I thought each component defines its own context
Got it
for the record, my AI system is unproven in production so I don't really recommend the huge complexities it took to setup
but it's a very interesting implementation
It's just my hobby and I'm the only person working on my project, so everything goes 
(also if you're not intending to release as a general purpose shared library, no reason to make it generic)
(could save a lot of time/effort figuring that out)
I think the topic of 2nd order Systems (systems used by other systems) is still a relatively unexplored topic in ECS, so I think its interesting
Sorry for asking so many questions about it, but I'm still confused on how the actual implementing logic looks like for the struct that calculates the score. Do you have an example?
Since that part also looked generic
oh boy ok
{
private EntityType entityType;
private bool not;
private float score;
/// <inheritdoc/>
public float Score(in EntityContext<AIContext> entityContext, ref AIContext context)
{
Check.Assume(context.Observations.Length != 0, $"Entity({entityContext.Entity.ToFixedString()}) without Observation using HasEntityInMemory.");
var observations = context.Observations[entityContext.EntityIndexInChunk].AsNativeArray();
foreach (var obs in observations)
{
if (this.entityType != EntityType.Any && obs.EntityType != this.entityType)
{
continue;
}
return this.not ? 0f : this.score;
}
return this.not ? this.score : 0f;
}
/// <summary> Factory for <see cref="HasEntityInMemory"/>. </summary>
public class Factory : Scorer<AIContext>.Factory<HasEntityInMemory>
{
/// <inheritdoc/>
public override short ScorerType => 1;
/// <inheritdoc/>
public override string DefaultName => "Has Entity In Memory";
public EntityType EntityType { get; set; }
public bool Not { get; set; }
public float Score { get; set; }
/// <inheritdoc/>
protected override void Init(ref HasEntityInMemory scorer, MemoryAllocator allocator)
{
scorer.entityType = EntityType;
scorer.not = Not;
scorer.score = Score;
}
}
}```
this is a scorer
Factory is what the UI graph works and what is serialized
I see. And when the factories are called, the results are added to a buffer somewhere?
there is no buffer
Where is the result of the factory put at runtime then?
private UnsafeParallelHashMap<int, ReferenceData> aiUtilityGraphs;
Ah I meant buffer in the more general sense of "in an array type thing"
versus on entities or something
each node is allocated
and just points to each other
the same graph is used by all entities that use the node
no state is stored in it
What would you do if you needed to store state?
store it on the entity
The reason I'm asking is since I need to store state for my ability stuff, so I was wondering
like my entities have state, target/s etc
Huh. Having a node graph often implies data being stored in the nodes to prevent duplicate pathing calculations
just think of each node as a single job
What do you mean by pathing?
Oh wait that type of node graph
I was thinking like pathing nodes, A* or something
so you can visually see what paths the AI took
This is just for general purpose AI, not pathfinding in particular
over the last X frames
That's really neat, since utility systems are usually tricky to debug
yeah
{
fixed (Action<T>* actionHeader = &this)
{
#if UNITY_EDITOR && !BL_AI_DISABLE_DEBUGGER
entityContext.AIDebugger.WriteNode(this.header.Guid);
#endif
var action = (void*)((IntPtr)actionHeader + UnsafeUtility.SizeOf<Action<T>>());
switch (this.header.ActionType)
{
case (short)ActionType.Selector:
UnsafeUtility.AsRef<SelectorAction<T>>(action).Execute(in entityContext, ref context);
break;
case (short)ActionType.AILink:
UnsafeUtility.AsRef<AILinkAction<T>>(action).Execute(in entityContext, ref context);
break;
case (short)ActionType.Composite:
UnsafeUtility.AsRef<CompositeAction<T>>(action).Execute(in entityContext, ref context);
break;
default:
context.CustomActions(this.header.ActionType, new Actions<T>(action), in entityContext, ref context);
break;
}
}
}```
each node has a unique ID
and it writes this before entering it
(can be compiled out as you can see)
i basically use fake inheritance
for each type of node
(Action is not System.Action)
Yeah I thought so, that would have been weird ๐
UnsafeUtility.SizeOf<Action<T>>() this works on IL2CPP?
ah
Are il2cpp builds working atm?
not sure how to resolve it
yes
So yeah, you have to select "Faster runtime" not "Faster (smaller) builds" for this AI to work atm
cant you just give your generic type wrapper class a custom sizeof method?
(which is the opposite issue that Unity had for a while with il2cpp)
again this is in burst so it doesn't matter
the issue is my deserializer and creation of the nodes at runtime
that il2cpp has issues with
guess I gotta figure out my weird marshaling issue soon then 
it's just my generic nodes
user generic have no issues because they're fully defined
(de)serialization issues are my nemesis
my current workaround is
where T : unmanaged, IContext<T>
{
[Preserve]
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual GenericResolver<T> GenericResolver { get; }```
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public struct GenericResolver<T>
where T : unmanaged, IContext<T>
{
public AISystemBase<T>.AIJob Job { get; }
public FirstScoreWinsSelector<T>.Factory FirstScoreWinsSelector { get; }
public HighestScoreWinsSelector<T>.Factory HighestScoreWinsSelector { get; }
public RandomWeightedScoreWinsSelector<T>.Factory RandomWeightedScoreWinsSelector { get; }
public AllOrNothingQualifier<T>.Factory AllOrNothingQualifier { get; }
public DefaultQualifier<T>.Factory DefaultQualifier { get; }
public FixedScoreQualifier<T>.Factory FixedScoreQualifier { get; }
public MinimumOrNothingQualifier<T>.Factory MinimumOrNothingQualifier { get; }
public SumAllAboveThresholdQualifier<T>.Factory SumAllAboveThresholdQualifier { get; }
public SumAllQualifier<T>.Factory SumAllQualifier { get; }
public SumWhileAboveThresholdQualifier<T>.Factory SumWhileAboveThresholdQualifier { get; }
public AILinkAction<T>.Factory AILinkAction { get; }
public CompositeAction<T>.Factory CompositeAction { get; }
public SelectorAction<T>.Factory SelectorAction { get; }
public DefaultScorer<T>.Factory DefaultScorer { get; }
}```
and this is enough to get it to run fine in both burst and il2cpp "Faster runtime"
but not "Faster (smaller) builds"
even manually defining the implementation (just for the sake of testing) didn't work for me
so i'm not sure how to solve this
i could have code-gen explicit definitions if it came to it, but it didn't help
odd
i just get
ExecutionEngineException: An unresolved indirect call lookup failed
which has 0 google results
(try it yourself "An unresolved indirect call lookup failed")
so that's always a good sign i'm doing something bad ๐
different ExecutionEngineException
Did you try the hint google gave you?
For example, "cake recipes" instead of "how to make a cake."
the best bit is,
in Unity 2022.1, IL2CPP no longer produces an ExecutionEngineException, eliminating a whole class of errors that are difficult to rectify.
you got pranked
โFaster (smaller) buildsโ is meant to remove these exceptions but i seem to have found an edge case
I also have an issue with il2cpp generics, but I think mine is intended
Hmmm so it perhaps it isnt registering one of your Generics as being used and therefore cant compile the correct version for intepreting the generic?
then an explicit implementation would work, but tertle mentioned that didn't work either
yeah i defined the explicit implementations as a test
and i could get it to work only at the top level
Can you try to narrow down the problem by making the most concise test that results in this error?
Going by the article, if il2cpp can already generate code for value type generics, why does marshaling them not work?
If anyone else here writes shaderlabs, have you gotten unorm float4 buffers to work? Ive been feeding in Color32s and I'm forced to unpack them manually (bitmask the bytes and / 255) as setting a buffer<unorm float4> Color32 doesnt unpack automatically.
Although unorm float4 seems to be a DX12 feature....
ugh, 1.0-pre unity plz.
How are you receiving the color32 buffer?
I assume you are writing a custom GLSL shader that explicitly takes in a list of colors?
HLSL. I'm using a Buffer<unorm float4> Colors; Populated using a compute buffer of ComputeBuffer(count, sizeof(int))
and using something like this doesn't work?:
[MaterialProperty("_ColorBuffer")]
public struct ColorBufferPropertyOverride : IComponentData
{
public Buffer<float4> ColorBuffer;
}
I'm not using Entities Rendering but that will work with Color, not Color32 which is a byte packed version.
Not work as in it doesnt convert, or doesnt convert correctly?
This is what I have to do to unpack a Color32 into a float4. Since the color itself is a R8G8B8A8_UNORM float4.
Where Buffer<uint> LightColor;
I wish to be able to do Buffer<unorm float4> LightColor; and not have to do that unpacking.
Oh duh. Of course it wont work, a Color32 is the size of an int/float.
And I'm pretty sure the docs say that most conversions require the same number of bytes for the conversion to occur
yea, but what's the use of a unorm then?
I want to feed in R8G8B8A8 which is 32 bits wide and thus size of an int for packing and just directly render it
I think i misunderstood what your shader looked like.
as part of your shader you have a Buffer<unorm float4> Colors that already convert into the correct color type, but trying to populate that data from Unity => HLSL isnt working
is that correct?
I am attempting to use Buffer<unorm float4> Colors and I'm populating it with Color32s, which is in RGBA32 format.
I can use Buffer<uint> Colors then unpack it using bitshifts so the data is being transferred properly.
sorry. I don't know enough to be any more help here
Yea, it's very very niche hlsl coding and there's only a few posts from 2010 (12 years ago) talking about it
Ugh, i know why. i dont have access to driver level shader resource view assignment of buffer types. Unity defaults to 32 bit wide values.
I dont have access to the source parameter in this example C++ draw call.
They'll port it to 22 once it makes it to 23
It's already landed in 23 nearly a month ago. That port is taking a while.
is there any way to parallel write to a native reference? Or should i just use nativearray<whatever>[0]?
ok, from endless googling, it appears you can't, unless im missing something lol
I just stumbled upon the problem that perfabs in subscenes do not get LinkedEntityGroups. How am I supposed to destroy them at runtime? Destroying the root entity always leaves the children behind.
ah they should definitely get LEG
my big complaint with baking is that prefabs get LEG even if they shouldn't (they have no hierarchy)
how is everyone not getting LEG when my problem is I am ^_^'
BakedEntityData - line 824
CreateEntityForPrefab
var buffer = _EntityManager.AddBuffer<LinkedEntityGroupBakingData>(entity);
always adds a linked entity group to a prefab
are your children physics objects or something?
Are you talking about 1.0? Because I am still on 0.51 and they dont get a LEG
I just added a cube to a sphere and it does not get a LEG:
I have some physics objects as children which get unparented but it also happens without any physics involved
Maybe I should specify that by prefabs I mean prefabs placed in the subscene and not referenced prefabs
Can someone explain what exactly is Project Tiny? I dont understand why description says its only for small games, like mobile games, are there some actual limitation? And why its not updating, are there any problems? Can i somehow get something from it, like ecs sprite rendering and use it in my unity project, as i understand i cant, but why?
Forget about it for now
It's been postponed till better times
but there is so much stuff like sprite rendering and 2d physics, i cant find anything else like that for ecs
Yep
isnt it main performance boost
ye but u have to use normal physics and sprite rendering which is kinda slow if u want to have a lot of objects, not sure about ecs performance tho, i assume physics much be optimized in some similar way at low lvl
Yeah. Sadly
Physics is fine though
It's pretty efficient on it's own
Bad part is that you get 2d for the price of 3d
You can do certain optimizations thogug
To make 2d rendering faster
Like disabling game objects that are culled
The goal of project tiny was to export games and pack them for things like web content: https://tiny.vision/demos/TinyRacing/Wasm/TinyRacing.html
Can't remember the exact final size of that project - but it was a few kb and can work nicely on mobile WebGL (it likely compiled things to wasm too). And as Issue said - it's been shelved.
You can't really use things like rendering from project tiny because it uses a different rendering/audio path than what Unity provides out of the box (it uses BGFX as its graphics backend https://github.com/bkaradzic/bgfx and miniaudio for its audio playback engine https://github.com/mackron/miniaudio.) You can probably still take a look at the package source and get some inspiration from it - doubt you can pull things out of it and use it directly in your project.
i wonder why they decided to make it specifically for small games, even tho ecs is good for scaling, i guess its also good to small size projects, but it is what it is. I will look into BGFX, thats rly interesting
well, since ECS was fine for small projects
that's probably why they didn't bother with tiny
I think facebook messenger's instant games were a thing a couple of years ago and was a candidate for Project Tiny. I didn't really follow it so I don't know what happened afterwards. ยฏ_(ใ)_/ยฏ
LEG is only automatically added to prefab assets referenced by a baker, not game objects or instantiated prefabs in a subscene. But you can manually add LinkedEntityGroupAuthoring to the game object to add a LEG for the entire hierarchy.
I need to implement a dynamic navmesh, one that I can update at runtime for changes in scenery. Is there something like this for DOTS already? If so, can someone point me in the right direction?
Haven't really used subscenes much yet but this seems like a weird design decision to me as it makes prefabs work differently depending on their instantiation method. Does 1.0 have a LikedEntityGroupAuthoring? Because I just created one myself for 0.51
Yeah they added the LinkedEntityGroupAuthoring in 1.0. It walks the hierarchy and adds all children to it.
I kinda like how it gives you explicit control over whether you want the LEG, but I don't like how it's inconsistent with the prefab workflow.
Yeah I can see why the explicit control might help. But its annoying that I have to add these to the prefabs in my test scenes just because they are not instantiated at runtime
I know a lot of folks here would prefab that no LEG get automatically added, but I think its the right approach for new DOTS developers. Otherwise, things don't work how you expect them to. I think I'd prefer a DoNotAddLinkedEntityGroup authoring component that we can add to a prefab or game object to skip the LEG generation.
Same goes for the transform components. I think the TransformUsageFlags stuff in the baker is really confusing. Maybe there could be an OverrideEntityDefaults authoring component that lets you control both the transform components and LEG.
I don't suppose anyone has any insight into why this is happening, when I instantiate all these physics items
the irony is I want them to do something like this but in a different way, and I had a script that changed the initial linear velocity, but I removed it and reset the values to zero, but they are still flying away in this manner
You mean the confetti effect? Are you spawning them all at the same place? The physics engine will violently separate the objects if they intersect.
yeah that's what I thought it could be but I've even turned off collisions between them
Make sure they arent colliding with the source object as well. Any clipping will cause that spray
why is clipping so vliolent
ok I found it, its colliding with an environment collider that surrounds the whole shelves, how did I not see that
thanks
Thats just how physics engines work
is there a violence setting to turn it down
yeah and its because I've got tons of colliders overlapping, it kind of makes it more difficult to remember all of them
i have little bumps in my level and it makes my ghost do so many barrel rolls
No, as in that's how the math to resolve collision position offsets work. You'll need to iteratively reduce collider penetration to reduce the violence which costs quite a bit of performance. Especially with 3D rigidbodies.
It's also how they ensure stacking stability. If bodies just offset their positions by their calculated penetration distance, stacked boxes would be very unstable.
In this 2015 GDC talk, QWOP creator Bennett Foddy explains how to make your game feel solid without writing your own physics engine or breaking your entire game.
GDC talks cover a range of developmental topics including game design, programming, audio, visual arts, business management, production, online games, and much more. We post a fresh G...
3:10 - 4:00 is spot on
I tried to use generic SystemStateComponents and got the following error:
Execute() parameter 'registered' is not a supported parameter in an IJobEntity type.
Is it just not allowed to use generic in any place that uses code generation?
It didnt work with ForEach either but I got a different error
Efe is code gen as well
But yes you can't use generics in code gen
If you want to use generics you need to manually write the jobs
You mean IJobChunk?
Yes
Thats sad. Just wanted to create a simple reactive framework to avoid all the boilerplate code
But if that means having to write every system that uses it with IJobChunk I am not sure if I will gain anything from it
IJC isn't that bad in terms of boilerplate. If unity comes out with a SysAPI to get and update type handles, I would say it's equivalent, possibly superior, to IJE.
Sooo each chunk is 16 KB big... Archetypes do store them basically in some sort of linked list... so chunks are most likely not next to each other in memory, means that if our chunks do not contain many entities... its slower since theres more memory jumping required.
In that case, how do we deal with large entities ? Imagine something like this...
Character
- Identity{ UniqueId, name, type }
- Stats{ level, attack, defence, magicAttack, magicDefence, maxHealth, luck, agility, ... }
- Transform
- Rotation
- Mesh
- Health
- Velocity
- Collider
- Inventory
- Equipment
- AOI
- AnimationPlaying
...
As you can see the list grows and grows... and such an entity is pretty big, lets just guess we could only fit like 50 into one chunk. However there like ten thousands of them crawling around the world, so we have like hundreds or thousands of chunks.
This way the performance becomes worse since there a lot of chunks and a lot of chunk switching...
So how do we deal with such massive entities ? What are common techniques ?
lets just guess we could only fit like 50 into one chunk.
that's optimistic with that type of structure
i'd estimate you'd end up with just 5-10/chunk, or less, based off experience
i can tell you in a work project we have 2-3 players per chunk, 5-6 normal creatures
and this is what happens when you don't think about/pay attention to this problem
so ah good you're hopefully do this ahead of time!
If you use unity's ECS packages (physics, rendering, netcode), it's about 25 entities per chunk with no custom components.
Most likely :/
Of course we can outsource some of that data since there a few things which are not unique to each entity. Like the stats, those are allways the same for a group of entities... like each default character has the same attack, defence, maxHealth. So we could store that somewhere else and reference it.
However Most of the stuff actually can not be outsourced... inventory is unique per character... also the equipment attached. Transform/Rotation is also unique... aswell as the current animation, the current health, the mesh being used and and and...
So is the only way here to accept that this becomes slow by design ? ๐
I mean, it's not that slow. You're not gonna see 3ms per 100,000 entities levels of speed but you'll have a comfortable 60fps.
your only solution is to really break up each entity into smaller entities
Or fragmenting entities and storing references in a off-chunk buffer component element (a buffer with internal buffer capacity set to 0).
for example, the stat/effect library i'm super obsessed with all your stats (health, % damage increase, gravity, turn speed) are stored in a single buffer and are written to player from individual effect entities
so every stat in the game is just 16 bytes per entity in the archetype
(i've tested this at 100million stats on 10million targets at 20ms/frame)
(memory is much more of a problem at this extreme ^_^' 32GB min machine requirement no other feature in game)
Ah i see... that kinda makes sense ^^ however this is also kinda a dependency nightmare ๐
Im working heavily with custom networking... and such a structure would mean that i also need to synchronise effect entities with the client/server, which is again more work... and you always need to have those in mind aswell ๐
Nice, finally a stat effect simulator ๐
however this is also kinda a dependency nightmare
๐ฏ
i had to plan this carefully
and wrote a very clearly defined life cycle management solution
as well as a way to cache chunk references safely for fast lookups
for something less extreme but more flexible / less strict, would interlocked operations work?
i also need to synchronise effect entities with the client/server, which is again more work
yeah already planned this out
most effects dont need synchronization
like effects are, a sword has 6 stats
these stats dont need to be synced to client
just the effect of the stats do
things like buffs/auras etc existing need to sync to apply visuals
oh i just do direct pointer writing
it's more about when a target/effect is destroyed
it might reference something that doesn't exist
i have no actual safety checks in this entire library (hascomponent/exists etc)
and i dont think any lookups either, at least not for regular frame operations
they're fine, i just wanted to push to extreme
Ah, hrm.
Oh boy that sounds like a lot of fun ๐
Easiest way is to force the chip manufactures to implement like 5mb L1 Caches so that the chunk size can be increased ๐
Nah, chunk sizes seems to be dictated by enabled component bitmasks.
v128 is used for enabled state. Why they didnt use v256 is beyond me.
{
[NativeDisableUnsafePtrRestriction]
internal StatEffect* Effect;
}```
effect entity has this
``` /// <summary> The buffer sits on the owner and can be directly written from stat entities via <see cref="StatEffectApplication"/>. </summary>
[InternalBufferCapacity(0)]
[ChunkSerializable]
public unsafe struct StatValueBuffer : IBufferElementData
{
[NativeDisableUnsafePtrRestriction]
internal StatEffect* Effect;
}```
whatever has stats has this
i.e. they share a pointer
so i can just write the stat directly
on change the thing that has the stats iterates the StatValueBuffer and calculates the actual stats
Do you have the stats on the entity or are they stored in a NA somewhere?
Oh wait stat is it's own entity?
yeah effect is its own entity
effects are condition -> action
ugh, eww
action can be, add stat, create effect, enable capability
can have up to 8 conditions
conditions can be, low health, nighttime, on block etc
the final stat buffer is stored on the actual target
public struct Stat : IBufferElementData
{
public float Value;```
simply a float buffer
value is calculated from all StatValueBuffer
the index in the buffer is the stat key
all stats always exist on all entities that can have a stat
even at 500 stats i'm ok with this memory cost
for the performance benefit
if memory is too problematic though i'll just switch to my IDynamicHashMap
A hash map on an entity? I always wanted one.
here you go then
basically just a wrapper for DynamicBuffer<byte> which is reinterpreted into a hashmap
Yea, fantastic. I'll need to go back to my drawing board and see how I can use it.
the pain line is htis
hashMapBuffer.AsHashMap<TestHashMap, int, byte>();
c# limitation on generics and i can't figure out how to remove the need for this explicit generics
i would really like it to just be
hashMapBuffer.AsHashMap()
compiler not smart enough
Same way native array does it?
Or is that extension limitation?
public static DynamicHashMap<TKey, TValue> AsHashMap<TBuffer, TKey, TValue>(this DynamicBuffer<TBuffer> buffer) where TBuffer : unmanaged, IDynamicHashMap<TKey, TValue> where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged
even though TBuffer defines TKey, Value
the compiler can't figure it out without you specifying the generics yourself
always bothered me
i assume it's because of inheritance
but with unmanaged if you specify a TBuffer type there is only 1 possibility as far as i'm aware
Yea, if a type satisfies the unmanaged check, all subsequent types should also be unmanaged. Maybe the TKey : IEquatable is causing the compiler to request all types?
nah even without that it still requires <>
Can I somehow get an entity reference inside of this foreach or do I have to do some weird dots voodoo magic to be able to destroy the entities I want?
.Query<>().WithEntityAccess()
Not gonna lie, I was not expecting it to be that easy
Older ways to generate meshes(which were much simpler to use) do not work anymore at least i do not know how to do it that way - seems now only way is using RenderMeshUtility
I think that would work without generics only if it's part of original type
try
I don't have DynamicHashMap class ๐ค
you can create a very simple test case
I don't know how to declare collections ๐
Can you give me blank example?
hold up
or not?
I can see how it can be done without generics
but it has to be part of DynamicBuffer I think
which is probably not smth you want
or maybe of DynamicHashMap
Has anyone been able to get skinned meshes to work (SkinMatrix) as an ECS component 1.0?
Edit: Problem was my shaders didnt use the "Compute Deformation" node in the shader graph
what do you mean declare collections?
there are no collections here
this is just a reinterpretation of a dynamicbuffer into a hashmap
public struct Kek<T0, T1> where T0 : unmanaged where T1 : unmanaged
{
public static Kek<T0, T1> AsKek(DynamicBuffer<Kek<T0, T1>> lul)
{
return default;
}
}
here
No stupid generics
but this doesn't help at all?
DynamicBuffer<Kek<T0, T1>>
try add this to an entity
where T0 : unmanaged where T1 : unmanaged
{
public byte Value;
public static Kek<T0, T1> AsKek(DynamicBuffer<Kek<T0, T1>> lul)
{
return default;
}
}```
all i'd be getting back is a single byte not a hashmap
๐ฅด
apart from that
public struct Kek<T0, T1> : IBufferElement
generic components aren't even allowed without attribute registering which is a no go unfortunately
System.ArgumentException : Unknown Type:`BovineLabs.Effects.Tests.Effects.KekTest+Kek`2[System.Int32,System.Int32]` All ComponentType must be known at compile time. For generic components, each concrete type must be registered with [RegisterGenericComponentType].
Hey folks.. just doing some initial testing piping the unity nav stuff through dots.. i have a landscape mesh that's roughly 1k width and 1k length, not too dense:
it's taking a few seconds to bake this - should i expect faster or does that seem about right? ( with or without dots obviously )
My next question was, it's also taking a few seconds to build when i add a building to the map at runtime, almost as if it's rebuilding the entire landscape mesh again.. this is my prototype update code:
if your navbounds is the entire map
yeah it will rebuild the entire map
wait hmm maybe that's not true
been a while
you need your build sources list to be the same order
bare minimum
it hashes and only updates new/things out of order
yeah that's why i added the conditional to check if the source list already contains the mesh at the same position
so the source list should be:
Initial Build -
0 : landscape mesh
After placing building -
0 : landscape mesh
1 : building block mesh1
2 : building block mesh2
..etc..
tbf, it's parsing meshes not colliders, and there are around 200 meshes ( kinda 'building blocks' ) in the building
but it's taking an equally long time to build after placing the building as it does for the initial landscape build
But yeah for that size seems about right
For a fresh build
Just have to figure out how to partial update
yeah, i think the update async isn't partially building, trying to debug that now
for IJobEntity, how do attributes prioritize when using a query for scheduling? I.E if I have [WithAll(T)] but my query I schedule with does not, what happens? Also how should I reason about which one to pick?
I suppose that the attributes are added on top of the query? At least that's how I understand it reading the docs
if you use query argument
then I think attribute query options won't work
you should just check codegened result
For a typical Entity.ForEach I can use a field on my system that's a managed type. But in IJobEntity I'm not allowed to pass any managed types even if the job is intended to run main-thread only. Is there a workaround for this issue?
Trying to convert a ForEach in to a IJobEntity and it suddenly became very hard because of this limitation
yes
.RunByRef()
this way you can have managed fields in job struct
Do I need to put something on my Job? It still complains about the job itself: error SGJE0009: ... Job contains non-value type fields.
Oh wait, this only works for IJobEntityBatch right?
Well - First question - why do you want a managed field on an IJE to begin? :3
IJE sometimes more convinient than query
besides, allows you to do abstracted execution
tested in both 2021.3 and 2020.3 and still the same
basically, when i just let it build that initial landscape mesh, so it adds only that to the list, and remove the 'requires singleton' to allow the gather/bake system to run continually, it seems to be rebaking the landscape each time
SystemAPI.Query should solve that in most cases tho? I mean, it doesn't currently allow for DRY but we're aware of that 
somehow it's not hashing the list as 'same as before' and doing a partial rebuild
In this exact case I'm making a job to start loading assets, it's done through addressables and as a consequence of loading I get a handle back. Since I can't store the handle in a native container (it contain's an interface field) I am storing it in plain old Dictionary. But I can't use Dictionary in IJE since it's managed.
I currently have this implemented in EForEach but I'd prefer to migrate it to IJE to future proof it (on v0.51.1 atm), planning to upgrade to 1.0
Perhaps I should just make this in to a function call instead? I'm not entirely sure how to approach this case
It's Main Thread only and non-burstable because of API usage
It seems this case is best suited for just any old function call / you could likely write a simple query.ToXXX to solve your needs :3
https://forum.unity.com/threads/how-to-sort-a-nativelist-which-is-used-in-a-previous-job.1362064/
Hiya; more job system related. I'm wondering how i can sort a list, that is also used in a previous IJobFilter. Anyone have experience with this?
I have a list of indices i'm filtering, and after that i would like to sort them. Something like:
void OnEnable()
{
var rng = new...
Feels like the SortJob should use IDefer?
I think it's because you use filtering you are updating the list's length thus the sortJob goes wonky
Yes, but normally you use AsDeferredArray for that. And for example i can use two filter jobs after eachother
mmm yeah I always use deferredArray but never did that particular sequence of jobs
Hi guys, Does anyone here know how to check a entity have an IEnableableComponent(including disable)?
var indSort = indices.SortJob();
var handle = new FilterOdd().ScheduleFilter(indices, 32);
handle = indSort.Schedule(handle);```
Thanks! It does work!
I just dont understand why, whats the difference between what i did?
var handle = new FilterOdd().ScheduleFilter(indices, 32);
handle = indices.SortJob().Schedule(handle);
Is it the safety system that 'sees' indices is read after the FilteroOddJob, and you move it before. But how
any of this is IJE?
FilterOdd is an example, and uses IJobParallelForFilter
I dont know what you mean with IJE
IJobEntity
No sorry im not using ECS per se, just the job system. Still thought this would be the most correct channel
it is
Sort job is an extension method of NativeArray/List that reads from the container. Once you schedule a job using a NativeContainer, you can not read or write from it from the main thread except for more scheduling. So to schedule a sort job after another job completes, you need to first create the job that sorts the NA/L then schedule it after. See if there's a ScheduleByRef() and use that for the sort job, otherwise you're good.
I am trying to build a system that spawns entities on destruction of another entity.
Sounds simple but I am a bit stuck. I tried using SystemStateComponents.
The system correctly triggers when the entity is destroyed but I have no chance of getting its position to spawn the entities at because the LTW component has already been destroyed.
Is there any good way, besides constantly updating my state component with the position, to handle that?
you could use a pipeline for destruction using some DestroyTag
which will remove entities in the end
so in order to get extended behaviour you just UpdateBefore destruction system
I thought about that. The problem is the entity is a child of the main entity (enemy). So I would have to add that tag to the whole linked entity group or constantly check the parent entity for the tag ๐
you can achieve that behaviour in destruction pipeline
just before destroying entity check whether it has Parent component
and maybe some kind of
Hierarchy entity tag
which would indicate that destroying children equals destroying whole hierarchy
So you mean the system would run on the parent entity?
no
it triggers of DestroyTag
but before destroying entity you can check whether it has Parent component
oh you mean I should then just add the tag to all its children too?
no
let's say it this way
foreach entity with destroy tag
{
if (em.TryGetComponent<Parent>(entity, out var parent)){
toDestroyToo.Add(parent.value);
}
}
yeah I guess I see what you mean
but the problem is the parent is the one getting actively destroyed but the child is the one with the ability
atm the parent get destroyed and destroys all of its linked entities with it
but the linked entity does not have a clue that its about to get destroyed
It could only know if I would add the DestroyTag to the parent and all its linked entities if it dies
the purpose of having a separate entity for the ability was to avoid overloading the root entitiy with components
but it's just a tag
but that would create a separate archetype for each enemy with a different ability
so instead of having the movement code iterate over one chunk it would have to iterate over 1 chunk per enemy ability combination
that would be ok. but what would that change?
because then
you can iterate over all destroy tag + ability holder
knowing that it has somewhere ability entity in hierarchy
but right now thats the only ability that triggers on destruction. so basically it would need a HasTriggerOnDestructionAbilityTag which is pretty close to having a tag per Ability again
why can't you do with just having 1 tag per all?
after querying for DestroyTag and AbilityHolder and getting the ability entity how would I execute the ability?
didn't you just want to spawn entity into it?
just do that spawn
and let system loop do it on next run
The Ability entity has a SpawnOnDeath component which should spawn the specified prefab:
public struct SpawnOnDeath : IComponentData
{
public Entity Prefab;
public int Count;
}
But this could also be sth like ExplodeOnDeath
So the tag wont tell me what kind of ability to trigger
does it need to?
Just make a spawn on death of entity
and that entity will do it's job itself
you can have instead a buffer
DynamicBuffer<SpawnOnDeath>
Oh so you mean the AbilityHolder should instantiate an AbilityPrefab which just does its stuff when it exists?
yeah
ok now I got it ๐
I guess thats a good approach for the OnDeath abilities. But there are a lot of other abilities which e.g. should run each frame
it's the way ECS works
event entities
and etc
code execution can be delayed by 1 frame
but absolutely no blocking
for maximum CPU cache efficiency
yeah thx for the input I will think about it
Cool.
error SGICE002: Seeing this error indicates a bug in the dots compiler. We'd appreciate a bug report (About->Report a Bug...). Thnx! <3 System.NullReferenceException: Object reference not set to an instance of an object.
0.51?
Yes.
I fixed some of the missing usings in my code and it's gone now.
Yea, unity largely removed that error in 1.0 at least. More bugs with baking though.
Hope you're filing those as you run into them
guys, does rendering static meshes using entities will be more efficent than rendering them as gameobjects?
yes, although the workflow has to allow for it. (can't make 1 million unique meshes with different textures more efficient) - aaand, there's quite the bug right now with performance of the dots renderer that is fixed in b15
kk, thanks for letting me know!
I am rather thinking about rendering some foliage, although I assume that the vertex animation isn't supported by now, right?
i guess you'd do that with shadergraph? and that is supported
I waited 30 minutes for the Rival Online FPS sample to build and it segfaults when I click "Host Game."
:/
I guess I should try disabling "Graphics Jobs": https://forum.unity.com/threads/segmentation-fault-core-dumped-in-standalone-app-but-not-in-editor.1226610/#post-7819407.
Hello,
My game is closing abruptly with only a "segmentation fault (core dumped)" error in console, no errors in Player.log, and it only happens in...
There aren't any errors in the player logs.
Still segfaults.
I guess I'm not allowed to play with an up-to-date DOTS sample game.
@covert lagoon Are you building it using the buildconfig asset in the project? ( https://philsa.github.io/rival-doc/Samples/OnlineFPSSample/hosting-connecting.html )
And what unity version?
This is a stretch but has anyone managed to get ComputeBuffer BeginWrite or the GraphicsBuffer version to work?
I can get BeginWrite to actually communicate data to the GPU but whenever I have rendering take a while, concurrent CPU writing and GPU reading causes a lot of flickering. Has anyone managed to "fence" rendering until CPU writing is completed?
A single post by the rendering guys who made BatchRenderingGroup say how they sync writing using an AsyncReadbackRequest but I want rendering to occur after a system in PresentationGroup to finish writing since the results in that produce updated values.
And I dont want to use a rotating double buffer (which didnt work anyways)
Can you not use a Mutex or some sort of lock for this purpose?
It's GPU - CPU race conditions. Mutex and locks are CPU only.
I mean, there is a locking writing version, called SetData, which is very slow (relatively) and mainthread only.
I'm using it now and it works but I spent 8 hours today trying to get BeginWrite to work and it didnt.
What exactly are you writing to that is used by both CPU and GPU?
since that seems to be the problem. Its hard to synchronize writing if done by 2 separate cores with limited communication
ComputeBuffer, a structured buffer on the shader side.
I guess i mean, why do both CPU and GPU need to write to it? Why are you unable to just use the GPU for the buffer
I am trying to transfer data from the CPU to the GPU. By writing to this ComputeBuffer, I am transferring data from the CPU to the GPU.
Basically I have object positions in the CPU on Entities that I am transferring to the GPU for custom rendering. I want to do it fast but due to long rendering times on the GPU, the GPU rendering overlaps with the CPU writing job. When that happens, a race condition occurs and the screen flickers.
Oh you mean the GPU is reading from the buffer before the CPU finishes writing to it
Yea.
I thought you meant that both the GPU and CPU were writing to it. Which is a race condition.
What you described isnt technically a race condition i dont think
It is because since the writing is not guaranteed to be in a set order (rearranges every frame) so if you read from the buffer and halfway through the write job overwrites it, the rendering breaks.
That is an interesting problem....
I suppose ComputeBuffer.EndWrite isnt for signaling that the buffer can be read then
No, it's very low level. Exposes basically the raw memory if possible. You dont even need to use EndWrite
Right. And a rotating buffer didn't work? I know that is often used in order to help with rendering frames faster
basically you would need to delay your writes until you know the frame is complete
No. I had the CPU job write to a "future' buffer and the GPU read from a "past" buffer but that didnt seem to work.
The same flickering happened. And I know the CPU job is fine because if I use SetData() with identical output results, rendering works flawlessly
How many different sections are writing to this buffer. Can you just have a counting semaphore that locks next frame writes until all from the previous frame complete?
Something like how C# has Task.WhenAll?
That's the problem. There's no way to tell if the GPU finished rendering the previous frame. That would fix the issue.
But you can tell when you start writing your next frame. And that is your timelimit
So currently we keep track of where the GPU is using a tiny AsyncReadback per frame. It's certainly not nice but currently there is no exposed API to keep track of what frame is done on the GPU.
That's from the batchrenderinggroup team, aka hybrid renderer.
The way I see it you either
A. Have a job(s) each frame that write to the buffer, and you cant start the next frame's job until the previous completes
B. Any previous writes are immediately canceled when the next frame wants to write to the buffer
GPU Execution overlaps with Systems, which is where the compute buffer data is being updated.
Oh i see what you mean, you cant time GPU execution with systems so you have no idea when the GPU reads from the buffer, which is a race condition
And oddly no, placing the BeginWrite data upload inside the Rendering block (which I am 99% sure that it's always following completion of GPU execution) doesnt fix the problem of rendering flicking.
if thats the case, a double buffer should work then
since you switch it out per frame
or i think a triple buffer is used normally
This is what I'm doing now, which works. Reading arrays from Systems and uploading using SetData
I've tried something like a double buffer that cycles. Didnt work.
My initial reaction is that you are implementing it wrong somehow.
Based on the timeline you shared, I think you either have to find a way to prevent overlap between your buffer writing and GPU reading.
Or you use multiple buffers so that you dont write to the buffer you are reading in the same frame.
And this is all that I'm doing to calculate these arrays. Basically a simple circle distance culling.
i dont think using set buffer would work though since you are just replacing the buffer during the reads which results in the same problem.
I think you need multiple buffers on the GPU side, though i dont know what that woudl look like
I thought so as well so I placed this writing CPU system to be manually updated inside the Rendering block, where it is guaranteed to not be overlapping with a GPU reading segment. But the flickering still occurred.
That's the thing, ComputeBuffer.SetData() does work.
Almost certainly a sync issue then, cause it looks like SetData() does wait for GPU sync to work
whereas StartWrite explicitly states that no CPU-GPU Sync occurs
which i know you already mentioned but wanted to be sure
Yea. And when I reduce the rendering costs (remove 90% of the rendered objects), no flickering because GPU finishes before a new CPU write happens.
I mean, theoretically possible? Havent tried not resetting the interlocked counter
I assume you don't have any custom processing of light in your shaders
Objectively, SetData functions fine. There is minimal performance cost (sub 0.05ms) on the profiler to upload position data. The reason why i want to use BeginWrite is to remove the redundant 262KB NativeArrays required to collect the position data that is just immediately uploaded.
like you are just using URP/Lit or something?
This is a fully custom light rendering system. My own renderer
So you also have custom shaders to process lightmaps? OR just using standard lightmap structs and passing them to shaders
Fully custom, i'm sending in float4s (XY is position, Z is light radius, W is light color).
As in I have 8 shaders and 12 draw calls to render my own lighting:
So I know 100% what's going on behind the scenes down to the individual pixel values. Because I wrote it myself.
Wow. Nice
As I see it, having these artifacts will always be a risk of not forcing CPU-GPU sync, and using SetData seems like the easiest way to enforce that sync (not sure if cheapest)
Implementing some sort of double/triple buffer would work, but I don't know how to properly implement that in Unity (unity does it automatically? I dont know how that wokrs though). Of course having 2 buffers for light frame data would have worked if you could update the data outside of the GPU buffer read, but you said you couldn't get that to work
Yea, but that comes with an additional cost of even more memory being used. Memory is cheap but adding rotating buffers adds up quickly
right. At the end of the day its either a processing/memory cost.
If you cant get all the writing (processing) done before GPU reads start, you need more memory to compensate
Thinking about it, shouldn't SetData lead to frame loss since you have to wait for sync before moving data to the GPU?
Honestly, I have no clue what it does.
It works and doesnt seem to have an impact on timing either.
My initial guess would be that it saves data in a separate array that gets pushed into the GPU during a safe/sync point
This may be exactly what you want anyways
Which i guess technically is a 2nd buffer it thats how it works
Yea. I wanted to write directly to that separate data without an intermediate NativeArray.
So ideally you get the code for how SetData syncs with the GPU and use that to write data safely
It's an internal engine API (set data is just an exposed Extern function) so I'll need to find a C++ decompiler and see how it works.
https://github.com/Unity-Technologies/UnityCsReference has the C# API, which is easily available in any IDE. The C++ side, not so much.
Is copying the data once that big of an issue, or does it have to copy for every shader?
Just once. It's not an issue in terms of performance but these intermediate buffers are a quarter of a MB each (242KB) and the majority of it is not used.
This feels like the type of problem thats both really big and really small. If your entire lighting setup only ever requires an extra persistent 242KB of RAM, that sounds small. But in games with a small footprint that can be really significant
Ehhh, this game is using the full suite of DOTS netcode, physics, and support up to 8192 (small) lights simultaneously. So it's not a small game and a quarter MB isnt much when the fluid sim portion takes up 4GB of floats so... eh
But every tiny bit helps. A bit of optimization here, some there, and I can halve the costs
Whatever you think works based on my (limited) experience working with OpenGL and shaders directly. I think the trade off of using SetData is worth it. You might be able to make the buffer smaller if you wrote your own GPU sync code, but thats the only benefit i see.
It might be worth looking into just to learn how to sync with GPU data though.
Which comes back to my original question, how can I do that? How can I initialize a "fence" that synchronizes GPU and CPU?
There's CreateAsyncFence which just synchronizes GPU threads and of course the various mutex and locking abilities on CPU but none that cross between.
what about CommandBuffer.WaitOnAsyncGraphicsFence?
That's the gpu fence I'm talking about. It synchronizes GPU threads to execute only after the inputted graphics fence is passed. And those fences are formed following the execution of a GPU draw call or dispatch.
on the topic of performance, do you know A good way of moving Persistent data into the ECS ecosystem?
I've been looking into using a Baker to create Blob assets, but It's still hard to find info on best practices, can the Baker seems to act at runtime for loaded scenes, which is not ideal if the blob asset requires processing to create
Yea, blobs are what you want. What's wrong with blobs?
The baker only runs in the editor. It generate bytecode that is the "cached" version of subscenes containing pure entities data.
Nothing is wrong with blobs or the baker. Its just not completely clear
All subscenes do at runtime is read from that chunk of cached data and immediately translates it into entities. Very fast, no monobehaviors or GOs at runtime if you're going full ECS
Got any examples of data you want converted to blobs?
Right now I'm working on creating a simple workflow for Skinnedmesh animations in ECS, since Unity hasn't released their package yet
So I'm creating a baker that bakes AnimationClips into something ECS readable for SkinMatrix components
vertex animated textures?
Can't you just use shaders for vertex animated textures?
Hrm. Honestly, I would recommend not touching animations ATM. Unlike all the 2D custom stuff I'm doing, unity will come out with their own DOTS animation workflow so anything you do now might get invalidated in a year or so.
Ugh but I dont want to wait a year
You are right though
Thats why I wanted a minimal setup, just to make sure it works
A year passes quick. It felt like just yesterday I was slogging through IJobEntityBatch in 0.17 and trying to convert everything to ISystem.
Yeah. This reminds me of waiting for Jetpack Compose all over again
Great library for making android apps!
Now if only they had a better Dependency Injection system....
Here's a guide using hybrid components https://www.youtube.com/watch?v=vs6h4waQpPA
Apparently Rival from Phil (commented above) has a animation system bundled with it as well
I need to up my searching game. This is great!
Rival seems to be fully DOTS and free. The source isnt googlable but if you install the package, you can probably just traverse the package and find how he does animations.
Rival is officially supported by Unity themselves so I recommend digging through his package as that is probably Unity verified good code.
I've looked though some Unity code so I don't think that necessarily makes it quality. ๐
Ehhhh, unity code is corporate code.
What, it's written in COBOL?
Actually hip, happening corporations probably write in F# or Go or something
Yes, although I changed it a bit.
I am using Unity 2021.3.13f1.
I only changed this:
Platform: Linux
Configuration: Release
Scripting Backend: IL2CPP
IL2CPP Compiler Configuration: Release
I found a message I sent earlier this year: <#๐ปโunity-talk message>.
I guess I should try removing TextMeshPro.
Does TextMeshPro not mix well with Entities in Linux builds for some reason?
Hiya; im quite stuck with sorting a list that has been filtered.
The steps are as follows:
- Make a list with indices 0..8
- Filter out everything that is odd
- SortJob
However i'm noticing my sortJob gets the indices pre-filtering, eventhough its called on that List. I even added sync points and i see in the debugger that my list is correct the moment i schedule the sort.
void OnEnable()
{
NativeList<int> indices = new NativeList<int>(10, Allocator.TempJob);
for (int i = 0; i < 8; i++)
indices.Add(i);
Debug.Log($"Start indices: {string.Join(',', indices.AsArray())}");
var sortJob = indices.SortJob(new Comparer());
JobHandle handle = default;
handle = new FilterOddJob().ScheduleFilter(indices, 32);
handle.Complete();
Debug.Log($"After filtering: {string.Join(',', indices.AsArray())}");
handle = sortJob.Schedule(handle);
handle.Complete();
indices.Dispose();
}
[BurstCompile]
struct FilterOddJob : IJobParallelForFilter
{
public bool Execute(int index) => index % 2 == 0;
}
struct Comparer : IComparer<int>
{
public int Compare(int x, int y)
{
Debug.Log($"Comparing {x} with {y}!");
return x.CompareTo(y);
}
}
To be clear; i dont understand why my sorting is done on odd numbers. I would expect, since the indices have been filtered, only to see comparing the even numbers.
Actually; i was struggling with something related yesterday and asked on the forums, that same person just predicted and answered my problem! https://forum.unity.com/threads/how-to-sort-a-nativelist-which-is-used-in-a-previous-job.1362064/#post-8591611
I have a list of indices i'm filtering, and after that i would like to sort them. Something like:
void OnEnable()
{
var rng = new...
No. It's written in Fortran.
That explains the high performance simulation code
@covert lagoon Have you tried building with IL2CPP in "development" mode, or building with Mono? If successful, it might help isolating the issue.
According to the thread you linked earlier, this sounds like an issue that happens with Linux + non-dev IL2CPP builds
has anyone actually been using the RenderMeshUtility.AddComponents with a RenderMesh with 1.0? Ive tried runtime and in a baking system and neither appear to work.
Only way ive actually been able to make it work is to copy an already converted entity's RenderMeshArray and use the RenderMeshArray version of AddComponents(or manually add every component), but that seems to defeat the purpose of the whole utility.
Just changing "Configuration" to "Develop" in the Classic Build Profile component as shown in the following screenshot did not help, but then also changing the scripting backend to Mono fixed it.
But when I try to close the window, the game dies without actually closing. The window stops being redrawn and both CPU and GPU usage drop to 0%.
Ok I killed it then launched it again and this time it closed properly.
Player-prev.log ends with this:
Setting up 4 worker threads for Enlighten.
Vulkan PSO: data extracted [new size=126144, old size=0, incomplete=0]
Vulkan PSO: Saved size[126144] path[/tmp/PhilippeStAmand/Rival_OnlineFPS_ClientServer/vulkan_pso_cache.bin] success=1 headerChanged=1 sizeChanged=1
malloc_consolidate(): unaligned fastbin chunk detected
Caught fatal signal - signo:6 code:-6 errno:0 addr:0x3e800004c5a
Is there a specific version of entities that I need to install depending on my unity version? I'm following up the official "Getting Started" guide but I only have error consoles no matter what I do
1.0-exp only works on Unity 2022 (2022.2.0b8 and later).
0.51 works on Unity 2020 (2020.3.30 and later) and Unity 2021 (2021.3.4 and later).
Just click the button to add a package by Git name in the package manager, type com.unity.entities, press Enter, and it should install the latest version that supports the version of Unity that you're using.
Yep that's exactly what I'm doing. I have Unity 2022.2.0b8 and installing entities exactly like that, but I'm getting errors from other packages like these:
Looks like the only thing I can do is remove all 2D but that's the project I wanted to make
Version 1.3.0 of com.unity.collections renamed NativeHashMap to NativeParallelHashMap: https://docs.unity3d.com/Packages/com.unity.collections@1.3/changelog/CHANGELOG.html#changed.
I guess com.unity.2d.animation depends on an older version of com.unity.collections than com.unity.entities, and the newer version on which com.unity.entities depends is being used.
But shouldn't you have a different error then?
One about the NativeHashMap type not being found.
But I can't find a version where .Count is not a method.
Im wondering if someone could help me understand when to use IJobEntity vs IJobChunk
IJE is just codegen which becomes IJobChunk
it's made for less boilerplate code
write some simple IJE and take a look at generated code
ok ty
No clue to be honest, I have been trying to play around with versions but no luck, I guess I need to wait for the 2d animation to be updated to start working with DOTS
seems this doesnt work : var rendMesh = EntityManager.GetSharedComponentManaged<RenderMesh>(meshEntity);
rendMesh.mesh.GetVertices(vertices); (vertices is list of Vector3) - so how we can get list of mesh vertices manipulate it and set it back to RenderMesh?
Firstly are you still on 0.51?
Secondly are you writing the verts back to the mesh?
its 1.0 - mesh and vertices are null even material is - it seems the only way is to use RenderMeshUtility destroy entity or remove RenderMesh and then create it again using AddComponents from RenderMeshUtility? Or is there an easier way?
oh thats because rendermesh isn't really what is used anymore in 1.0
seems the only way is creating it again and again like explained here : https://docs.unity3d.com/Packages/com.unity.entities.graphics@1.0/manual/runtime-entity-creation.html if we want procedural meshes(generated at runtime)? I also dont know how to copy list of vertices generated in prev frame...
i dont create my entities at runtime
for my procedural generation and i have infinite voxel terrain
There is also this RenderMeshArray component documents say it contains meshes ...
Yep this worked for me in order to change vertices from the code : Mesh mesh = rma.GetMesh(MaterialMeshInfo.FromRenderMeshArrayIndices(0, 0));mesh.GetVertices(vertices); vertices[0] = new Vector3(0,-100,0);
mesh.SetVertices(vertices); >>>> This is code in Entities.ForEach(simply changes value of 1 vertex) - but to be honest i dont know exactly what means this MaterialMeshInfo need to read more docs if they exist (rma is RenderMeshArray component(inside EFE), vertices is List<Vector3> from the main thread) - now i can at least read veritices and other mesh properties previously generated xD EDIT : seems that MaterialMeshInfo simply supplies indices for lists in RenderMeshArray(which contains Lists of Meshes and Materials which we set when creating entity explained in doc in my 2nd post above - look up) so we can get proper mesh / material we want to manipulate in our code ... EDIT2 : also read this interesting post and whole thread actually : https://forum.unity.com/threads/rendermesharray-getmesh-materialmeshinfo-returns-null-why.1359493/#post-8576641
renderMeshArray.GetMesh( materialMeshInfo ) returns null, why?
using UnityEngine;
using Unity.Entities;
using Unity.Rendering;
public partial class...
yes RenderMeshArray is what is used in 1.0
It is used by entities graphics in baking IIRC. From what I remember when looking at this before is that the RenderMeshArray version is for runtime and the RenderMesh version is for baking time. The name is bad and I think it will get renamed to reflect this
Hi everyone ! I'm currently designing a navmesh navigation system in DOTS 1.0 using NavMeshQuery.
I was wondering what would be less costly between these two option :
- having a single NavSystem & NavAgentComponent that handles both path Queries & part of the navigation state base (eg : RequireRouting, ComputingPath, GoingToDest, etc...)
- having 2 separate system NavQuerySystem & NavAgentSystem with 2 separate components NavQueryComponent & NavAgentComponent (possiblity to split NavQuerySystem into 3 subsystems StartQuery, UpdateQuery, EndQuery)
the NavQueryComponent would then need to be added only when the entities need to be computing a new path & removed upon completion. how expensive is it to add & remove components at runtime in system having design myself an ECS i know it's suppose to be the most expensive part of the ECS if it's archetype Based even though Unity has probably optimised the shit out of it.
Any thought ? thank you taking the time to read my post !
@vernal cypress there really is no difference in you splitting the logic up into multiple systems or not. you only get the systems overhead on mainthread once per system (which is not really significant). everything else performance wise depends on your actual logic.
whether adding and removing components is a good idea or not depends on how frequent you do this. since you shouldnt need to request a path every third frame it should be fine to add and remove a component to start pathfinding
i would advise to not overanalyze your problem performance wise at this point and just implement it the most simple way possible. ecs really shines with how easy it is to modify the architecture later on
for example switching between removing / adding and enabling /disabling components is really easy now
@solemn hollow Thank you for your insight ! Yeah I will try to prototype a working solution fast and refactor it later then
i am really interested in what you end up with. i am doing navmesh stuff myself atm. though more baking than the agent
Cool ! i'll keep you updated. feel free to share your progress with me aswell, i'm interested.
exactly what i'm doing atm.. tbh once you get it up and running you realise there's not much to it, the main difficulty is in deciding exactly how you're going to push the data around inside ecs but as Manarz suggests, get something up and running first and then look at streamlining/optimizing it
basic stupid question but how do I get data and write to it in an IjobEntity that isn't part of the main query
@honest plinth I spent yesterday testing this and couldnt get the RenderMesh version working during baking at all, only using RenderMeshArray would it render and still only with a subscene closed. docs for "runtime" creation definitely seem out of step with actual reality of what exists(feels like this area might still be undergoing changes?)
is ComponentDataFromEntity<>() the only way
ok cool thanks, I figured I'd check if there was a better way
you could technically get the chunks for another query on the main thread and stuff that data into the job if you were some kind of masochist
its kind of convaluted having to get the data and the entity then write backwards and forwards etc, but I guess its fine for now
Other option is possibly write to a native container and then transfer those values over in another job
Be interesting to see some comparisons, out of the handful of ways you could approach doing that common scenario, which ways are faster etc
that's why componentLookup has a ref option now.
CDFE, interim container, ecb, buffer etc
that's a good idea for the when I need to write lots of data, thanks, but this time its just one value so it should be fine
that's cool I was hoping they would get to simplifying things, but to bad I can't update
If it's just one value, I'd maybe pass in a NativeReference and then assign it where it needs to go afterwards
for 0.51 you can use my library where you can get refs or ptrs: https://github.com/enzi/Entities.Exposed/tree/9bd3cc55e2fbce520b88057cede52caf688c0632
that commit is compatible with 0.51
So if you have say one Health float for example to write, pass in a NativeReference<float>, write to it, then afterwards write that float to your target health. Rather than opening up a CDFE of every potential Health and passing that in
interesting, thanks, I'll have a look at that
ok, your right, that's an even better way, thanks a lot
is there an equivalent of GetComponentLookup() for SharedComponents? I want to look up an unmanaged SCD (just an int) for a random entity in an IJobEntity...
i have one if you need
it doesn't do exactly what you want, returns it from shared index
This might be a dumb question, but what's the intended way of ordering OnCreate calls when using ISystem's? In my case, I just want to make sure that one system runs before the others (the first system creates a singleton with a list and the second/third/etc. adds some static data into it). It seems like I could just use blind calls to World.GetOrCreateSystem from the subsequent/dependent systems? But surely there's a better way? I see a lot of people creating the singletons in self-disabling/ordered OnUpdate or in Baking but that doesn't seem ideal to me for this use-case?
Without singletons this could presumably be done by using system state. But I'm a bit nervous about that since the only way to then add to the state would be via the managed route with GetOrCreateSystemManaged.
https://gitlab.com/tertle/com.bovinelabs.core/-/blob/0.9/BovineLabs.Core/Iterators/SharedComponentLookup.cs
there you go, wrote a new version to get shared component data from entity
ideally creation order shouldn't matter imo
and i strictly try to avoid this
but in 1.0 there's a new [Create(Before|After)] attribute
/// Apply to a system to specify a creation ordering constraint with another system in the same <see cref="ComponentSystemGroup"/>.
/// </summary>
/// <remarks>Create before or after a system constrains the creation order of these systems when initializing a default world.
/// System destruction order is defined as the reverse of creation order.</remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
public class CreateBeforeAttribute : Attribute, ISystemOrderAttribute```
if you must order them
Baking but that doesn't seem ideal to me for this use-case
adds some static data into it
IMO baking seems ideal for your use case
By which you mean baking the singleton? Because baking happens before system creation, right?
well yes
but the entity wont exist until after system creation
due to having to load from subscene
unless you manually control the subscene/system creation ordering
I'm not sure I understand. If I did that, and the singleton entity didn't exist until after system creation, I wouldn't be able to add to the singleton's list in the second system's OnCreate function?
well the question is really
why do you need it in oncreate
that kind of determines what is required
Sure - my goal here is to give the second system a handle to a value that's continuously computed by the first system. That relationship is set up on system creation and the computing is based on a small set of configuration data that's passed in and added to this list. So it would make sense that that handle would go in the second system's state on creation, I'd think.
For example, the type of the output value (the computed data) is one of a few different options. I'd like to return a strongly-typed handle for that.
Doing all of this in OnUpdate just seems like it's probably... too late? Or at least would be pretty complicated.
What's the problem with just calling SystemAPI.GetSingleton<MyData>() in OnUpdate in the second system?
This is a library, so MyData wouldn't have a member for the computed data you're looking for. Hence the handle instead.
Sorry - I misunderstood you. MyData or some other singleton in the application would probably hold the handle. Or they could hold it in system state. I don't really care. But where does the handle come from? I was planning on returning it as part of a call they make from OnCreate.
in OnCreate of System1, it creates a singleton and puts the data on it
then any other system (System2) can read it whenever it needs
anyway that doesn't really solve the whole baking in time thing, that'd require setting it up in OnStartRunning etc
and the attribute approach i mentioned above would solve your problem anyway if that's the way you want to do it
(i got to bounce)
Yeah, I think the attribute would probably work. My situation's kinda complicated. Thanks for the help!
@rotund token your SCL is pretty awesome! Thanks for the tip ๐
@rotund token entityManager.GetCheckedEntityDataAccess() <-- where can I find this?
[0.51] How do I use ComponentSystemBase.GetComponentTypeHandle with a component type inheriting from Unity.NetCode.ICommandData?
Hi guys, I have spent three days already on this, so I hope to find answers here. In my project, I'm using DOTS [1.0.0-exp.12] with Netcode for Entities [1.0.0-exp.13]. My issue is straightforward, and I need help understanding how it can be solved. I'm working on the Menu to Game transition. I have a managed script storing all prefabs and baking them into an entity. This script is in subscene (in a prefab) and has GhostComponent assigned, which means it is spawned in the Default World when the user launches the game. So it is not in "InGame" status, and Client/Server worlds don't exist yet. (tbh, I don't like this solution, and I would like to load the sub-scene instead when I host the game, but it seems it is impossible now). Later I'm trying to host the game, so I create Server and Client worlds, move to "InGame" status, and I need to access the prefabs now. I want to spawn a prefab in the multiplayer. The problem is in querying the entity with prefabs. It is listed only in the Default world, and I cannot access it in the Server world. On the Unity forum, I have found a note that the pre-spawned-ghosted entities should be spawned automatically when you enter the multiplayer, but this is not happening. They are all listed under the Disabled tag, and they are not in Server/Client world. How do you store your prefabs before you go into a multiplayer mode, and how do you simultaneously make them accessible for server and client? Thank you very much for any tip/directions. I'm losing my hair on this.
Have you assigned the command target component on the network entity on both the client and server? I had a similar problem and you must do the assignment on both worlds for everything to properly connect
You need internal access to the Entities package
You can see how I guess access here : https://gitlab.com/tertle/com.bovinelabs.core/-/tree/0.9/BovineLabs.Core/Internal/Entities
Without needing to change the package
Emm, I'm creating the entity before the client and server worlds exists. So I cannot update the CommandTargetComponent yet. It sounds like in your scenario the entity was somehow created in the other worlds? I'm actually thinking about copying the entity to both worlds and disable it in the main world, but I cannot query it because it is already disabled from GhostComponent.
Always spawn networked entities (entities with synchronized components) on the server and the client will spawn automagically
So the NetworkIDComponent must have the NetworkStreamInGame component added by you in the code.
Both on the client and server
Well, I see your point but how can I access the entity from the default world? Sounds like I need to remove the GhostComponent, (move it) from the default world and reconstruct the GhostComponent on the ServerWorld, or instantiate it somehow.
seems like b16 is the last version before 2022.2 release
Default world? The default world shouldnt be used when you're using netcode.
1.0 pre dots when?
are the annoying asset database problems fixed? still on b9
nope, possibly gotten worse. I basically close the editor whenever I'm editing code then reopen when I need to test and close when Im done
damn, are you on b16?
https://github.com/Unity-Technologies/DOTS-training-samples/blob/dots-training-2022-11-na-group1/Ported/Mazombie/Mazombie/Packages/manifest.json
Unity internal is still on 1.0 exp.14. So actually using the "current" release.
Well, I was saying at the main post, this entity exists before NetCode starts. The user click host / connect button and that will create ServerWorld and ClientWorld. They call it "Prespawned ghosts" at netcode documentation. It has two rules:
- With regard to using subscenes, when placing an object in a subscene, you no longer place the ConvertToClientServerEntity component on it as being in a subscene implies conversion to an Entity. Also, it means the option of making an entity only appear on the client or server is now missing. Prespawned ghosts always appear on both client and server as they are just like a normal spawned ghost, and will always be synchronized (as configured) after the game starts.
- Loading a new subscene with prespawned ghosts after starting (entering the game) is currently not supported.
I'm loading the subscene with prespawned ghost before starting (enterting the game) so it should be supported
Yea
This is my creation bootstrap script. Ignition() is called when start client/server is pressed.
My SceneManager, which is a core unity feature using full scenes not subscenes contains the subscenes and entities for gameplay.
And yes, that scene has prespawned ghosts in subscenes that are mirrored on client and server with proper sync
This is my current scene distribution
And of course the things that need to be networked as well
I just press the unload so it leaves only the launcher scene active
And when starting up server/client, i make sure to load SampleScene (the main scene) before starting the worlds and everything works
Weird, I have it almost the same, but it seems it is working for you. In my case the "Samples/SampleScene" contains SubScene where is placed my baker script that has attached GhostComponent. So you have defacto my scenario (where you have loaded scene before entering the network mode). I will have to recheck my bootstraper.
Make sure your prespawned networked entities are prefabs with the ghost authoring component on it:
They are, I was checking it 10 times. I had it on my mind too.
Thank you for sharing the screenshots. It makes me sure about that I'm on the right track.
i think something important was fixed around ~b12 can't remember what
some point up to b14 they fixed il2cpp
but yeah still getting corrupted subscenes in b14, haven't tried the newer ones just yet