Beispiel #1
0
        protected override void OnUpdate()
        {
#if UNITY_EDITOR // Live edit
            if (EditorApplication.isPlaying && m_Version != LastVersion)
            {
                m_Version = LastVersion;
                foreach (var contextsValue in m_Contexts.Values)
                {
                    contextsValue?.Dispose();
                }
                m_Contexts.Clear();
                EntityManager.RemoveComponent <ScriptingGraphInstance>(m_Query);
            }
#endif
            Entities.With(m_UninitializedQuery).ForEach((Entity e, ScriptingGraph g) =>
            {
                // Start
                var inputs = EntityManager.HasComponent <ValueInput>(e)
                    ? EntityManager.GetBuffer <ValueInput>(e)
                    : new DynamicBuffer <ValueInput>();
                GraphInstance ctx = CreateEntityContext(inputs, e, g.ScriptingGraphAsset.Definition);
#if VS_TRACING
                ctx.ScriptingGraphAssetID = g.ScriptingGraphAsset.GetInstanceID();
#endif
                EntityManager.AddComponentData(e, new ScriptingGraphInstance());
                EntityManager.AddComponentData(e, new ScriptingGraphInstanceAlive());
#if !UNITY_EDITOR // keep it for live edit
                EntityManager.RemoveComponent <ScriptingGraph>(e);
#endif
                if (!m_ShouldTriggerEventJob)
                {
                    m_ShouldTriggerEventJob = ctx.ContainsEventReceiver;
                }
                m_EventFieldDescriptions = ctx.EventFields;
            });

#if VS_DOTS_PHYSICS_EXISTS
            VisualScriptingPhysics.SetupCollisionTriggerData(EntityManager, FrameCount, ref m_TriggerData, m_Query, VisualScriptingPhysics.EventType.Trigger);
            VisualScriptingPhysics.SetupCollisionTriggerData(EntityManager, FrameCount, ref m_CollisionData, m_Query, VisualScriptingPhysics.EventType.Collision);
#endif
            // A list: I assume the most common case is "the entity has not been destroyed"
            NativeList <Entity> destroyed = new NativeList <Entity>(Allocator.Temp);
            Entities.With(m_Query).ForEach((Entity e) =>
            {
                var beingDestroyed = m_BeingDestroyedQueryMask.Matches(e);

                if (!m_Contexts.TryGetValue(e, out var ctx))
                {
                    return;
                }

                // used for random seed
                ctx.LastSystemVersion = LastSystemVersion;

                ctx.ResetFrame();

#if VS_TRACING
                if (s_TracingEnabled && ctx.FrameTrace == null)
                {
                    ctx.FrameTrace = new DotsFrameTrace(Allocator.Persistent);
                }
#endif

#if VS_DOTS_PHYSICS_EXISTS
                TriggerPhysicsEvents(e, ref m_TriggerData, VisualScriptingPhysics.TriggerEventId);
                TriggerPhysicsEvents(e, ref m_CollisionData, VisualScriptingPhysics.CollisionEventId);
#endif
            });

            // Retrieve events that are dispatched from code
            if (m_ShouldTriggerEventJob)
            {
                m_DispatchedEvents.AddRange(
                    VisualScriptingEventUtility.GetEventsFromApi(m_EventSystem, m_EventFieldDescriptions));
            }

            // run each graph while there's either:
            // - a graph reference whose output trigger has been activated
            // - a graph input trigger has been activated by another graph referencing it
            // - events dispatched
            var  ocount    = m_OutputTriggersPerEntityGraphActivated.Count();
            var  icount    = m_InputTriggersPerEntityGraphActivated.Count();
            int  iteration = 0;
            bool secondOutputTriggersMap = true;
            var  dispatchedEvents        = new List <EventNodeData>();
            while (iteration == 0 || iteration < 100 && (ocount > 0 || icount > 0 || m_DispatchedEvents.Count > 0))
            {
                // LogIterationReason();

                dispatchedEvents.Clear();
                ocount = 0;

                Entities.With(m_Query).ForEach(e =>
                {
                    if (!m_Contexts.TryGetValue(e, out GraphInstance ctx))
                    {
                        return;
                    }

                    var beingDestroyed = m_BeingDestroyedQueryMask.Matches(e);

                    if (beingDestroyed)
                    {
                        destroyed.Add(e);
                    }
                    // swap two hash maps - one for the current iteration and one for the next one, clear and swap after each iteration.
                    // for some reason var tmp = h1; h1 = h2; h2 = tmp; didn't work

                    var events = ctx.GlobalToLocalEventData(m_DispatchedEvents).ToList();

                    for (var i = 0; i < events.Count; ++i)
                    {
                        bool eventsTriggered = false;
                        var evt = events[i];

                        // TODO: move that out of the loop once we remove the evt parameter of ResumeFrame and process events/inputs/graphrefs right at once
                        if (eventsTriggered)
                        {
                            // keep filling the same output map. events might trigger graph outputs
                            ctx.ResumeFrame(e, Time, evt, secondOutputTriggersMap
                                ? m_OutputTriggersPerEntityGraphActivated
                                : m_OutputTriggersPerEntityGraphActivated2);
                        }
                    }

                    // this call will remove used entries from the input map
                    var resumeInputs = ctx.TriggerGraphInputs(e, m_InputTriggersPerEntityGraphActivated);
                    // this one won't as we need to process them for each graph. use the output map previously filled by the first ResumeFrame call and maybe the subsequent ones in the event loop
                    var triggerGraphReferences = ctx.TriggerGraphReferences(e, secondOutputTriggersMap
                        ? m_OutputTriggersPerEntityGraphActivated
                        : m_OutputTriggersPerEntityGraphActivated2);

                    if (iteration == 0 || resumeInputs || triggerGraphReferences)
                    {
                        // fill the other output map.
                        ctx.ResumeFrame(e, Time, default, secondOutputTriggersMap
        protected override void OnUpdate()
        {
#if UNITY_EDITOR // Live edit
            if (m_Version != LastVersion)
            {
                m_Version = LastVersion;
                foreach (var contextsValue in m_Contexts.Values)
                {
                    contextsValue?.Dispose();
                }
                m_Contexts.Clear();
                EntityManager.RemoveComponent <ScriptingGraphInstance>(m_Query);
            }
#endif

            Entities.With(m_UninitializedQuery).ForEach((Entity e, ScriptingGraph g) =>
            {
                // Start
                var inputs = EntityManager.HasComponent <ValueInput>(e)
                    ? EntityManager.GetBuffer <ValueInput>(e)
                    : new DynamicBuffer <ValueInput>();
                GraphInstance ctx = CreateEntityContext(inputs, e, g.ScriptingGraphAsset.Definition);
#if VS_TRACING
                ctx.ScriptingGraphAssetID = g.ScriptingGraphAsset.GetInstanceID();
#endif
                EntityManager.AddComponentData(e, new ScriptingGraphInstance());
                EntityManager.AddComponentData(e, new ScriptingGraphInstanceAlive());
#if !UNITY_EDITOR // keep it for live edit
                EntityManager.RemoveComponent <ScriptingGraph>(e);
#endif
            });

#if VS_DOTS_PHYSICS_EXISTS
            VisualScriptingPhysics.SetupCollisionTriggerData(EntityManager, ref m_TriggerData, m_Query, VisualScriptingPhysics.EventType.Trigger);
            VisualScriptingPhysics.SetupCollisionTriggerData(EntityManager, ref m_CollisionData, m_Query, VisualScriptingPhysics.EventType.Collision);
#endif
            // A list: I assume the most common case is "the entity has not been destroyed"
            NativeList <Entity> destroyed = new NativeList <Entity>(Allocator.Temp);
            Entities.With(m_Query).ForEach((Entity e) =>
            {
                var beingDestroyed = m_BeingDestroyedQueryMask.Matches(e);

                GraphInstance ctx;

                //Get the context
                if (beingDestroyed)
                {
                    if (!m_Contexts.TryGetValue(e, out ctx))
                    {
                        return;
                    }
                    destroyed.Add(e);
                }
                else
                {
                    if (!m_Contexts.TryGetValue(e, out ctx))
                    {
                        // MBRIAU: Should this be an error?
                        return;
                    }
                }

                ctx.LastSystemVersion = LastSystemVersion;
                ctx.ResetFrame(); // TODO move at the end

#if VS_TRACING
                if (ctx.FrameTrace == null)
                {
                    ctx.FrameTrace = new DotsFrameTrace(Allocator.Persistent);
                }
#endif

                if (beingDestroyed)
                {
                    ctx.TriggerEntryPoints <OnDestroy>();
                    ctx.RunFrame(e, Time);

                    EntityManager.RemoveComponent <ScriptingGraphInstance>(e);
                    EntityManager.RemoveComponent <ScriptingGraph>(e);
                }
                else
                {
                    // Start
                    if (ctx.IsStarting)
                    {
                        ctx.TriggerEntryPoints <OnStart>();
                        ctx.IsStarting = false;
                    }

                    // Update
                    ctx.TriggerEntryPoints <OnUpdate>();
                    ctx.TriggerEntryPoints <OnKey>();

#if VS_DOTS_PHYSICS_EXISTS
                    TriggerPhysicsEvents(e, ref m_TriggerData, VisualScriptingPhysics.TriggerEventId);
                    TriggerPhysicsEvents(e, ref m_CollisionData, VisualScriptingPhysics.CollisionEventId);
#endif
                    // Actually execute all nodes active
                    ctx.RunFrame(e, Time);

                    m_DispatchedEvents.AddRange(ctx.DispatchedEvents);
                }
            });

            TriggerEvents(m_DispatchedEvents);

#if VS_TRACING
            foreach (var graphInstancePair in m_Contexts)
            {
                var graphInstance = graphInstancePair.Value;
                if (graphInstance?.FrameTrace != null)
                {
                    DotsFrameTrace.FlushFrameTrace(graphInstance.ScriptingGraphAssetID, UnityEngine.Time.frameCount,
                                                   graphInstance.CurrentEntity,
#if UNITY_EDITOR
                                                   EntityManager.GetName(graphInstance.CurrentEntity),
#else
                                                   e.Index.ToString(),
#endif
                                                   graphInstance.FrameTrace);
                    graphInstance.FrameTrace = null;
                }
            }
#endif
            for (var index = 0; index < destroyed.Length; index++)
            {
                var entity = destroyed[index];
                m_Contexts[entity].Dispose();
                m_Contexts.Remove(entity);
            }

            destroyed.Dispose();
        }
        protected override void OnUpdate()
        {
            SceneWithBuildConfigurationGUIDs.ValidateBuildSettingsCache();

            var sceneSystem            = World.GetExistingSystem <SceneSystem>();
            var buildConfigurationGUID = sceneSystem.BuildConfigurationGUID;

            // Add scene entities that haven't been encountered yet
            if (!m_AddScenes.IsEmptyIgnoreFilter)
            {
                //@TODO: Should use Entities.ForEach but we are missing
                // 1. Entities.ForEach support with execute always (ILPP compilation not taking effect on first domain reload)
                // 2. Entities.ForEach not supporting explicit queries

                using (var addScenes = m_AddScenes.ToEntityArray(Allocator.TempJob))
                {
                    var trackerStates = new NativeArray <AssetDependencyTrackerState>(addScenes.Length, Allocator.Temp);
                    for (int i = 0; i != addScenes.Length; i++)
                    {
                        var sceneEntity        = addScenes[i];
                        var scene              = EntityManager.GetComponentData <SceneReference>(sceneEntity);
                        var requestSceneLoaded = EntityManager.GetComponentData <RequestSceneLoaded>(sceneEntity);

                        var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(scene.SceneGUID,
                                                                                    buildConfigurationGUID, out var requireRefresh);
                        var async = (requestSceneLoaded.LoadFlags & SceneLoadFlags.BlockOnImport) == 0;

                        LogResolving(async ? "Adding Async" : "Adding Sync", guid);

                        _AssetDependencyTracker.Add(guid, sceneEntity, async);
                        if (requireRefresh)
                        {
                            _AssetDependencyTracker.RequestRefresh();
                        }

                        trackerStates[i] = new AssetDependencyTrackerState {
                            SceneAndBuildConfigGUID = guid
                        };
                    }

                    EntityManager.AddComponentData(m_AddScenes, trackerStates);
                    trackerStates.Dispose();
                }
            }

            // Remove scene entities that were added and should no longer be tracked
            if (!m_RemoveScenes.IsEmptyIgnoreFilter)
            {
                using (var removeEntities = m_RemoveScenes.ToEntityArray(Allocator.TempJob))
                    using (var removeGuids =
                               m_RemoveScenes.ToComponentDataArray <AssetDependencyTrackerState>(Allocator.TempJob))
                    {
                        for (int i = 0; i != removeEntities.Length; i++)
                        {
                            LogResolving("Removing", removeGuids[i].SceneAndBuildConfigGUID);
                            _AssetDependencyTracker.Remove(removeGuids[i].SceneAndBuildConfigGUID, removeEntities[i]);
                        }
                    }

                EntityManager.RemoveComponent <AssetDependencyTrackerState>(m_RemoveScenes);
            }

            // Process any scenes that have completed their asset import
            var isDone = _AssetDependencyTracker.GetCompleted(_Changed);

            foreach (var change in _Changed)
            {
                var sceneEntity = change.UserKey;
                LogResolving($"Resolving: {change.Asset} -> {change.ArtifactID}");

                if (!m_ValidSceneMask.Matches(sceneEntity))
                {
                    throw new InvalidOperationException("entity should have been removed from tracker already");
                }

                // Unload any previous state
                var unloadFlags = SceneSystem.UnloadParameters.DestroySectionProxyEntities |
                                  SceneSystem.UnloadParameters.DontRemoveRequestSceneLoaded;
                sceneSystem.UnloadScene(sceneEntity, unloadFlags);

                // Resolve new state
                var scene   = EntityManager.GetComponentData <SceneReference>(change.UserKey);
                var request = EntityManager.GetComponentData <RequestSceneLoaded>(change.UserKey);
                if (change.ArtifactID != default)
                {
                    ResolveSceneSectionUtility.ResolveSceneSections(EntityManager, change.UserKey, scene.SceneGUID,
                                                                    request, change.ArtifactID);
                }
                else
                {
                    Debug.LogError(
                        $"Failed to import entity scene because the automatically generated SceneAndBuildConfigGUID asset was not present: '{AssetDatabaseCompatibility.GuidToPath(scene.SceneGUID)}' -> '{AssetDatabaseCompatibility.GuidToPath(change.Asset)}'");
                }
            }

            if (!isDone)
            {
                EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
            }
        }
Beispiel #4
0
            public void Execute(int index)
            {
                Entity e    = SimulationChunksFirstSegment[index];
                int    iter = 0;

                do
                {
                    if (iter++ >= 1000000)
                    {
                        throw new NotImplementedException();
                    }
                    var segment = Segments[e];
                    var items   = Items[e];
                    // Debug.Log($"{e} {segment} {items.Length}");

                    for (int i = 0; i < items.Length; i++)
                    {
                        ref BeltItem item = ref items.ElementAt(i);

                        // simple case, too far from belt end to care about a next segment
                        if (item.Distance > Settings.BeltDistanceSubDiv)
                        {
                            item.Distance--;
                            segment.DistanceToInsertAtStart++;
                            Segments[e] = segment;
                            break;
                        }

                        // no next segment, so BeltDistanceSubDiv is the min distance
                        // continue to move the next item on the belt
                        if (segment.Next == Entity.Null)
                        {
                            continue;
                        }

                        if (!HasBeltSegmentMask.Matches(segment.Next))
                        {
                            if (HasBeltSplitterMask.Matches(segment.Next))
                            {
                                var splitter = Splitters[segment.Next];
                                // no room in input
                                if (splitter.Input.Type != ItemType.None)
                                {
                                    continue;
                                }

                                if (item.Distance > 0) // still inserting
                                {
                                    item.Distance--;
                                    segment.DistanceToInsertAtStart++;
                                    Segments[e] = segment;
                                    break;
                                }

                                // will be update this frame
                                item.Distance           = (ushort)(Settings.BeltDistanceSubDiv);
                                splitter.Input          = item;
                                Splitters[segment.Next] = splitter;
                                items.RemoveAt(i);
                                // Debug.Log("MOVE TO SPLITTER");
                                i--;
                            }

                            continue;
                        }

                        // only move if the next segment has room
                        var nextBeltSegment = Segments[segment.Next];
                        if (nextBeltSegment.DistanceToInsertAtStart == 0)
                        {
                            continue;
                        }

                        if (item.Distance > 0) // still inserting
                        {
                            item.Distance--;
                            segment.DistanceToInsertAtStart++;
                            Segments[e] = segment;
                        }
                        else if (InsertInSegment(ref Items, ref Segments, item, segment.Next))
                        {
                            items.RemoveAt(i);
                            i--;
                        }

                        break;
                    }
                    e = segment.Prev;
                } while (e != Entity.Null);