My FPS Counter is in-accurate any ideas why? - c#

When I start up my game it stays around 95-101 rapidly changing, in between all of those numbers.. but when I open up the stats bar I'm getting upper 200's low 300's
so wondering why that is still new to c# so be easy on me lol. heres the code
thanks in advance as always ^_^.
float deltaTime = 0.0f;
void Update()
{
deltaTime += (Time.deltaTime - deltaTime) * 0.1f;
}
void OnGUI()
{
int w = Screen.width, h = Screen.height;
GUIStyle style = new GUIStyle ();
Rect rect = new Rect (0, 0, w, h * 2 / 100);
style.alignment = TextAnchor.UpperRight;
style.fontSize = h * 2 / 100;
style.normal.textColor = new Color (255.0f, 255.0f, 255.0f, 1.0f);
float msec = deltaTime * 1000.0f;
float fps = 1f / deltaTime;
string text = string.Format ("({1:0.} fps)", msec, fps);
GUI.Label (rect, text, style);
}
}

In order to display a meaningful FPS rate you need to measure how many frames were rendered over a constant period of time, for example one second. Then only after that period do you display the calculated value on screen. This will provide for an average frames per second as opposed to an instantaneous frames per second, the latter of which is not particularly useful in most cases as it leads to widely fluctuating values.
Code
First define some fields:
DateTime _lastTime; // marks the beginning the measurement began
int _framesRendered; // an increasing count
int _fps; // the FPS calculated from the last measurement
Then in your render method you increment the _framesRendered. You also check to see if one second has elapsed since the start of the period:
void Update()
{
_framesRendered++;
if ((DateTime.Now - _lastTime).TotalSeconds >= 1)
{
// one second has elapsed
_fps = _framesRendered;
_framesRendered = 0;
_lastTime = DateTime.Now;
}
// draw FPS on screen here using current value of _fps
}
Cross-technology
It should be pointed out that the above code makes no particular use of Unity whilst still being reasonably accurate and is compatible with many frameworks and APIs such as DirectX; OpenGL; XNA; WPF or even WinForms.
When I start up my game it stays around 95-101 rapidly changing, in between all of those numbers.. but when I open up the stats bar I'm getting upper 200's low 300's
The ASUS VG248QE is 1ms and the max it can do is 144Hz so it is unlikely you are getting "upper 200's low 300's". FPS is meaningless when VSYNC is turned off on a non-GSYNC monitor. Is your VSYNC turned on?

In Unity, FPS is equivalent to number of Updates that occur in 1 second. This is because Update() is called every Time.deltaTime seconds.
InvokeRepeating method
You can also use InvokeRepeating to implement your own FPS counter while using only integers, like this:
private int FrameCounter = 0;
private int Fps = 0;
void Start()
{
InvokeRepeating("CountFps", 0f, 1f);
}
void Update()
{
FrameCounter++;
}
private void CountFps()
{
Fps = FrameCounter;
FrameCounter = 0;
}
Then just display the Fps variable in the OnGUI() method. Using this method, your Fps value will get updated every second; if you want more frequent updates, change the last argument of InvokeRepeating call and then adjust the Fps calculation accordingly.
Note, however, that InvokeRepeating takes Time.timeScale into account, so e.g. if you pause the game with Time.timeScale = 0f; the counter will stop updating until you unpause the game.
FixedUpdate method
Another approach is to count the FPS in FixedUpdate() method instead of OnGUI() or Update(). This gets called every Time.fixedDeltaTime seconds which is always the same, no matter what. The value of Time.fixedDeltaTime can be set globally for the project via menu Edit->Project Settings->Time, item Fixed Timestep.
In this case, you would count frames the same way (in Update), but update your FPS counter in FixedUpdate - which is basically the same as calling you own method with InvokeRepeating("CountFps", 0f, 0.02f) (0.02f being a typical Time.fixedDeltaTime value, but this depends on your project settings as per above).
Conclusion
Most of the time, you won't need to update the displayed FPS that often, so I personally like to use the InvokeRepeating method and 1 second intervals.

