I am trying to make a timing system in C#, and I am having trouble calculating delta time.
Here is my code:
private static long lastTime = System.Environment.TickCount;
private static int fps = 1;
private static int frames;
private static float deltaTime = 0.005f;
public static void Update()
{
if(System.Environment.TickCount - lastTime >= 1000)
{
fps = frames;
frames = 0;
lastTime = System.Environment.TickCount;
}
frames++;
deltaTime = System.Environment.TickCount - lastTime;
}
public static int getFPS()
{
return fps;
}
public static float getDeltaTime()
{
return (deltaTime / 1000.0f);
}
The FPS counting is working correctly, but the delta time is faster than it should be.
Value of System.Environment.TickCount changes during the execution of your function which is causing deltaTime to move faster than you expect.
Try
private static long lastTime = System.Environment.TickCount;
private static int fps = 1;
private static int frames;
private static float deltaTime = 0.005f;
public static void Update()
{
var currentTick = System.Environment.TickCount;
if(currentTick - lastTime >= 1000)
{
fps = frames;
frames = 0;
lastTime = currentTick ;
}
frames++;
deltaTime = currentTick - lastTime;
}
public static int getFPS()
{
return fps;
}
public static float getDeltaTime()
{
return (deltaTime / 1000.0f);
}
Related
I have one rather ambiguous problem in my C# (Unity) code. It lies in the fact that my player disappears because of the prescribed lines about the spawnpoint. Because of them, my player simply disappears when I run the game
The lines where the problem is possible are 22, 109-112. Please help me with this problem. Thank you very much in advance
But I need spawnpoint for further work. Thank you very much in advance!
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public static GameManager instance;
private void Awake()
{
if(GameManager.instance != null)
{
Destroy(gameObject);
Destroy(player.gameObject);
Destroy(floatingTextManager.gameObject);
Destroy(HUD);
Destroy(menu);
return;
}
instance = this;
SceneManager.sceneLoaded += LoadState;
SceneManager.sceneLoaded += OnSceneLoaded;
}
public List<Sprite> playerSprites;
public List<Sprite> weaponSprites;
public List<int> weaponPrices;
public List<int> xpTable;
public Player player;
public Weapon weapon;
public FloatingTextManager floatingTextManager;
public Animator misMenuAnim;
public RectTransform hitpointBar;
public GameObject HUD;
public GameObject menu;
public int pesos;
public int experience;
public void ShowText(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration)
{
floatingTextManager.Show(msg, fontSize, color, position, motion, duration);
}
public bool TryUpgradeWeapon()
{
if (weaponPrices.Count <= weapon.weaponLevel)
return false;
if(pesos >= weaponPrices[weapon.weaponLevel])
{
pesos -= weaponPrices[weapon.weaponLevel];
weapon.UpgradeWeapon();
return true;
}
return false;
}
public void OnHitpointChange()
{
float ratio = (float)player.hitpoint / (float)player.maxHitpoint;
hitpointBar.localScale = new Vector3(1, ratio, 1);
}
public int GetCurrentLevel()
{
int r = 0;
int add = 0;
while(experience >= add)
{
add += xpTable[r];
r++;
if (r == xpTable.Count)
return r;
}
return r;
}
public int GetXpToLevel(int level)
{
int r = 0;
int xp = 0;
while(r < level)
{
xp += xpTable[r];
r++;
}
return xp;
}
public void GrantXp(int xp)
{
int currLevel = GetCurrentLevel();
experience += xp;
if (currLevel < GetCurrentLevel())
OnLevelUp();
}
public void OnLevelUp()
{
player.OnLevelUp();
OnHitpointChange();
}
public void OnSceneLoaded(Scene s, LoadSceneMode mode)
{
player.transform.position = GameObject.Find("SpawnPoint").transform.position;
}
public void Respawn()
{
misMenuAnim.SetTrigger("Hide");
UnityEngine.SceneManagement.SceneManager.LoadScene("SampleScene");
player.Respawn();
}
public void SaveState()
{
string s = "";
s += "0" + "|";
s += pesos.ToString() + '|';
s += experience.ToString() + "|";
s += weapon.weaponLevel.ToString();
}
public void LoadState(Scene s, LoadSceneMode mode)
{
SceneManager.sceneLoaded += LoadState;
if (!PlayerPrefs.HasKey("SaveState"))
return;
string[] data = PlayerPrefs.GetString("SaveState").Split('|');
pesos = int.Parse(data[1]);
experience = int.Parse(data[2]);
player.SetLevel(GetCurrentLevel());
weapon.SetWeaponLevel(int.Parse(data[0]));
}
}
I have tried many ways over the course of a month, but none of them could solve the problem...
public class PipeSpawner : MonoBehaviour
{
public float maxTime = 1;
private float timer = 0;
public GameObject pipe;
public float height;
void Update()
{
if (timer > maxTime)
{
GameObject newpipe = Instantiate(pipe);
newpipe.transform.position = transform.position + new Vector3(0, Random.Range(-height, height), 0);
Destroy(newpipe, 15);
timer = 0;
}
}
}
Timer never passes max time, so the code in the update method never executes.
This is a neat way of doing "cooldowns" or "timers":
public class PipeSpawner : MonoBehaviour
{
public float futureTimestamp;
public GameObject pipe;
public float height;
void Start()
{
futureTimestamp = SetFutureTimestamp(5);
}
void Update()
{
if (Time.time > maxTime)
{
GameObject newpipe = Instantiate(pipe);
newpipe.transform.position = transform.position + new Vector3(0, Random.Range(-height, height), 0);
Destroy(newpipe, 15);
}
}
}
void SetFutureTimestamp(float seconds) {
futureTimestamp = Time.time + seconds;
}
Basically setting a timestamp in the future and checking if current time is larger than future time each update. Time.time > futureTimestamp
You could use class Timer and
Timer.Start();
create a global int variable
int tik = 0
and using the event Timer_Tik to count how many seconds passed (tik++).
To control the interval you should use Timer.Interval = 1000; witch is one second and final
if (tik > maxTime)
The Tag script has been working for me so far as an alternate to the unity tags up to this point, allowing me to assign multiple tags to an object at once. Now I want to create a method that will get all of the objects in the scene, filter them by the tag, and then return it as an array. The null reference exception refers to line 41 of the Tag.cs script. How do I fix this?
Tags.cs file
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tags : MonoBehaviour
{
public string[] startTags;
private string[] tags;
private void Start()
{
tags = startTags;
}
public bool FindTag(string search)
{
bool results = false;
for (int i = 0; i < tags.Length; i++)
{
if(search == tags[i])
{
results = true;
break;
}
}
return results;
}
//Find objects by custom script tags
//HERE IS WHERE THE METHOD IS CREATED
public static GameObject[] ObjectsByTag(string search)
{
//Get all objects in scene
GameObject[] allObjects = FindObjectsOfType<GameObject>();
GameObject[] storedObjects = new GameObject[allObjects.Length];
GameObject[] finalObjects;
//Filter
int count = 0;
for (int i = 0; i < allObjects.Length; i++)
{
if (allObjects[i].GetComponent<Tags>().FindTag(search)) //line 41
{
storedObjects[count] = allObjects[i];
count++;
}
}
//Assign final length
finalObjects = new GameObject[count];
//Reassign to final array
for (int i = 0; i < count; i++)
{
finalObjects[i] = storedObjects[i];
}
return finalObjects;
}
}
GameController.cs file (How it is being used
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameController : MonoBehaviour
{
//SCREEN START
//Get Screen Size
private float sHeight;
private float sWidth;
//Intended Screen Size
readonly float iH = 695f;
readonly float iW = 1540f;
//Convert
private float cH;
private float cW;
public float ConvertedHeight => cH;
public float ConvertedWidth => cW;
//SCREEN END
//MOUSE CAM START
//mousePostion
private float mX;
private float mZ;
public float MouseX => mX;
public float MouseZ => mZ;
//MOUSE CAM END
//EnemySpeedModifier
private float esm;
public float ESM
{
get { return esm; }
set { esm = value; }
}
//GameOver
private bool gameOver = false;
public bool GameOver
{
get { return gameOver; }
set { gameOver = value; }
}
//game speed
public float speed;
/*
//projectile list
private GameObject[] projectiles;
public GameObject[] Projectiles()
{
return projectiles;
}
public void Projectiles(GameObject value)
{
GameObject[] tempArray = projectiles;
tempArray[projectiles.Length] = value;
projectiles = tempArray;
Debug.Log("Projectile Count: " + projectiles.Length);
}
*/
//HERE IS WHERE IT IS USED
public GameObject[] ProjectilesInScene
{
get
{
return Tags.ObjectsByTag("projectile");
}
}
// Start is called before the first frame update
void Start()
{
//CONVERT SCREEN SIZES START
sHeight = Screen.height;
sWidth = Screen.width;
cH = iH / sHeight;
cW = iW / sWidth;
//CONVERT SCREEN SIZES END
}
// Update is called once per frame
void Update()
{
if (gameOver)
{
speed /= 1 + 0.5f * Time.deltaTime;
}
//Update mose position
mX = Input.mousePosition.x;
mZ = Input.mousePosition.y;
}
}
It seems that not all of your GameObject objects have the Tags component. Per the GameObject.GetComponent documentation
Returns the component of Type type if the game object has one attached, null if it doesn't.
If you know that some objects won't have the Tags component, your line 41 can use a simple null conditional operator:
if (allObjects[i].GetComponent<Tags>()?.FindTag(search) == true)
{
...
}
Note the ? after GetComponent<Tags>().
I wrote this simple anti speed hack for unity, and in theory and practice it does (somewhat) works. But if the game is being alt+tabbed or minimized, or even sometimes out of nowhere, code thinks time has changed. I'm assuming it has something to do with the time lag? Anyways, here's the script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class AntiHack : MonoBehaviour {
public static float systemTime = 0F;
public static float timer = 0F;
public static bool kickPlayer = false;
public float tolerance = 1.1f;
int resetTime = 0;
// UI Canvas
public Canvas antihack_Canvas;
void Start()
{
systemTime = System.DateTime.Now.Second;
timer = System.DateTime.Now.Second;
}
void Update()
{
if (systemTime == 10F || systemTime == 50F)
{
timer = System.DateTime.Now.Second;
resetTime = 0;
}
systemTime = System.DateTime.Now.Second;
timer += Time.deltaTime;
float result = timer - systemTime;
if (result < 0 )
{
result = result * -1;
}
if (result > tolerance && kickPlayer == true && systemTime > 10F)
{
KickPlayer();
}
if (result > 60 + tolerance && systemTime < 10F && kickPlayer == true)
{
KickPlayer();
}
}
//If player got caught do this
void KickPlayer()
{
Application.LoadLevel ("antiHackScreen");
}
public static void RestartTimer(bool kick)
{
timer = System.DateTime.Now.Second;
kickPlayer = kick;
}
}
And I'm using this when the level is being started:
public class restartTimer : MonoBehaviour {
// Use this for initialization
void Start () {
AntiHack.RestartTimer (true);
}
}
Any help would be appreciated! Thank you!
I have a Timer that counts down every 3 seconds (The white circle). It has a script attached called ReloadTimer.
I have a script that fires bullets (TankShooter) and reloads for 3 seconds.
How do I make it so that my countdown starts when I am reloading?
I tried looking at a lot of Unity forums and the advice didn't work.
ReloadTimer.cs
[ExecuteInEditMode]
public class ReloadTimer : MonoBehaviour
{
public Image filled;
public Text text;
public float maxValue = 3;
public float value = 0;
// UpdateReload is called once per frame
public void UpdateReload ()
{
value = Mathf.Clamp(value, 0, maxValue);
float amount = value / maxValue;
filled.fillAmount = amount;
text.text = value.ToString();
}
}
TankShooter
public int m_PlayerNumber = 1;
public Rigidbody m_Shell;
public Transform m_FireTransform;
public AudioSource m_ShootingAudio;
public AudioClip m_FireClip;
public float m_ShellVelocity = 100f;
private string m_FireButton;
public int maxAmmo = 5;
private int currentAmmo;
public float reloadTime = 2f;
private bool isReloading = false;
public ReloadTimer reloadTimer;
public class TankShootingT : NetworkBehaviour
{
public ReloadTimer reloadTimer;
private void Start()
{
if (!isLocalPlayer)
{
return;
}
currentAmmo = maxAmmo;
m_FireButton = "Fire" + m_PlayerNumber;
}
private void Update()
{
if (isReloading)
return;
if (currentAmmo <= 0)
{
StartCoroutine(Reload());
return;
}
reloadTimer.UpdateReload();
if (m_FireButton == "Fire1" && Input.GetButtonUp(m_FireButton))
{
// we released the button, have not fired yet
CmdShoot();
}
}
IEnumerator Reload()
{
isReloading = true;
Debug.Log("Reloading...");
yield return new WaitForSeconds(reloadTime);
currentAmmo = maxAmmo;
isReloading = false;
}
[Command]
private void CmdShoot()
{
currentAmmo--;
// Instantiate and launch the shell.
Rigidbody shellInstance = Instantiate(m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
shellInstance.velocity = m_ShellVelocity * m_FireTransform.forward;
// Server spawns the shell
NetworkServer.Spawn(shellInstance.gameObject);
m_ShootingAudio.clip = m_FireClip;
m_ShootingAudio.Play();
}
}
For starters, There isn't such thing as UpdateReload that would be "called once per frame" as this is not a predetermined Unity function, it is just a function that you created (You can read about this here). Another problem is that you didn't even call that function anywhere else in your scripts. And even if you did, Mathf.Clamp() needs to be placed in an Update() function so it can update it's value each frame.
I made some modifications to the scripts that you posted, but I haven't tested them yet. give it a try and let me know how it goes:
ReloadTimer.cs
public class ReloadTimer : MonoBehaviour
{
public static ReloadTimer Instance { set; get; }
public Image filled;
public Text text;
public float coolDownTime = 3;
public bool isCoolingDown = false;
void Awake()
{
Instance = this;
}
void Update()
{
if (isCoolingDown == true)
{
filled.fillAmount += 1.0f / coolDownTime * Time.deltaTime;
int percentageInt = Mathf.RoundToInt((filled.fillAmount / coolDownTime) * 10);
text.text = percentageInt.ToString();
}
}
}
TankShootingT.cs
public int m_PlayerNumber = 1;
public Rigidbody m_Shell;
public Transform m_FireTransform;
public AudioSource m_ShootingAudio;
public AudioClip m_FireClip;
public float m_ShellVelocity = 100f;
private string m_FireButton;
public int maxAmmo = 5;
private int currentAmmo;
public float reloadTime = 2f;
private bool isReloading = false;
public ReloadTimer reloadTimer;
public class TankShootingT : NetworkBehaviour
{
public ReloadTimer reloadTimer;
private void Start()
{
if (!isLocalPlayer)
{
return;
}
currentAmmo = maxAmmo;
m_FireButton = "Fire" + m_PlayerNumber;
}
private void Update()
{
if (isReloading)
return;
if (currentAmmo <= 0)
{
StartCoroutine(Reload());
return;
}
reloadTimer.UpdateReload();
if (m_FireButton == "Fire1" && Input.GetButtonUp(m_FireButton))
{
// we released the button, have not fired yet
CmdShoot();
}
}
IEnumerator Reload()
{
isReloading = true;
ReloadTimer.Instance.isCoolingDown = true;
Debug.Log("Reloading...");
yield return new WaitForSeconds(reloadTime);
currentAmmo = maxAmmo;
isReloading = false;
ReloadTimer.Instance.isCoolingDown = false;
ReloadTimer.Instance.filled.fillAmount = 0.0f;
}
[Command]
private void CmdShoot()
{
currentAmmo--;
// Instantiate and launch the shell.
Rigidbody shellInstance = Instantiate(m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
shellInstance.velocity = m_ShellVelocity * m_FireTransform.forward;
// Server spawns the shell
NetworkServer.Spawn(shellInstance.gameObject);
m_ShootingAudio.clip = m_FireClip;
m_ShootingAudio.Play();
}
}
Hope this helps a bit.