Problem fixed itself without any editing of code.
UI and GUI not updating score?
I have been searching for hours on why my score will not update and followed about 4 tutorials on how to make this work.
I need a score in the top-left corner to update every time an "avoid" (object in game) is destroyed. I have 2 classes in use for this. avoidBehaviour which controls the "avoid" individually and a controller.
avoidBehaviour - for when the "avoid" is destroyed:
I first get the namespace/other class
public avoidInstantiate avoidInstantiate;
Then I call the UpdateScore from the controller class, when the event OnMouseDown on the "avoid"
private void OnMouseDown()
{
Destroy(gameObject);
avoidInstantiate.UpdateScore();
}
controller - Used to show the score UI, keep count of the score and update the UI
Import Using UnityEngine.UI
using UnityEngine.UI;
Then my code for the rest is here
private int score;
public Text scoreText;
//happens once on start of game
void Start()
{
score = 0;
SetScoreText();
}
public void UpdateScore()
{
//Debug.Log("s1 " + score);
score = score + 1;
SetScoreText();
//Debug.Log("s2 " + score);
}
void SetScoreText()
{
scoreText.text = "Score: " + score.ToString();
}
There are two problems.
The score is displaying at the start as "Score: 0", but never updates.
The score seems to carry over from the last run of the game. So I run the game the first time and get to a score of 10. The following time I run the game, the score starts at 10.
Thank you in advance everyone. I know this question is always asked, but I just cannot find the problem.
Hi @$$anonymous$$axLouis,
All you probably need to do is call UpdateScore()
before destroy like so
avoidBehaviour
private void On$$anonymous$$ouseDown()
{
avoidInstantiate.UpdateScore();
Destroy(gameObject);
}
or better yet you can use a coroutine like so
avoidBehaviour
private void On$$anonymous$$ouseDown()
{
StartCoroutine(DestroySelf());
}
IEnumerator DestroySelf()
{
avoidInstantiate.UpdateScore();
yield return new WaitForSeconds(0.05f); // change this time as needed (must be greater than 0)
Destroy(gameObject);
}
But I would like to know, what object is avoidBehaviour
attached to, is this object instantiated and how is the reference variable avoidInstantiate
set in the avoidBehaviour
script?
I ask these questions because if the object avoidBehaviour
attached to is instantiated then you can not rely on references set on prefabs.
Oh and the avoidBehaviour is attached to an "avoid" prefab.
Hi @$$anonymous$$axLouis,
That is the problem. Take a look at your prefab under the project tab. Now take a look at Target
and Avoid Instantiate
on the attached Avoid Behaviour
script. You will see that they are not set even though you initially set them when creating the initial prefab.
As mentioned, you need to dynamically set them at runtime in either the Awake()
or the Start()
function.
There are several ways you can accomplish this depending how you have your game set up. Below is just one example (for the target I am using the player as an example)
//happens once on start of game
private void Start()
{
target = GameObject.FindWithTag("Player").transform;
avoidInstantiate = GameObject.Find("Controller").GetComponent<AvoidInstantiate>();
}
Now during runtime, take a look at one of the instantiated objects in the hierarchy and verify that the target
and avoidInstantiate
references are set.
BTW, you should consider making the classes for AvoidInstantiate
and AvoidBehaviour
start with a capital (good coding practice is to use upper camel case). This is not good
public avoidInstantiate avoidInstantiate;
this is better
public AvoidInstantiate avoidInstantiate;
but that means changing the file name (can be don easily in Unity) and changing the class name.
Answer by MaxLouis · Dec 09, 2016 at 12:54 AM
Hi @Mavina and thanks for helping,
I have made the changes but it is no different. Here is the source code for both classes.
Controller (Ignore the class name - just me being lazy):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class avoidInstantiate : MonoBehaviour
{
public GameObject avoid;
public Quaternion spawnRotation;
public float spawnSpeed;
public int sideNumber;
public float posX;
public float posY;
public float timeLeftUntilSpawn = 0f;
public float secondsBetweenSpawn = 3f;
public float startTime = 0f;
public float SHeight = Screen.height;
public float SWidth = Screen.width;
private int score;
public Text scoreText;
//happens once on start of game
void Start()
{
score = 0;
SetScoreText();
}
public void UpdateScore()
{
//Debug.Log("s1 " + score);
score = score + 1;
SetScoreText();
//Debug.Log("s2 " + score);
}
void SetScoreText()
{
scoreText.text = "Score: " + score.ToString();
}
// Update is called once per frame
void Update()
{
timeLeftUntilSpawn = Time.time - startTime;
//spawn speed
if (secondsBetweenSpawn >= 0.4f){
secondsBetweenSpawn -= 0.001f;
}
else{
secondsBetweenSpawn = 0.4f;
}
if (timeLeftUntilSpawn >= secondsBetweenSpawn){
startTime = Time.time;
timeLeftUntilSpawn = 0;
AvoidSpawning();
}
}
public void AvoidSpawning()
{
//random spawn side
sideNumber = Random.Range(1, 5);
//left
if (sideNumber == 1)
{
posX = -Screen.width;
posY = Random.Range(-Screen.height, Screen.height);
InstantiateAvoid();
}
//top
else if (sideNumber == 2)
{
posX = Random.Range(-Screen.width, Screen.width);
posY = Screen.height;
InstantiateAvoid();
}
//right
else if (sideNumber == 3)
{
posX = Screen.width;
posY = Random.Range(-Screen.height, Screen.height);
InstantiateAvoid();
}
//bottom
else if (sideNumber == 4)
{
posX = Random.Range(-Screen.width, Screen.width);
posY = -Screen.height;
InstantiateAvoid();
}
}
//Instantiate and positioning of avoids
void InstantiateAvoid()
{
Vector3 spawnPosition = new Vector3(posX, posY, 0);
Instantiate(avoid, spawnPosition, spawnRotation);
}
}
avoidBehaviour:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class avoidBehaviour : MonoBehaviour {
public Transform target;
public float speed;
public avoidInstantiate avoidInstantiate;
//happens once on start of game
private void Start()
{
}
// Update is called once per frame
void Update ()
{
//speed of movement and target position
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
private void OnMouseDown()
{
StartCoroutine(DestroySelf());
}
IEnumerator DestroySelf()
{
avoidInstantiate.UpdateScore();
yield return new WaitForSeconds(0.05f);
Destroy(gameObject);
}
void OnCollisionEnter2D(Collision2D other)
{
Debug.Log("collision name = " + other.gameObject.name);
if (other.gameObject.name == "whiteCircle")
{
Destroy(other.gameObject);
}
}
}
And btw, the "avoid" are instantiated in the controller - an empty object.
Follow this Question
Related Questions
How do you add +1 to a score counter after a destroy script (C#)? 1 Answer
Can't update score text - small error breaks the game (Space Shooter Tutorial) 1 Answer
Combine text and buttons in scroll rect 0 Answers
Different Score for Active OnMouseDown objects 0 Answers
Kill counter doesn't stop counting 0 Answers