I have simple coin counter, in 2d Unity game. But It's count one coin as 2. I think that it's because of wrong converting int to string.
public GameObject coin; // Gameobject with coin
public Text CoinCounter; // Text with counter that shows in game
private float TotalCounter = 0; // Float for counting total amount of picked up coins
{
TotalCounter = Convert.ToInt32((CoinCounter.text)); // Converting text counter to Numbers
}
private void Update()
{
TotalCounter = Convert.ToInt32((CoinCounter.text)); // Updating Counter evry frame update
Debug.Log(TotalCounter); // Showing Counter in Console
}
private void OnTriggerEnter2D(Collider2D collision)
{
TotalCounter = (TotalCounter + 1); // adding 1 to total amount when player touching coin
CoinCounter.text = TotalCounter.ToString(); // Converting to Text, and showing up in UI
coin.SetActive(false); // Hiding coin
}
So, in Debug Log it's showing right Total amount, but in UI, It's Showing wrong number. As example, When Total Amount is 1 it's showing 2 etc.
It's better to write your convertor code into the trigger void , after that check it ; this might be happened because of update function, try like that and check again: `
public GameObject coin;
public Text CoinCounter;
private float TotalCounter = 0;
private void Update()
{}
private void OnTriggerEnter2D(Collider2D collision)
{
TotalCounter = (TotalCounter + 1);
Debug.Log(TotalCounter);
CoinCounter.text = TotalCounter.ToString();
Debug.Log(CoinCounter.text);
coin.SetActive(false);
}
`
You don't have to do it in Update but only when you actually change it.
The method you are looking for is probably int.TryParse
you should use int for amounts (unless will you have values like 1.5 coins later)
Than you execute your code everytime it collides ... with anything. You should only collide with a coin instead. Either use tags or compare with the referenced value in your case
public GameObject Coin; // Gameobject with coin
public Text CoinCounter; // Text with counter that shows in game
private int _totalCounter = 0; // Int for counting total amount of picked up coins
// I guess it's supposed to be Start here
void Start()
{
// Converting text counter to Numbers
int.TryParse(CoinCounter.text, out _totalCounter);
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject != Coin) return;
// later this should probably rather be
//if(collision.gameObject.tag != "Coin") return
_totalCounter += 1; // adding 1 to total amount when player touching coin
CoinCounter.text = _totalCounter.ToString(); // Converting to Text, and showing up in UI
Coin.SetActive(false); // Hiding coin
// later this should probably rather be
//collision.gameObject.SetActive(false);
}
Problem was not in converting, trigger worked twice. Need check if the coin is enabled before disabling it and adding to the coin counter. Eg:
if (coin.activeSelf)
{
coin.SetActive(false);
Debug.Log("Object is not active ");
TotalCounter += 1;
Debug.Log("Total Counter + :" + TotalCounter);
CoinCounter.text = TotalCounter.ToString();
Debug.Log("Text after +:" + CoinCounter.text);
}
Related
I have a "Player score: 100 pts" text with a timer that counts from 50 seconds to 0. I want to make it so every 5 seconds that goes by, 10 points are removed from the "Player score". So every 5 seconds it would be 10, 90, 80, etc.. how can I achieve that? I'm using Unity and coding in C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScoreCountdownn : MonoBehaviour
{
float scoreReductionTime = 5.0f;
int scoreReductionAmount = 10;
int maxScore = 100;
int scoreReduction = 5;
float timeUntilScoreReduction;
int currentScore;
void Start()
{
// Set the time until the next score reduction
timeUntilScoreReduction = scoreReductionTime;
// Set the current score to the max score
currentScore = maxScore;
}
// Can be Update or FixedUpdate depending on your goal
void Update()
{
// Reduce the time until score reduction
// by the time interval that has just passed
timeUntilScoreReduction -= Time.deltaTime;
// If the timeUntilScoreReduction reaches 0 or below,
// the score is reduced and the timeUntilScoreReduction
// is reset to the next time at which score reduction occurs
if (timeUntilScoreReduction <= 0.0f)
{
currentScore -= scoreReduction;
timeUntilScoreReduction = scoreReductionTime;
ScoreCountdown.text = currentScore;
}
Debug.Log(timeUntilScoreReduction);
Debug.Log(currentScore);
}
}
In your Update or FixedUpdate function, you can access Time.deltaTime.
It is the difference in time in seconds since the last call of the Update or FixedUpdate function. Hence, you can keep track of how much time has passed, by adding up these time intervals between every repetition.
Since you didn't include any code, I'll try to help you with some general code that you can look at for reference.
EDIT: The code was altered when the original question was edited to provide more information.
using UnityEngine;
using UnityEngine.UI;
public class ExampleClass : MonoBehaviour
{
float scoreReductionTime = 5.0f;
int scoreReductionAmount = 10;
int maxScore = 100;
int scoreReduction = 5;
float timeUntilScoreReduction;
int currentScore;
// You can drag your UI gameobject from the hierarchy
// to this field in the editor to link them.
// That way Unity knows what the gameobject is without
// you having to specify it here in the code
public GameObject ScoreCountdown;
void Start()
{
// Set the time until the next score reduction
timeUntilScoreReduction = scoreReductionTime;
// Set the current score to the max score
currentScore = maxScore;
// The gameobject has components, one of which is the text component.
// You have to access this component and set its text value
// to the desired string. Since the currentScore is an integer,
// and text is a string, you have to make a string of the integer.
ScoreCountdown.GetComponent<Text>().text = currentScore.ToString();
}
// Can be Update or FixedUpdate depending on your goal
void Update()
{
// Reduce the time until score reduction
// by the time interval that has just passed
timeUntilScoreReduction -= Time.deltaTime;
// If the timeUntilScoreReduction reaches 0 or below,
// the score is reduced and the timeUntilScoreReduction
// is reset to the next time at which score reduction occurs
if (timeUntilScoreReduction <= 0.0f)
{
currentScore -= scoreReduction;
timeUntilScoreReduction = scoreReductionTime;
ScoreCountdown.GetComponent<Text>().text = currentScore.ToString();
}
}
}
Note that in your question, you said that the score should decrease by 10 every 5 seconds, but then you gave the example of the score decreasing as 95, 90, 85, ... I chose to consider the first statement within the code, with a score reduction of 10 instead of the 5 in the second statement.
I'm creating a 2D car game using unity. Basic idea is adding coin count when player collect coins and display collected coin in the end-game menu. In my CoinCount script, in OnTriggerEnter2D I add coin value to current collected coins.But when game over some times its shows correct answer and some times it's add 2 or more values to collected values.
//CoinCount script
void OnTriggerEnter2D(Collider2D colInfo)
{
int inc = 0;
if (colInfo.gameObject.CompareTag("Coin"))
{
inc = 5;
coinCount += inc;
print("coinCount" + coinCount);
AudioManager.instance.PlaySound("Coin");
}
currentBalance += inc;
PlayerPrefs.SetInt("CoinCount", currentBalance);
PlayerPrefs.Save();
}
I tried maintain a public class for manage coins but it will give the same result. As an example if I collect 5 coins with the value of 5, it should display 25 as total coin count. sometimes it's 30 and 35.
public class GameScoreManager : MonoBehaviour
{
public static int value;
public Text currentScoreText;
// Start is called before the first frame update
void Start()
{
value = 0;
}
// Update is called once per frame
void Update()
{
currentScoreText.text = "$" + value.ToString();
print("Game coin count" + value);
}
}
This is the CoinCount script after I created the GameScoreManager class.
void OnTriggerEnter2D(Collider2D colInfo)
{
if (colInfo.gameObject.CompareTag("Coin"))
{
GameScoreManager.value += scoreValue;
}
}
I attached this script for each coins for destroy it self after hitting the player
public class DestroyCoin : MonoBehaviour
{
public GameObject effect;
//This script destroy the coin
void OnTriggerEnter2D(Collider2D colInfo)
{
if (colInfo.CompareTag("Player"))
{
Instantiate(effect, transform.position, transform.rotation);
Destroy(gameObject);
}
}
}
Much appreciate your help
I would go about solving such an issue by linking the addition of the coins value to the player's score DIRECTLY to destruction of the coin.
You might think that in the same game frame your coin gets a collision event to self destruct, and your player gets an event to add the coins value to his score.
If you're a guru and you know how the unity engine's internal mechanisms work by heart, be my guest and use that knowledge to write sloppy code that still works. But for a mere mortal like me, good practice can avoid this type of issues... (for example what if the coin's destruction causes no more collision for the player to add a value to the score?)
Use the same collision event to add a value to the player's score and destroy the coin for good, making sure such an event does not occur again. Even set the coin's value to 0 at that moment, just to be doubble-safe.
I manage to solve the problem by identifying the colider. Checked it's attached in the beginning and then disable the collision after the first hit.
void OnTriggerEnter2D(Collider2D colInfo)
{
int inc = 0;
//if (colInfo.CompareTag("Coin"))
if (colInfo.gameObject.CompareTag("Coin") && colInfo.gameObject.GetComponent<CircleCollider2D>().enabled)
{
colInfo.gameObject.GetComponent<CircleCollider2D>().enabled = false;
Destroy(colInfo.gameObject);
inc = 5;
coinCount += inc;
print("coinCount" + coinCount);
// AudioManager.instance.PlaySound("Coin");
currentBalance += inc;
}
PlayerPrefs.SetInt("CoinCount", currentBalance);
PlayerPrefs.Save();
}
Thanks and learnt a lot with this
Does any know if Unity has a way to count how many particles have been emitted by a particle system? So I could check to see if there has been an emission, like:
public ParticleSystem mySystem;
private int currentParticleCount;
private int lastParticleCount;
void Start () {
lastParticleCount = mySystem.getEmissionCount();
}
void Update () {
currentParticleCount = mySystem.getEmissionCount();
if(currentParticleCount>lastParticleCount) {
DoStuff();
}
lastParticleCount = currentParticleCount;
}
You can use ParticleSystem.particleCount to return the current number of particles. If that's not giving you the proper amount of particles, use the ParticleSystem.GetParticles function since that returns just the current number of alive particles. Below is an example for both of them:
private ParticleSystem ps;
// Use this for initialization
void Start()
{
ps = GetComponent<ParticleSystem>();
}
// Update is called once per frame
void Update()
{
Debug.Log("Particles Count: " + ps.particleCount);
Debug.Log("Particles Alive Count: " + GetAliveParticles());
}
int GetAliveParticles()
{
ParticleSystem.Particle[] particles = new ParticleSystem.Particle[ps.particleCount];
return ps.GetParticles(particles);
}
The exact feature that you are asking for is not build it, BUT:
You can know the current particles displayed by the system, so you can make a counter that acumulates the number, or if you know the "displaying time" you can do the maths.
Knowing the current particles:
ParticleSystem.particleCount https://docs.unity3d.com/ScriptReference/ParticleSystem-particleCount.html
I'm trying to make a game in unity (which uses c#) and what I am trying to accomplish is almost identical to what is done in the game Adventure capitalist. When you click on one of the companies, there is a "cooldown" timer. I put that in quotations because you don't get the money until after the timer has finished. I have looked at the other suggested questions and have managed to create the code below
public UnityEngine.UI.Text showCurrency;
public int money = 0;
public int moneyPerClick = 1;
public float timeToCollect = 3.0F;
private float timeStamp;
private bool buttonClicked;
void Start()
{
timeStamp = Time.time + timeToCollect;
}
void Update()
{
showCurrency.text = "Money: " + money;
if(buttonClicked && timeStamp > 0.0F)
{
timeStamp -= Time.time;
}
if (timeStamp == 0.0F)
{
money += moneyPerClick;
}
}
public bool Clicked()
{
buttonClicked = true;
return buttonClicked;
}
I currently get 1 error but that started happening after I added the showCurrency.text = "Money: " + money; part. So that needs to be fixed.
The code, as far as I can tell, it not working. I don't have the cooldown effect working with the image fill (which will be a problem for another day) So I can't actually see if the timer is counting down, but I guess I could have a Debug.Log and have a system.out line to test that. The other thing that isn't working is I'm not getting the new money amount to show up on screen.
This code is a beginners best guess at how it would be layed out and it is where I'm at. If it looks like I am using the methods wrong, that's probably because I am. Any further information to at least point me in the right direction would be greatly appreciated.
Unity's Update() method gets called every frame. So if you have the game set to 30 FPS, then Update() will get called 30 times every second.
Firstly, timeStamp -= Time.time subtracts the current time from your stored time every single frame (it gets to be a realllly small number really fast). As you have it, try changing your second if statement to an inequality check instead of checking for equality:
if (timeStamp <= 0.0F)
Alternatively, your Update() function could be simplified to something like this:
void Update()
showCurrency.text = "Money: " + getMoney();/*Make money into a property with a getter and setter, so that it will be easily changeable at run-time*/
if(buttonClicked && (Time.time >= timeStamp))
{
timeStamp = (Time.time + timeToCollect);
setMoney(getMoney() + moneyPerClick);
buttonClicked = false; /*Reset your button to be clickable again*/
/*You could also setup your setMoney() like setMoney(moneyPerClick), but that's not what you asked ;b*/
}
}
I have the a script called Timer.cs. This script is connected to some GUI Text, which displays the amount of time remaining in the game.
Also attached to this script is an Audio Source with my desired sound selected. When the clock reaches zero, the text changes to say "GAME OVER!" and the character controls lock up; however, the sound does not play.
All other instances of audio.Play() in my scene are working fine, and when I set the Audio Source to "Play On Awake", it plays without a problem. What could be the problem?
Using UnityEngine;
using System.Collections;
public class Timer : MonoBehaviour {
public float timer = 300; // set duration time in seconds in the Inspector
public static int sound = 1;
public static int go = 1;
bool isFinishedLevel = false; // while this is false, timer counts down
void Start(){
PlayerController.speed = 8;
PlayerController.jumpHeight = 12;
}
void Update (){
if (!isFinishedLevel) // has the level been completed
{
timer -= Time.deltaTime; // I need timer which from a particular time goes to zero
}
if (timer > 0)
{
guiText.text = timer.ToString();
}
else
{
guiText.text = "GAME OVER!"; // when it goes to the end-0,game ends (shows time text over...)
audio.Play();
int getspeed = PlayerController.speed;
PlayerController.speed = 0;
int getjumpHeight = PlayerController.jumpHeight;
PlayerController.jumpHeight = 0;
}
if (Input.GetKeyDown("r")) // And then i can restart game: pressing restart.
{
Application.LoadLevel(Application.loadedLevel); // reload the same level
}
}
}
Given that you are calling it as part of your Update routine, I'd have to guess that the problem is you calling it repeatedly. I.e. you're calling it every frame as long as timer <= 0.
You shouldn't call Play() more than once. Or at least not again while it is playing. A simple fix would be something along the lines of
if(!audio.isPlaying)
{
audio.Play();
}
See if that solves your problem, and then you can take it from there.
I had error using audio.Play(); and used following it fixed the error for me
GetComponent<AudioSource>().Play();