OnGUI function is called at las twice per frame (sometimes more). You are calculating your "FPS" inside OnGUI so it will almost never be accurate.
Defining :
deltaTime += (Time.deltaTime - deltaTime) * 0.05f;
will bring your FPS values closest to real but it will not be accurate if you calc it on OnGUI method.
I guess (not sure) that you should use FixedUpdate() instead of OnGUI() to calc your FPS. (also you don't need to change your deltaTime to multiply by 0.05f if you use FixedUpdate)

Related

Loads of objects being spawned in a short period after setting a random range

new to unity and C# and currently going through the create with code course. For the Prototype 2 exercise im trying to set it so that dogs are spawned between 2 and 5 seconds, each time varying slightly with randomness. However what happens at the moment is that they are spawned in random intervals, however there is then a huge increase in the amount of dogs spawned and it quickly fills up the scene and uses alot of processing power:
My SpawnManager script is as follows:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnManager : MonoBehaviour
{
public GameObject[] dogPrefabs;
private float spawnRangeX = 10;
private float spawnPosZ = 20;
private float startDelay = 2;
private float startspawnDelay = 1.5f;
public float RandomSpawnBeg = 2; //* Time.deltaTime;
public float RandomSpawnEnd = 5; //* Time.deltaTime;
public float RandomSpawn = Random.Range(RandomSpawnBeg, RandomSpawnEnd);
//public float boneDelay = 2.0f;
// Start is called before the first frame update
void Start()
{
InvokeRepeating("SpawnRandomAnimal", startDelay, RandomSpawn); //calls SpawnRandomAnimals method, after 2 seconds, every 1.5 seconds.
}
// Update is called once per frame
void Update()
{
}
void SpawnRandomAnimal()
{
int animalIndex = Random.Range(0, dogPrefabs.Length);
Vector3 spawnPos = new Vector3(Random.Range(-spawnRangeX, spawnRangeX), 0, spawnPosZ); //creating a Vector3 variable which sets a random value for the x axis between the spawnRange vars, 0 on the y axis, and the spawnPosZ var for the z axis.
Instantiate(dogPrefabs[animalIndex], spawnPos, dogPrefabs[animalIndex].transform.rotation); // spawn an animal from the index with an updated vector 3 position and rotation
//InvokeRepeating("SpawnRandomAnimal", startDelay, RandomSpawn);
Debug.Log("Spawn time is " + RandomSpawn);
}
}
Im a bit lost as to what could be causing this onslaught of dogs. I though that it may be telling it to do it every 2 - 5 frames as oppose to seconds, however when i * RandomSpawnBeg and RandomSpawnEnd by time.deltatime its still performing the same way.
Im really enjoying learning C# and unity but getting a bit stuck on how time works within it, if anyone can shed some light on this for me i would really appreciate it!
Thanks
first of all the InvokeRepeating function
public void InvokeRepeating(string methodName, float time, float repeatRate);
Invokes the method methodName in time seconds, then repeatedly every repeatRate seconds.
example InvokeRepeating("LaunchProjectile", 2.0f, 0.3f); it means that i'll create a projectile after 2 seconds from the Start frame and each 0.3 second i'll call this LaunchProjectile again . This is for the invoke repeating now we attack your problem :
Start() the Start() function is called in Unity once and only once at the first frame before calling the Update().
So basically you are invoking repeatedly with the same amount of frame rate each time because the randomizing happens only once.
To fix this just change where you call the randomizing function to this :
void Start()
{
InvokeRepeating("SpawnRandomAnimal", startDelay,Random.Range(RandomSpawnBeg, RandomSpawnEnd));
}
Now test this my friend and I hope your journey in Unity is full of joy.
I advice you to review this documentation it will help you out in many ways
Order of execution

Physics inconsistent even when using FixedUpdate() or Time.DeltaTime()

I want to move a rigidBody2D for a fixed amount of time with a fixed amount of velocity, when the player presses a button. I am calling the method in FixedUpdate() and the results are not consistent. Sometimes the rigidBody will travel more and sometimes less (Here is a relevant part of my code how i went about do this)
void Update()
{
GetPlayerInput();
}
private void FixedUpdate()
{
GroundCheck();
ApplayNormalPlayerMovement();
ApplyMove(); // This is the method of interest - I tried calling this in Update() with Time.DeltaTime - still inconsistent results.
MoveCooldownCounter(); // I tried calling this in Update() - inconsistent results also
}
IEnumerator MoveRB()
{
savedVelocityX = rb.velocity.x;
rb.gravityScale = 0;
savedXinput = xInput;
while (moveTimer >= 0)
{
if (xInput != 0)
xInput = 0;
cc.sharedMaterial = noFriction;
if (facingRight)
{
rb.velocity = new Vector2(moveSpeed, .0f); // I tried multiplying the moveSpeed by Time.DeltaTime and FixedDeltaTime - still inconsistent results.
} else
{
rb.velocity = new Vector2(-moveSpeed, .0f);
}
moveTimer -= Time.fixedDeltaTime;
yield return null;
}
moveTimer= moveDuration;
rb.gravityScale = gravity;
rb.velocity = new Vector2 (savedVelocityX, .0f);
xInput = savedXinput;
moveCooldownInternal -= Time.deltaTime; // I tried changing this to a specific float - still inconsistent results in physics..
}
private void MoveCooldownCounter()
{
if (moveCooldownInternal != moveCooldown)
{
moveCooldownInternal -= Time.deltaTime;
if (moveCooldownInternal <= 0)
{
moveCooldownInternal = moveCooldown;
}
if (moveCooldownInternal == moveCooldown && isGrounded)
canMove = true;
}
}
private void ApplyMove()
{
if (b_Fire3 && canMove)
{
StartCoroutine("MoveRB");
canMove= false;
}
}
Side note: right now i experience player input loss on occasions because i call this ApplyMove() in FixedUpdate() (will have to find a workaround for that as well - naturally if I can call the ApplyMove in Update() and get consistent results than this issue would be fixed).
Pleas excise my newbiness, i am trying to learn :)
Thank you in advance!
Add comment
Unity is a game engine. All game engines are based on the game loop - however Unity somewhat hides if from you, behind the 3 Update functions.
Not all parts are equally important. Drawing is generally skipped when the GPU is not ready or the FPS are capped. And Drawing and physics are generally calculated independantly of one another (unless you really messed up the development).
With Physics and Animations, you generally want to stuff to be consistent to the Game Tick Counter, not real time. All movement of game pieces and all animation should count in game ticks. Real Time is a nice figure and all, but ticks can have wildly different processing times. Especially since the CPU side drawing work also has to run in the same thread.
Just figure out your maximum ticks/second. And if you want to run something to run for "roughly" 10 ingame seconds, you multiply that value. It does not mater if the game on this machine needs 2 seconds for 200 ticks or 2 minutes for 200 ticks - with the number of ticks, the results will be consistent (unless the math itself is inprecise, like floating point math).
If it's not multiplayer game, it does not have to be hackproof and thus easiest fix is to capture the first frame of the button pressed and apply the force only on that frame, because of that we have to capture input on the Update function and also there immadietly apply the force even though it's suggested to do physics stuff in fixed update, but if you use delta time in update function for calculation it should be fine!
Now I think you know how to do that but I'll write it anyway we can either use apply force or set the velocity,
void Update()
{
if(Input.GetKeyDown("w"))
rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y + 5f*Time.deltaTime);
}
Note: I didn't test it but it should be allright since GetKeyDown returns true only on the first frame when the button was pressed,
If it was just GetKey and in case of jump we would check the grounding of player, we could be during jump and still be grounded on the second frame even if we jumped because of not really precise ground checking.
PS. Use fixedDeltaTime in fixedUpdate method!

