void DrawStats() { var samplesPerSecond = 1.0f / m_StatsDeltaTime.average; int y = 2; Overlay.Managed.Write(2, y++, " tick rate: {0}", m_NetworkClient.serverTickRate); Overlay.Managed.Write(2, y++, " frame timescale: {0}", m_FrameTimeScale); Overlay.Managed.Write(2, y++, " sim : {0:0.0} / {1:0.0} / {2:0.0} ({3:0.0})", m_ServerSimTime.min, m_ServerSimTime.min, m_ServerSimTime.max, m_ServerSimTime.stdDeviation); Overlay.Managed.Write(2, y++, "^FF0 lat : {0:0.0} / {1:0.0} / {2:0.0}", m_Latency.min, m_Latency.average, m_Latency.max); Overlay.Managed.Write(2, y++, "^0FF rtt : {0:0.0} / {1:0.0} / {2:0.0}", m_RTT.min, m_RTT.average, m_RTT.max); Overlay.Managed.Write(2, y++, "^0F0 cmdq : {0:0.0} / {1:0.0} / {2:0.0}", m_CMDQ.min, m_CMDQ.average, m_CMDQ.max); Overlay.Managed.Write(2, y++, "^F0F intp : {0:0.0} / {1:0.0} / {2:0.0}", m_Interp.min, m_Interp.average, m_Interp.max); y++; Overlay.Managed.Write(2, y++, "^22F header/payload/total bps (in):"); Overlay.Managed.Write(2, y++, "^22F {0:00.0} / {1:00.0} / {2:00.0} ({3})", m_HeaderBitsIn.graph.average / 8.0f * samplesPerSecond, (m_BytesIn.graph.average - m_HeaderBitsIn.graph.average / 8.0f) * samplesPerSecond, m_BytesIn.graph.average * samplesPerSecond, m_NetworkClient.clientConfig.serverUpdateRate); Overlay.Managed.Write(2, y++, "^F00 bps (out): {0:00.0}", m_BytesOut.graph.average * samplesPerSecond); Overlay.Managed.Write(2, y++, " pps (in): {0:00.0}", m_PackagesIn.graph.average * samplesPerSecond); Overlay.Managed.Write(2, y++, " pps (out): {0:00.0}", m_PackagesOut.graph.average * samplesPerSecond); Overlay.Managed.Write(2, y++, " pl% (in): {0:00.0}", m_PackageLossPctIn.average); Overlay.Managed.Write(2, y++, " pl% (out): {0:00.0}", m_PackageLossPctOut.average); y++; Overlay.Managed.Write(2, y++, " upd_srate: {0:00.0} ({1})", m_SnapshotsIn.graph.average * samplesPerSecond, m_NetworkClient.clientConfig.serverUpdateInterval); Overlay.Managed.Write(2, y++, " cmd_srate: {0:00.0} ({1})", m_CommandsOut.graph.average * samplesPerSecond, m_NetworkClient.serverTickRate); Overlay.Managed.Write(2, y++, " ev (in): {0:00.0}", m_EventsIn.graph.average * samplesPerSecond); Overlay.Managed.Write(2, y++, " ev (out): {0:00.0}", m_EventsOut.graph.average * samplesPerSecond); var startIndex = m_BytesIn.graph.GetData().HeadIndex; var graphY = 5; DebugOverlay.DrawGraph(38, graphY, 60, 5, m_Latency.GetData().GetArray(), startIndex, Color.yellow, 100); DebugOverlay.DrawGraph(38, graphY, 60, 5, m_RTT.GetData().GetArray(), startIndex, Color.cyan, 100); DebugOverlay.DrawGraph(38, graphY, 60, 5, m_CMDQ.GetData().GetArray(), startIndex, Color.green, 10); DebugOverlay.DrawGraph(38, graphY, 60, 5, m_Interp.GetData().GetArray(), startIndex, Color.magenta, 100); DebugOverlay.DrawHist(38, graphY, 60, 5, m_HardCatchup.GetArray(), startIndex, Color.red, 100); m_2GraphData[0] = m_BytesIn.graph.GetData().GetArray(); m_2GraphData[1] = m_BytesOut.graph.GetData().GetArray(); graphY += 7; DebugOverlay.DrawGraph(38, graphY, 60, 5, m_2GraphData, startIndex, m_BytesGraphColors); graphY += 6; DebugOverlay.DrawHist(38, graphY++, 60, 1, m_SnapshotsIn.graph.GetData().GetArray(), startIndex, Color.blue, 5.0f); DebugOverlay.DrawHist(38, graphY++, 60, 1, m_CommandsOut.graph.GetData().GetArray(), startIndex, Color.red, 5.0f); DebugOverlay.DrawHist(38, graphY++, 60, 1, m_EventsIn.graph.GetData().GetArray(), startIndex, Color.yellow, 5.0f); DebugOverlay.DrawHist(38, graphY++, 60, 1, m_EventsOut.graph.GetData().GetArray(), startIndex, Color.green, 5.0f); }
void DrawFPS() { DebugOverlay.Write(0, 1, "{0} FPS ({1:##.##} ms)", Mathf.RoundToInt(1000.0f / m_FrameDurationMS), m_FrameDurationMS); float minDuration = float.MaxValue; float maxDuration = float.MinValue; float sum = 0; for (var i = 0; i < _no_frames; i++) { var frametime = m_FrameTimes[i]; sum += frametime; if (frametime < minDuration) { minDuration = frametime; } if (frametime > maxDuration) { maxDuration = frametime; } } DebugOverlay.Write(Color.green, 0, 2, "{0:##.##}", minDuration); DebugOverlay.Write(Color.grey, 6, 2, "{0:##.##}", sum / _no_frames); DebugOverlay.Write(Color.red, 12, 2, "{0:##.##}", maxDuration); DebugOverlay.Write(0, 3, "Frame #: {0}", Time.frameCount); DebugOverlay.Write(0, 4, m_GraphicsDeviceName); int y = 6; for (int i = 0; i < recordersList.Length; i++) { DebugOverlay.Write(0, y++, "{0:##.##}ms (*{1:##}) ({2:##.##}ms *{3:##}) {4}", recordersList[i].avgTime, recordersList[i].avgCount, recordersList[i].time, recordersList[i].count, recordersList[i].name); } if (showFPS.IntValue < 3) { return; } y++; // Start at framecount+1 so the one we have just recorded will be the last DebugOverlay.DrawHist(0, y, 20, 2, m_FrameTimes, Time.frameCount + 1, fpsColor, 20.0f); DebugOverlay.DrawHist(0, y + 2, 20, 2, m_TicksPerFrame, Time.frameCount + 1, histColor, 3.0f * 16.0f); DebugOverlay.DrawGraph(0, y + 6, 40, 2, m_FrameTimes, Time.frameCount + 1, fpsColor, 20.0f); if (GameWorld.s_Worlds.Count > 0) { var world = GameWorld.s_Worlds[0]; DebugOverlay.Write(0, y + 8, "Tick: {0:##.#}", 1000.0f * world.worldTime.tickInterval); } }
protected override void OnUpdate() { var cameraArray = Group.GetComponentArray <Camera>(); var playerCameraArray = Group.GetComponentArray <PlayerCamera>(); for (var i = 0; i < cameraArray.Length; i++) { var camera = cameraArray[i]; var playerCamera = playerCameraArray[i]; var settings = playerCamera.cameraSettings; var enabled = settings.isEnabled; var isActive = camera.gameObject.activeSelf; if (!enabled) { if (isActive) { Game.game.PopCamera(camera); camera.gameObject.SetActive(false); } continue; } if (!isActive) { camera.gameObject.SetActive(true); Game.game.PushCamera(camera); } if (!XRSettings.enabled) { camera.fieldOfView = settings.fieldOfView; } else { camera.stereoTargetEye = StereoTargetEyeMask.None; } if (debugCameraDetach.IntValue == 0) { // Normal movement camera.transform.position = settings.position; camera.transform.rotation = settings.rotation; } else if (debugCameraDetach.IntValue == 1) { // Move char but still camera } if (debugCameraDetach.ChangeCheck()) { // Block normal input Game.Input.SetBlock(Game.Input.Blocker.Debug, debugCameraDetach.IntValue == 2); } if (debugCameraDetach.IntValue == 2 && !Console.IsOpen()) { var eu = camera.transform.localEulerAngles; if (eu.x > 180.0f) { eu.x -= 360.0f; } eu.x = Mathf.Clamp(eu.x, -70.0f, 70.0f); eu += new Vector3(-Input.GetAxisRaw("Mouse Y"), Input.GetAxisRaw("Mouse X"), 0); float invertY = Game.configInvertY.IntValue > 0 ? 1.0f : -1.0f; eu += Time.deltaTime * (new Vector3(-invertY * Input.GetAxisRaw("RightStickY") * InputSystem.s_JoystickLookSensitivity.y, Input.GetAxisRaw("RightStickX") * InputSystem.s_JoystickLookSensitivity.x, 0)); camera.transform.localEulerAngles = eu; m_DetachedMoveSpeed += Input.GetAxisRaw("Mouse ScrollWheel"); float verticalMove = (Input.GetKey(KeyCode.R) ? 1.0f : 0.0f) + (Input.GetKey(KeyCode.F) ? -1.0f : 0.0f); verticalMove += Input.GetAxisRaw("Trigger"); camera.transform.Translate( new Vector3(Input.GetAxisRaw("Horizontal"), verticalMove, Input.GetAxisRaw("Vertical")) * Time.deltaTime * m_DetachedMoveSpeed); } if (debugCameraMove.IntValue > 0) { // Only show for one player if (lastUsedFrame < Time.frameCount) { lastUsedFrame = Time.frameCount; int o = Time.frameCount % movehist_x.Length; var rot = camera.transform.localEulerAngles; movehist_x[o] = rot.x % 90.0f; movehist_y[o] = rot.y % 90.0f; movehist_z[o] = rot.z % 90.0f; DebugOverlay.DrawGraph(4, 4, 10, 5, movehist_x, o, Color.red, 10.0f); DebugOverlay.DrawGraph(4, 12, 10, 5, movehist_y, o, Color.green, 10.0f); DebugOverlay.DrawGraph(4, 20, 10, 5, movehist_z, o, Color.blue, 10.0f); } } } }
protected override void Update(Entity abilityEntity, CharBehaviour charAbility, AbilityControl abilityCtrl, Ability_Movement.Settings settings) { if (abilityCtrl.active == 0) { if (abilityCtrl.behaviorState != AbilityControl.State.Idle) { abilityCtrl.behaviorState = AbilityControl.State.Idle; EntityManager.SetComponentData(abilityEntity, abilityCtrl); } return; } // Movement is always active (unless canceled) abilityCtrl.behaviorState = AbilityControl.State.Active; EntityManager.SetComponentData(abilityEntity, abilityCtrl); var time = m_world.worldTime; var command = EntityManager.GetComponentData <UserCommandComponentData>(charAbility.character).command; var predictedState = EntityManager.GetComponentData <CharacterPredictedData>(charAbility.character); var character = EntityManager.GetComponentObject <Character>(charAbility.character); var newPhase = CharacterPredictedData.LocoState.MaxValue; var phaseDuration = time.DurationSinceTick(predictedState.locoStartTick); var isOnGround = predictedState.IsOnGround(); var isMoveWanted = command.moveMagnitude != 0.0f; // Ground movement if (isOnGround) { if (isMoveWanted) { newPhase = CharacterPredictedData.LocoState.GroundMove; } else { newPhase = CharacterPredictedData.LocoState.Stand; } } // Jump if (isOnGround) { predictedState.jumpCount = 0; } if (command.buttons.IsSet(UserCommand.Button.Jump) && isOnGround) { predictedState.jumpCount = 1; newPhase = CharacterPredictedData.LocoState.Jump; } if (command.buttons.IsSet(UserCommand.Button.Jump) && predictedState.locoState == CharacterPredictedData.LocoState.InAir && predictedState.jumpCount < 2) { predictedState.jumpCount = predictedState.jumpCount + 1; predictedState.velocity.y = 0; newPhase = CharacterPredictedData.LocoState.DoubleJump; } if (predictedState.locoState == CharacterPredictedData.LocoState.Jump || predictedState.locoState == CharacterPredictedData.LocoState.DoubleJump) { if (phaseDuration >= Game.config.jumpAscentDuration) { newPhase = CharacterPredictedData.LocoState.InAir; } } // Set phase start tick if phase has changed if (newPhase != CharacterPredictedData.LocoState.MaxValue && newPhase != predictedState.locoState) { predictedState.locoState = newPhase; predictedState.locoStartTick = time.tick; } if (debugCharacterMove.IntValue > 0) { // Only show for one player if (lastUsedFrame < Time.frameCount) { lastUsedFrame = Time.frameCount; int o = Time.frameCount % movehist_x.Length; movehist_x[o] = predictedState.position.x % 10.0f; movehist_y[o] = predictedState.position.y % 10.0f; movehist_z[o] = predictedState.position.z % 10.0f; DebugOverlay.DrawGraph(4, 4, 10, 5, movehist_x, o, Color.red, 10.0f); DebugOverlay.DrawGraph(4, 12, 10, 5, movehist_y, o, Color.green, 10.0f); DebugOverlay.DrawGraph(4, 20, 10, 5, movehist_z, o, Color.blue, 10.0f); } } if (time.tick != predictedState.tick + 1) { GameDebug.Log("Update tick invalid. Game tick:" + time.tick + " but current state is at tick:" + predictedState.tick); } predictedState.tick = time.tick; // Apply damange impulse from previus frame if (time.tick == predictedState.damageTick + 1) { predictedState.velocity += predictedState.damageDirection * predictedState.damageImpulse; predictedState.locoState = CharacterPredictedData.LocoState.InAir; predictedState.locoStartTick = time.tick; } var moveQuery = EntityManager.GetComponentObject <CharacterMoveQuery>(charAbility.character); // Simple adjust of height while on platform if (predictedState.locoState == CharacterPredictedData.LocoState.Stand && character.groundCollider != null && character.groundCollider.gameObject.layer == m_platformLayer) { if (character.altitude < moveQuery.settings.skinWidth - 0.01f) { var platform = character.groundCollider; var posY = platform.transform.position.y + moveQuery.settings.skinWidth; predictedState.position.y = posY; } } // Calculate movement and move character var deltaPos = Vector3.zero; CalculateMovement(ref time, ref predictedState, ref command, ref deltaPos); // Setup movement query moveQuery.collisionLayer = character.teamId == 0 ? m_charCollisionALayer : m_charCollisionBLayer; moveQuery.moveQueryStart = predictedState.position; moveQuery.moveQueryEnd = moveQuery.moveQueryStart + (float3)deltaPos; EntityManager.SetComponentData(charAbility.character, predictedState); }
public void TickUpdate() { if (m_ShowStats < 1) { return; } long ticks = m_StopWatch.ElapsedTicks; float frameDurationMs = (ticks - m_LastFrameTicks) * 1000 / (float)m_StopWatchFreq; m_LastFrameTicks = ticks; DebugOverlay.SetColor(Color.yellow); DebugOverlay.SetOrigin(0, 0); DebugOverlay.Write(1, 0, "FPS:{0,6:###.##}", 1.0f / Time.deltaTime); fpsHistory[Time.frameCount % fpsHistory.Length] = 1.0f / Time.deltaTime; DebugOverlay.DrawGraph(1, 1, 9, 1.5f, fpsHistory, Time.frameCount % fpsHistory.Length, Color.green); DebugOverlay.Write(30, 0, "Open console (F12) and type: \"showstats\" to toggle graphs"); if (m_ShowStats < 2) { return; } DebugOverlay.Write(0, 4, "Hello, {0,-5} world!", Time.frameCount % 100 < 50 ? "Happy" : "Evil"); DebugOverlay.Write(0, 5, "FrameNo: {0,7}", Time.frameCount); DebugOverlay.Write(0, 6, "MonoHeap:{0,7} kb", (int)(UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong() / 1024)); /// Graphing difference between deltaTime and actual passed time float fps = Time.deltaTime * 1000.0f; var idx = Time.frameCount % fpsArray[0].Length;; fpsArray[0][idx] = -Mathf.Min(0, frameDurationMs - fps); fpsArray[1][idx] = Mathf.Max(0, frameDurationMs - fps); float variance, mean, min, max; CalcStatistics(fpsArray[0], out mean, out variance, out min, out max); // Draw histogram over time differences DebugOverlay.DrawHist(20, 10, 20, 3, fpsArray, Time.frameCount, colors, max); DebugOverlay.SetColor(new Color(1.0f, 0.3f, 0.0f)); DebugOverlay.Write(20, 14, "{0,4:#.###} ({1,4:##.#} +/- {2,4:#.##})", frameDurationMs - fps, mean, Mathf.Sqrt(variance)); DebugOverlay.DrawGraph(45, 10, 40, 3, fpsArray, Time.frameCount, colors, max); /// Graphing frametime var idx2 = Time.frameCount % frameTimeArray.Length; frameTimeArray[idx2] = frameDurationMs; CalcStatistics(frameTimeArray, out mean, out variance, out min, out max); DebugOverlay.DrawHist(20, 15, 20, 3, frameTimeArray, Time.frameCount, Color.red, max); // Draw legend float scale = 18.0f - 3.0f / max * 16.6667f; DebugOverlay.DrawLine(20, scale, 40, scale, Color.black); DebugOverlay.Write(20, 18, "{0,5} ({1} +/- {2})", frameDurationMs, mean, Mathf.Sqrt(variance)); DebugOverlay.DrawGraph(45, 15, 40, 3, frameTimeArray, Time.frameCount, Color.red, max); // Draw some lines to help visualize framerate fluctuations float ratio = (float)DebugOverlay.Height / DebugOverlay.Width * Screen.width / Screen.height; float time = (float)Time.frameCount / 60.0f; for (var i = 0; i < 10; i++) { DebugOverlay.DrawLine(60, 20, 60 + Mathf.Sin(Mathf.PI * 0.2f * i + time) * 8.0f, 20 + Mathf.Cos(Mathf.PI * 0.2f * i + time) * 8.0f * ratio, Color.black); } }
protected override void Update(Entity abilityEntity, CharacterAbility charAbility, Ability_Movement.Settings settings) { Profiler.BeginSample("Movement_Update"); var time = m_world.worldTime; var command = EntityManager.GetComponentObject <UserCommandComponent>(charAbility.character).command; var characterPredictedState = EntityManager.GetComponentObject <CharacterPredictedState>(charAbility.character); var health = EntityManager.GetComponentObject <HealthState>(charAbility.character); var newPhase = CharacterPredictedState.StateData.LocoState.MaxValue; var phaseDuration = time.DurationSinceTick(characterPredictedState.State.locoStartTick); var isOnGround = characterPredictedState.State.IsOnGround(); var isMoveWanted = command.moveMagnitude != 0.0f; if (health.health <= 0) { newPhase = CharacterPredictedState.StateData.LocoState.Dead; } else { // Ground movement if (isOnGround) { if (isMoveWanted) { newPhase = CharacterPredictedState.StateData.LocoState.GroundMove; } else { newPhase = CharacterPredictedState.StateData.LocoState.Stand; } } // Jump if (isOnGround) { characterPredictedState.State.jumpCount = 0; } if (command.jump && isOnGround) { characterPredictedState.State.jumpCount = 1; newPhase = CharacterPredictedState.StateData.LocoState.Jump; } if (command.jump && characterPredictedState.State.locoState == CharacterPredictedState.StateData.LocoState.InAir && characterPredictedState.State.jumpCount < 2) { characterPredictedState.State.jumpCount = characterPredictedState.State.jumpCount + 1; characterPredictedState.State.velocity.y = 0; newPhase = CharacterPredictedState.StateData.LocoState.DoubleJump; } if (characterPredictedState.State.locoState == CharacterPredictedState.StateData.LocoState.Jump || characterPredictedState.State.locoState == CharacterPredictedState.StateData.LocoState.DoubleJump) { if (phaseDuration >= Game.config.jumpAscentDuration) { newPhase = CharacterPredictedState.StateData.LocoState.InAir; } } } // Set phase start tick if phase has changed if (newPhase != CharacterPredictedState.StateData.LocoState.MaxValue && newPhase != characterPredictedState.State.locoState) { characterPredictedState.State.locoState = newPhase; characterPredictedState.State.locoStartTick = time.tick; } if (debugCharacterMove.IntValue > 0) { // Only show for one player if (lastUsedFrame < Time.frameCount) { lastUsedFrame = Time.frameCount; int o = Time.frameCount % movehist_x.Length; movehist_x[o] = characterPredictedState.State.position.x % 10.0f; movehist_y[o] = characterPredictedState.State.position.y % 10.0f; movehist_z[o] = characterPredictedState.State.position.z % 10.0f; DebugOverlay.DrawGraph(4, 4, 10, 5, movehist_x, o, Color.red, 10.0f); DebugOverlay.DrawGraph(4, 12, 10, 5, movehist_y, o, Color.green, 10.0f); DebugOverlay.DrawGraph(4, 20, 10, 5, movehist_z, o, Color.blue, 10.0f); } } if (time.tick != characterPredictedState.State.tick + 1) { GameDebug.LogError("Update tick invalid. Game tick:" + time.tick + " but current state is at tick:" + characterPredictedState.State.tick); } characterPredictedState.State.tick = time.tick; // Apply damange impulse from previus frame if (time.tick == characterPredictedState.State.damageTick + 1) { characterPredictedState.State.velocity += characterPredictedState.State.damageDirection * characterPredictedState.State.damageImpulse; characterPredictedState.State.locoState = CharacterPredictedState.StateData.LocoState.InAir; characterPredictedState.State.locoStartTick = time.tick; } var moveQuery = EntityManager.GetComponentObject <CharacterMoveQuery>(charAbility.character); // Simple adjust of height while on platform if (characterPredictedState.State.locoState == CharacterPredictedState.StateData.LocoState.Stand && characterPredictedState.groundCollider != null && characterPredictedState.groundCollider.gameObject.layer == m_platformLayer) { if (characterPredictedState.altitude < moveQuery.settings.skinWidth - 0.01f) { var platform = characterPredictedState.groundCollider; var posY = platform.transform.position.y + moveQuery.settings.skinWidth; characterPredictedState.State.position.y = posY; } } // Calculate movement and move character var deltaPos = Vector3.zero; CalculateMovement(ref time, characterPredictedState, ref command, ref deltaPos); // Setup movement query moveQuery.collisionLayer = characterPredictedState.teamId == 0 ? m_charCollisionALayer : m_charCollisionBLayer; moveQuery.moveQueryStart = characterPredictedState.State.position; moveQuery.moveQueryEnd = moveQuery.moveQueryStart + (float3)deltaPos; Profiler.EndSample(); }