How to make score appear on GUI? - c#

I'm making a game, and I'm having trouble making the score appear on the game.
So far, this is all I have:
public class keepingScore : MonoBehaviour {
public static double homeScore;
// Use this for initialization
void Start ()
{
double homeScore = 5.0;
print(homeScore);
}
}
So my code is printing 5 to the console, and when I've tried other methods, it says it wont work because homeScore is not a string.
Any help guys?
Thanks!

Please try use GUI:
https://docs.unity3d.com/ScriptReference/GUI.html
or you can try Canvas GUI that must better:
https://docs.unity3d.com/Manual/UICanvas.html

So first of all what you need if you want to have score in your GUI is to have a Text component in your scene.
Once you have your Text component in your scene you need to create a script that will handle the score and add it to the Text component you have created. This is an example of a Score manager script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class keepingScore : MonoBehaviour {
public static double homeScore;
Text text;
void Awake () {
text = GetComponent<Text>();
homeScore = 0.0;
}
// Update is called once per frame
void Update () {
text.text = "Score: " + homeScore;
}
}
Now you can attach this script to the Text component you have created earlier. What this script does is first retreive the Text component that it is attached too and initialize a public static double homeScore that you can access and modify from any script by just doing keepingScore.homeScore. Finally the Update function will run every frame to update the Text component you have.
Now that you have a Text component in your scene with this script attached to it, you can start modifying the value of your score. From wherever you want. An example would be let's say when your player picks up a coin you want to give him 1 point, so if the player collides with the coin you add 1 to the homeScore
void OnCollisionEnter(Collision collision) {
if (collision.CompareTag("Coin"))
keepingScore.homeScore++;
}
This would for example add 1 to the score when the player collides with the coin.
You can do keepingScore.homeScore += pointAmount wherever you want to add points to the player and it will automatically update the GUI Text.

Related

Can I use a variable I got from the player into a text box?