Increase Light spotAngle overtime

I have a little question. I would like to increase the Light.spotAngle property over period of time. The written code works but I want this increase with speed, or something like that. I want to increase the value at spot angle at some speed, not to be directly 100, but from 30 slowly to grow by 10 to 100.
Transform thisLight = lightOB.transform.GetChild(0);
Light spotA = thisLight.GetComponent<Light>();
spotA.spotAngle = 100f;
I tried with Time.DeltaTime, but is not work.
Help!!!
Use Mathf.Lerp to lerp from value a to b. The a value is 10 and the b value is 100 according to your question. Do that in a coroutine function. that gives you control over how long you want that slow tansistion to happen.
When you click an Object, start the coroutine function.
The coroutine function:
IEnumerator increaseSpotAngle(Light lightToFade, float a, float b, float duration)
{
float counter = 0f;
while (counter < duration)
{
counter += Time.deltaTime;
lightToFade.spotAngle = Mathf.Lerp(a, b, counter / duration);
yield return null;
}
}
Will change Light's SpotAngle from 10 to 100 within 5 seconds.
public Light targetLight;
void Start()
{
StartCoroutine(increaseSpotAngle(targetLight, 30, 100, 5));
}
See this post for how to detect click on any GameObject.

Smoothly Lerp object based on button press Unity

