Exemple #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();
        }