/// <summary> /// Updates the Scene /// </summary> internal void Update() { if (!this.IsCurrent) { throw new InvalidOperationException("Can't update non-current Scene!"); } switchLock++; // Update all GameObjects //Profile.TimeUpdateScene.BeginMeasure(); //DualityApp.EditorGuard(() => //{ this.UpdateComponents <ICmpUpdatable>(cmp => cmp.OnUpdate()); this.visibilityStrategy.Update(); //}); //Profile.TimeUpdateScene.EndMeasure(); // Perform a cleanup step to catch all DisposeLater calls from within the Scene update DualityApp.RunCleanup(); // Perform a scheduled Scene switch PerformScheduledSwitch(); switchLock--; }
[Test] public void DeactivateGameObjectDispose() { InitializableEventReceiver initTester = this.obj.AddComponent <InitializableEventReceiver>(); Scene.SwitchTo(this.scene, true); this.obj.Dispose(); DualityApp.RunCleanup(); // Need to run cleanup, so disposed GameObjects will be processed. Assert.IsTrue(initTester.HasReceived(InitializableEventReceiver.EventFlag.Deactivate)); }
[Test] public void EnforceOrderGameObjectDispose([Values(true, false)] bool deepObjectTree) { EventOrderLog eventLog = new EventOrderLog(); eventLog.EventFilter = EventType.Deactivate; int objectCount = deepObjectTree ? 10 : 1; GameObject root = this.GenerateSampleTree(objectCount, true, typeof(TestComponentA1), typeof(TestComponentA2), typeof(TestComponentA3), typeof(TestComponentA4), typeof(TestComponentA5)); Scene.SwitchTo(new Scene(), true); Scene.Current.AddObject(root); this.AssignEventLog(root, eventLog, true); root.Dispose(); DualityApp.RunCleanup(); this.AssertEventOrder(eventLog, 5 * objectCount, Component.ExecOrder, true); Scene.SwitchTo(null, true); }
/// <summary> /// Updates the Scene /// </summary> internal void Update() { if (!this.IsCurrent) { throw new InvalidOperationException("Can't update non-current Scene!"); } switchLock++; // Update all GameObjects this.UpdateComponents <ICmpUpdatable>(cmp => cmp.OnUpdate()); this.visibilityStrategy.Update(); if (this.lowFramerateMode) { this.UpdateComponents <ICmpFixedUpdatable>(cmp => cmp.OnFixedUpdate(Time.TimeMult)); } else { this.fixedStepTimer += Time.DeltaTime; while (this.fixedStepTimer >= this.fixedStepPeriod) { this.UpdateComponents <ICmpFixedUpdatable>(cmp => cmp.OnFixedUpdate(1f)); this.fixedStepTimer -= this.fixedStepPeriod; } } this.lowFramerateMode = (Time.UnscaledDeltaTime > Time.SecondsPerFrame * 0.9f); // Perform a cleanup step to catch all DisposeLater calls from within the Scene update DualityApp.RunCleanup(); // Perform a scheduled Scene switch PerformScheduledSwitch(); switchLock--; }
/// <summary> /// Updates the Scene /// </summary> internal void Update() { if (!this.IsCurrent) { throw new InvalidOperationException("Can't update non-current Scene!"); } switchLock++; // Update physics bool physUpdate = false; double physBegin = Time.MainTimer.TotalMilliseconds; if (Scene.PhysicsFixedTime) { physicsAcc += Time.MsPFMult * Time.TimeMult; int iterations = 0; if (physicsAcc >= Time.MsPFMult) { Profile.TimeUpdatePhysics.BeginMeasure(); DualityApp.EditorGuard(() => { double timeUpdateBegin = Time.MainTimer.TotalMilliseconds; while (physicsAcc >= Time.MsPFMult) { // Catch up on updating progress FarseerPhysics.Settings.VelocityThreshold = PhysicsUnit.VelocityToPhysical * DualityApp.AppData.PhysicsVelocityThreshold; physicsWorld.Step(Time.SPFMult); physicsAcc -= Time.MsPFMult; iterations++; double timeSpent = Time.MainTimer.TotalMilliseconds - timeUpdateBegin; if (timeSpent >= Time.MsPFMult * 10.0f) { break; // Emergency exit } } }); physUpdate = true; Profile.TimeUpdatePhysics.EndMeasure(); } } else { Profile.TimeUpdatePhysics.BeginMeasure(); DualityApp.EditorGuard(() => { FarseerPhysics.Settings.VelocityThreshold = PhysicsUnit.VelocityToPhysical * Time.TimeMult * DualityApp.AppData.PhysicsVelocityThreshold; physicsWorld.Step(Time.TimeMult * Time.SPFMult); if (Time.TimeMult == 0.0f) { physicsWorld.ClearForces(); // Complete freeze? Clear forces, so they don't accumulate. } physicsAcc = PhysicsAccStart; }); physUpdate = true; Profile.TimeUpdatePhysics.EndMeasure(); } double physTime = Time.MainTimer.TotalMilliseconds - physBegin; // Apply Farseers internal measurements to Duality if (physUpdate) { Profile.TimeUpdatePhysicsAddRemove.Set(1000.0f * physicsWorld.AddRemoveTime / System.Diagnostics.Stopwatch.Frequency); Profile.TimeUpdatePhysicsContacts.Set(1000.0f * physicsWorld.ContactsUpdateTime / System.Diagnostics.Stopwatch.Frequency); Profile.TimeUpdatePhysicsContinous.Set(1000.0f * physicsWorld.ContinuousPhysicsTime / System.Diagnostics.Stopwatch.Frequency); Profile.TimeUpdatePhysicsController.Set(1000.0f * physicsWorld.ControllersUpdateTime / System.Diagnostics.Stopwatch.Frequency); Profile.TimeUpdatePhysicsSolve.Set(1000.0f * physicsWorld.SolveUpdateTime / System.Diagnostics.Stopwatch.Frequency); } // Update low fps physics state if (!physicsLowFps) { physicsLowFps = Time.LastDelta > Time.MsPFMult && physTime > Time.LastDelta * 0.85f; } else { physicsLowFps = !(Time.LastDelta < Time.MsPFMult * 0.9f || physTime < Time.LastDelta * 0.6f); } // Update all GameObjects Profile.TimeUpdateScene.BeginMeasure(); DualityApp.EditorGuard(() => { this.UpdateComponents <ICmpUpdatable>(cmp => cmp.OnUpdate()); this.visibilityStrategy.Update(); }); Profile.TimeUpdateScene.EndMeasure(); // Perform a cleanup step to catch all DisposeLater calls from within the Scene update DualityApp.RunCleanup(); // Perform a scheduled Scene switch PerformScheduledSwitch(); switchLock--; }
private void OnUpdate() { if (serverState == ServerState.Unloaded) { return; } Time.FrameTick(false, false); AsyncManager.InvokeBeforeUpdate(); Scene.Current.Update(); AsyncManager.InvokeAfterUpdate(); DualityApp.RunCleanup(); lock (sync) { // Respawn dead players immediately if (playerSpawningEnabled) { foreach (KeyValuePair <NetConnection, PlayerClient> pair in players) { if (pair.Value.State == PlayerState.Dead) { RespawnPlayer(pair.Value); } } } if (serverState == ServerState.LevelReady) { if (players.Count >= minPlayers) { countdown -= Time.DeltaTime; if (countdown <= 0f) { serverState = ServerState.LevelRunning; countdownNotify = 0; levelStartTime = NetTime.Now; SendToActivePlayers(new PlayerSetControllable { IsControllable = true }, 3, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); SendToActivePlayers(new ShowMessage { Flags = 0x01, Text = "\n\n\n\f[c:1]Go!" }, 24, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); } else if (countdown < countdownNotify) { countdownNotify = (int)Math.Ceiling(countdown); if (countdownNotify == 15) { SendToActivePlayers(new ShowMessage { Text = "\n\n\n\f[c:1]Game will start in 15 seconds!" }, 48, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); } else if (countdownNotify == 3) { SendToActivePlayers(new ShowMessage { Flags = 0x01, Text = "\n\n\n\f[c:4]3" }, 24, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); } else if (countdownNotify == 2) { SendToActivePlayers(new ShowMessage { Flags = 0x01, Text = "\n\n\n\f[c:3]2" }, 24, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); } else if (countdownNotify == 1) { SendToActivePlayers(new ShowMessage { Flags = 0x01, Text = "\n\n\n\f[c:2]1" }, 24, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); } } } } else if (serverState == ServerState.LevelComplete) { countdown -= Time.DeltaTime; if (countdown <= 0f) { if (activePlaylist == null) { ChangeLevel(currentLevel, currentLevelType); } else { ChangeLevelFromPlaylist(activePlaylistIndex + 1); } } } // Update all players if (playerConnections.Count > 0) { List <ActorBase> spawnedActors = levelHandler.SpawnedActors; int playerCount = players.Count; int spawnedActorCount = spawnedActors.Count; NetOutgoingMessage m = server.CreateMessage(14 + 21 * playerCount + 24 * spawnedActorCount); m.Write(SpecialPacketTypes.UpdateAllActors); m.Write((long)(NetTime.Now * 1000)); foreach (KeyValuePair <NetConnection, PlayerClient> pair in players) { PlayerClient player = pair.Value; m.Write((int)player.Index); // Player Index if (player.State != PlayerState.Spawned || !player.ProxyActor.IsVisible) { m.Write((byte)0x00); // Flags - None continue; } m.Write((byte)0x01); // Flags - Visible Vector3 pos = player.ProxyActor.Transform.Pos; m.Write((ushort)(pos.X * 2.5f)); m.Write((ushort)(pos.Y * 2.5f)); m.Write((ushort)(pos.Z * 2.5f)); m.Write((bool)player.ProxyActor.IsFacingLeft); } foreach (ActorBase actor in spawnedActors) { if ((actor.CollisionFlags & CollisionFlags.TransformChanged) == 0) { continue; } actor.CollisionFlags &= ~CollisionFlags.TransformChanged; m.Write((int)actor.Index); // Object Index if (!actor.IsVisible) { m.Write((byte)0x00); // Flags - None continue; } if (actor.Transform.Scale > 0.95f && actor.Transform.Scale < 1.05f && actor.Transform.Angle > -0.04f && actor.Transform.Angle < 0.04f) { m.Write((byte)0x01); // Flags - Visible Vector3 pos = actor.Transform.Pos; m.Write((ushort)(pos.X * 2.5f)); m.Write((ushort)(pos.Y * 2.5f)); m.Write((ushort)(pos.Z * 2.5f)); m.Write((bool)actor.IsFacingLeft); } else { m.Write((byte)0x03); // Flags - Visible | HasScaleAngle Vector3 pos = actor.Transform.Pos; m.Write((ushort)pos.X); m.Write((ushort)pos.Y); m.Write((ushort)pos.Z); m.Write((float)actor.Transform.Scale); m.WriteRangedSingle((float)actor.Transform.Angle, 0f, MathF.TwoPi, 8); m.Write((bool)actor.IsFacingLeft); } } m.Write((int)-1); // Terminator // Send update command to all active players server.Send(m, playerConnections, NetDeliveryMethod.Unreliable, PacketChannels.UnorderedUpdates); } } }