Im creating a speedometer in Unity and I want my speedo arrow to smoothly lerp up to it's max angle based on the wither or not a button is pressed on. When the button is let go, I'd like the arrow to fall back to it's original rotation value.
However, I'm having issues trying to work out how to make my object lerp from its original position, to it's new position and back again. I've got it so when I press a button the objects jumps to a position, however, I need it to be smoother. Could someone please look over my code and point out what I need to do please?
float maxAngle = 100.0f;
float maxVel = 200.0f;
Quaternion rot0;
public float rotateValue;
// Use this for initialization
void Start ()
{
rot0 = transform.localRotation;
}
// Update is called once per frame
void Update ()
{
if(Input.GetKey(KeyCode.Space))
{
SetNeedle(rotateValue);
}
}
void SetNeedle(float vel)
{
var newAngle = vel * maxAngle / maxVel;
transform.localRotation = Quaternion.Euler(newAngle,0,0) * rot0;
float angle = Mathf.LerpAngle(minAngle, maxAngle, Time.time);
transform.eulerAngles = new Vector3(0, angle, 0);
}
From the documentation:
static float Lerp(float from, float to, float t);
Interpolates between a and b by t. t is clamped between 0 and 1.
Which means t goes from 0% to 100%. When t == 0.5f the result will be the middle angle between from to to.
Hence, if the needle needs to be moved in a smooth and constant speed, you should do:
time += Time.deltaTime; // time is a private float defined out of this method
if(time >= 1.5f) // in this example the needle takes 1.5 seconds to get to its maximum position.
time = 1.5f // this is just to avoid time growing to infinity.
float angle = Mathf.LerpAngle(from, to, time/1.5f); // time/1.5f will map the variation from 0% to 100%.
But that requires the from and to to be constant during the lerp fase.
So what you need to do is the following:
when you press Space, set time = 0, from = currentAngle and to = maxAngle; Obviously this must be done only once during the key down event.
when you release Space, set time = 0, from = currentAngle and to = 0. Also do this only once.
All right?
You should use Time.deltaTime, not Time.time. That should make it move correctly.
EDIT: deltaTime won't solve the problem alone, however. Sorry I didn't fully read your code at first.
In order to smoothly move the needle, you need to know where the needle is currently, where it needs to go, and how much time has elapsed since the last time it moved.
We know how much time has elapsed with Time.deltaTime. But your code currently doesn't take into consideration where the needle is. float angle = Mathf.LerpAngle(minAngle, maxAngle, Time.deltaTime); will always evaluate to roughly the same value, so your needle will never move beyond a tiny bit.
What you should do instead is lerp from the needle's current position towards the maxAngle.
float angle = Mathf.LerpAngle(currentAngle, maxAngle, Time.deltaTime);

Xna adding gravity to a 2d sprite