I'm trying to make an app in Unity which requires your name and other details. I'm using the legacy Input Field to get the answers from the player which worked, but I can't seem to use the Input in any way other than Debug.Log.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ReadInput : MonoBehaviour
{
private string input;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void ReadStringInput(string s)
{
input = s;
Debug.Log(input);
}
}
I used this simple script to get the input but I have no clue how to actually use it in the game. It want it to say, for example, Welcome,(Person's Name/Input) outside of the log and actually into a text object.
If you right click in the hierarchy, under UI you can add a text object. I like to use a free package called Text Mesh Pro, which you can get in the asset store, but you don't need to.
Once you've made your text object, it should appear as a child of a gameobject called the Canvas. The text object should have a text field that you can access from script.
Text mytext;
public void UpdateMyText(string s)
{
mytext.text = s;
}
Here's the documentation
Just drag the text object into the script's mytext field in the inspector, and call that function when you want to update your text.

Display GUI with incrementing variable each collision

I have a GUI on my scene saying "Capsules Collected: 0/10" and a capsule object which has Collider that whenever the player enters the capsule , the capsule will be destroyed and the Capsules Collected will be increased by 1.
The Destroy Works well, the GUI isnt displaying. What is wrong with my code?
Here's my Code, I assigned this C# script on the Player itself:
using UnityEngine;
using System.Collections;
public class CapsuleGET : MonoBehaviour {
int capscore=0;
void Start(){
}
void OnTriggerEnter(Collider other) {
Destroy(other.gameObject);
capscore =capscore+1;
}
void Update(){
GUILayout.Label("Capsules Collected: "+capscore+"/10");
}
}
Like this .. very easy
using Unity.UI;
public class CapsuleGET
public Text displayScore; // DRAG to connect in Editor
void OnTriggerEnter(Collider other) {
Destroy(other.gameObject);
capscore =capscore+1;
displayScore.text = capscore.ToString();
1 - click to add canvas (don't forget to select 'scale with screen size')
2 - click to add Text, position as you want.
3 - in your script, "public Text score"
4 - drag from the "Text" to that variable
explanation with diagrams

Score Count not working on a prefab

This is semi complicated of a question but I'll do my best to explain it:
I am making this mobile game in which you have to shoot four cubes. I'm trying to make it so when the cubes are shot by a bullet, they're destroyed and a UI text says 1/4, to 4/4 whenever a cube is shot. But it's being really weird and only counts to 1/4 even when all four cubes are shot and destroyed. I put these two scripts on the bullets (I made two separate scripts to see if that would do anything, it didn't)
And to give a better idea of what I'm talking about, here's a screenshot of the game itself.
I've been using Unity for about 6 days, so I apologize for anything I say that's noob-ish.
EDIT
So I combined the two scripts onto an empty gameobject and here's the new script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class GameManagerScript : MonoBehaviour {
public GameObject cubes;
public Text countText;
public int cubeCount;
public Transform target;
// Use this for initialization
void Start () {
}
void OnTriggerEnter(Collider other)
{
cubes = other.gameObject;
}
// Update is called once per frame
void Update () {
cubes.transform.position = Vector3.MoveTowards(transform.position, target.position, 1f * Time.deltaTime);
if (cubes.gameObject.tag == "BULLET")
{
cubeCount = cubeCount + 1;
countText.text = cubeCount + "/4";
cubes.SetActive(false);
}
}
}
ANOTHER EDIT
I tried everything, so is there a way to detect when all the children in a parent on the Hierarchy are destroyed? Instead of counting up? This can give a better idea:
So I want to be able to detect when Cube, Cube1, Cube2, and Cube3 have all been destroyed.
The answer is pretty simple: Since every individual bullet has that script, each bullet has its own score.
For something like a score you want a single spot to store it, e.g. a script on an empty gameobject that serves as game controller. Just access that in the collision and increase the score (maybe have a look on singletons here).
You can combine those two scripts and actually it might be better to not have this on the bullet, but on the target because there are probably less of them which will save you some performance. (And it does more sense from a logical point of view.)
Edit:
I assume you create the bullets using Instantiate with a prefab. A prefab (= blueprint) is not actually in the game (only objects that are in the scene/hierarchy are in the game). Every use of Instantiate will create a new instance of that prefab with it's own version of components. A singleton is a thing that can only exist once, but also and that is why I mention it here, you can access it without something like Find. It is some sort of static. And an empty gameobject is just an object without visuals. You can easily create one in unity (rightclick > create empty). They are typically used as container and scriptholders.
Edit:
What you want is:
An empty gameobject with a script which holds the score.
A script that detects the collision using OnTriggerEnter and this script will either be on the bullets or on the targets.
Now, this is just a very quick example and can be optimized, but I hope this will give you an idea.
The script for the score, to be placed on an empty gameobject:
public class ScoreManager : MonoBehaviour
{
public Text scoreText; // the text object that displays the score, populate e.g. via inspector
private int score;
public void IncrementScore()
{
score++;
scoreText.text = score.ToString();
}
}
The collision script as bullet version:
public class Bullet : MonoBehaviour
{
private ScoreManager scoreManager;
private void Start()
{
scoreManager = GameObject.FindWithTag("GameManager").GetComponent<ScoreManager>(); // give the score manager empty gameobject that tag
}
private void OnTriggerEnter(Collider other)
{
if(other.CompareTag("Target") == true)
{
// update score
scoreManager.IncrementScore();
// handle target, in this example it's just destroyed
Destroy(other.gameObject);
}
}
}

Unity Slider decrease as timer

I'm trying to make a countdown timer but using a Unity Slider instead of text but I've ran across a few issues. So my current code is:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class CountdownTimer : MonoBehaviour {
//public Text timeText;
public float startingTime = 100.0f;
public Slider Timer;
// Use this for initialization
void Start () {
Timer = GetComponent<Slider> ();
}
// Update is called once per frame
void Update () {
startingTime -= Time.deltaTime;
Timer.value = startingTime;
if (startingTime <= 0)
{
startingTime = 0;
Application.LoadLevel ("GameOver");
}
}
}
This code works if I were to replace the slider with the text but not vice versa. My second issue is when I attach this code to my player and link the slider from the hierarchy, it disappears when I start the game.
Last issue is when I try to add an On Value Changed, I can link it to my player to get the functions from the code but from doing my research there isn't really anything I can link it to since I only have start and update. Scrollbars can use private voids and receive the dynamic float that way but I haven't been able to yet with Sliders
Example:
On Change Value
It does not work on the slider you say, you need to pass the max value as 100 on the slider component, or it uses 1 until the value gets between 0 and 1.
A UI item has to be under a Canvas to be rendered, so attaching it to your player makes it discarded from rendering. You can put the Canvas with the slider as child under the player object. But I would keep the canvas separated for clarity(POV).
The picture you added shows that you passed an object, but now you need to assign a method. Click the No Function and it will display all the available methods.

How do I access an updated variable between two scripts in Unity with C#?

Hopefully this isn't too much detail, I'm not used to asking programming questions.
I'm attempting to do the 3D Video Game Development with Unity 3D course that's on Udemy, though using C# instead of Javascript. I just finished up the tutorial that involves creating a space shooter game.
In it, a shield is created by the user when pressing a button. The shield has a "number of uses" variable that does not actually get used by the time the tutorial has finished. I'm trying to add it in, and have successfully managed to implement it so that with each use, we decrease the number of uses remaining, and no longer are able to instantiate the shield once that number is <=0.
This variable is stored on the player, and if I print it from the player, it returns the value I would expect.
However, I'm using a separate SceneManager.cs (this is where the tutorial placed the lives, and score, and timer variables ) where I print numbers into the GUI. My problem is that I cannot get my number of uses variable to stay current when I try to print it from the scene manager... it registers the initial value, but doesn't update after that.
Here is the Player Script
using UnityEngine;
using System.Collections;
public class player_script : MonoBehaviour {
// Inspector Variables
public int numberOfShields = 2; // The number of times the user can create a shield
public Transform shieldMesh; // path to the shield
public KeyCode shieldKeyInput; // the key to activate the shield
public static bool shieldOff = true; // initialize the shield to an "off" state
public int NumberOfShields
{
get{return numberOfShields;}
set{numberOfShields = value;}
}
// Update is called once per frame
void Update()
{
// create a shield when shieldKey has been pressed by player
if (Input.GetKeyDown (shieldKeyInput)) {
if(shieldOff && numberOfShields>0)
{
// creates an instance of the shield
Transform clone;
clone = Instantiate (shieldMesh, transform.position, transform.rotation) as Transform;
// transforms the instance of the shield
clone.transform.parent = gameObject.transform;
// set the shield to an on position
shieldOff = false;
// reduce the numberOfShields left
numberOfShields -=1;
}
}
print ("NumberOfShields = " + NumberOfShields);
}
public void turnShieldOff()
{
shieldOff = true;
}
}
when I run "print ("NumberOfShields = " + NumberOfShields);" I get the value I expect. (astroids trigger the turnShieldOff() when they collide with a shield.
Over in my Scene Manager however... this is the code I'm running:
using UnityEngine;
using System.Collections;
public class SceneManager_script : MonoBehaviour {
// Inspector Variables
public GameObject playerCharacter;
private player_script player_Script;
private int shields = 0;
// Use this for initialization
void Start ()
{
player_Script = playerCharacter.GetComponent<player_script>();
}
// Update is called once per frame
void Update ()
{
shields = player_Script.NumberOfShields;
print(shields);
}
// GUI
void OnGUI()
{
GUI.Label (new Rect (10, 40, 100, 20), "Shields: " + shields);
}
}
Any idea what I'm doing wrong that prevents shields in my SceneManager script from updating when NumberOfShields in my player_script updates?
I think you might have assigned a prefab into playerCharacter GameObject variable instead of an actual in game unit. In this case it will always print the default shield value of prefab. Instead of assigning that variable via inspector try to find player GameObject in Start function. You can for example give your player object a tag and then:
void Start() {
playerCharacter = GameObject.FindGameObjectWithTag("Player");
}

Categories