I am trying to simulate gravity in my first xna 2d game. I have the following
//Used for Jumping
double elapsedAirTime = 0.0;
double maxAirTime = 8.35;
//End Jumping
So I am trying to move the sprite up by a certain amount while the elapsedAirTime < maxAirTime
However, there is some issue where my code only seems to move the sprite up once and not multiple times during this segment of time. here is the code in my "player.cs" class, or the update method of the class.
if (newState.IsKeyDown(Keys.Space))
{
if(oldState.IsKeyUp(Keys.Space))
{
//if we are standing or jumping then change the velocity
if (playerState == PlayerStates.Standing)
{
playerState = PlayerStates.Jumping;
this.position.Y -= (float)(30.0 + ((1.2)*elapsedAirTime)*elapsedAirTime);
}
}
}
//if we are jumping give it some time
if (playerState == PlayerStates.Jumping)
{
if ((elapsedAirTime < maxAirTime) && position.Y < 3)
{
this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime);
elapsedAirTime += gameTime.ElapsedGameTime.TotalSeconds;
}
//otherwise time to fall
else
{
playerState = PlayerStates.Falling;
}
}
//add gravity to falling objects
if (playerState == PlayerStates.Falling || playerState == PlayerStates.Standing)
{
//if we are above the ground
if (this.position.Y < windowBot - 110)
{
//chnage state to falling
playerState = PlayerStates.Falling;
this.position.Y += 3.0f + ((float)(gameTime.ElapsedGameTime.TotalSeconds));
}
else
{
playerState = PlayerStates.Standing;
elapsedAirTime = 0.0f;
}
}
Any help is much appreciated, please and thank you!
To give your sprite the feel of gravity, you should add velocity and acceleration to your Sprite class. Then, create an Update method for the Sprite, and have acceleration be added to your velocity every update, and velocity added to position every update. Position should not be based on the amount of elapsed air time. You can set the acceleration to a constant gravitational value, and then add to the velocity of the Sprite whenever you jump. This will create a flowing parabolic jump that looks nice. If you want to include timing, you can pass the GameTime into the Sprite's Update method, and use it as a modifier on the velocity. Here is an example Update method:
void Update(GameTime gt)
{
int updateTime = gt.ElapsedGameTime.TotalMilliseconds - oldgt.ElapsedGameTime.TotalMilliseconds;
float timeScalar = updateTime / AVG_FRAME_TIME;
this.velocity += this.acceleration * timeScalar;
this.position += this.velocity;
oldgt = gt;
}
If you use timing, this method is a little complicated. You have to keep track of how much time the update took, then divide it by the average amount of time an update or frame should take to get the amount you should adjust your velocity by. Without timing, the method is very simple:
void Update()
{
this.velocity += this.acceleration;
this.position += this.velocity;
}
I would suggest using the simpler method until you understand exactly how timing works and why you need to implement it.
It looks like this line is at fault:
this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime);
I think you will find that this updates the sprites position quicker than you imagine, the sprite will move 330 pixels up the screen in 10 updates (assuming Game.IsFixedTimeStep == true) that is 1 tenth of a second realtime
It is likely that this is just updating so quickly that you don't get a change to see it rise before the && position.Y < 3 condition kicks in and changes the playerState.
It looks like you are trying to say - jump at a rate of x pixels per second for upto 8.5 seconds so long as space is held.
What you need for that is to change the calculation to this.position.y -= (float) (30 * gameTime.ElapsedGameTime.TotalSeconds), this will give a very liner movement to the jump action but it will mean that the sprite jumps at exactly 30 pixels per second.
If Game.IsFixedTimeStep == true - which is the default - the update gets called 60 times per second so gameTime.ElapsedGameTime.TotalSeconds is going to be about 0.1 every update. If something happens to cause an update to skip (rendering issues for example) then update will get delayed and gameTime.ElapsedGameTime.TotalSeconds may be 0.3 (the 2 updates skipped) but the formular still works out the correct jump rate.

Categories

Resources