I'm designing a game for my project and somehow the score(text) does not update after an action. It stuck at 0.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class uiManager : MonoBehaviour {
public Text scoreText;
bool gameOver;
int score;
// Use this for initialization
void Start () {
gameOver = false;
score = 0;
InvokeRepeating ("scoreUpdate", 1.0f, 0.5f);
}
// Update is called once per frame
void Update ()
{
scoreText.text = "Point: " + score;
}
void scoreUpdate()
{
if (gameOver == false)
{
score += 1;
}
}
public void gameOVER()
{
gameOver = true;
}
public void Play()
{
Application.LoadLevel ("MuachiJump");
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag == "branch")
{
score += 1;
Destroy(col.gameObject);
}
}
I just want to make sure is there any mistake in this code? All of them seem to be correct.
The code by itself seems fine. Make sure that uiManager is attached to an object in your scene that is active. In the Update method, if you add, for example, Debug.Log(score), it should print to the log every frame. If this isn't happening, you need to attach the script to an object in your scene as well as make sure that the Text object has a valid reference.
Do you have an active object with the script attached on your scene?
In my case the size of the textbox was the issue, just enlarge it and your score will be visible.
Related
I need help with my script. I really can't understand how to make it. I have a script that counts time but I don't know how to make it so that when the game is over the time appears in my Game Over scene as the highest score. I only need to save this high score for one time. After the game is closed the score can be removed. In the game, I have a countdown timer, when it reaches 0 the game is over.
This is my TimeCounter script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TimeCounter: MonoBehaviour
{
public Text timerText;
private float startTime;
bool finishCountTime = false;
public string minutes, seconds;
// Use this for initialization
void Start()
{
}
public void startTheTimer()
{
Invoke("startTime", 10);
startTime = Time.time;
}
public void stopTheTimer()
{
finishCountTime = true;
}
// Update is called once per frame
void Update()
{
float t = Time.time - startTime;
minutes = ((int)t / 60).ToString();
seconds = (t % 60).ToString("f2");
timerText.text = minutes + ":" + seconds;
}
}
and this is GameManager script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Threading;
public class GameManager: MonoBehaviour
{
[SerializeField] private float timer = 30;
private void Awake()
{
pop.onClicked += PopClicked;
}
private void OnDestroy()
{
pop.onClicked -= PopClicked;
}
private void PopClicked()
{
if (pop.Unclicked.Count == 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
private void Update()
{
if (timer <= 0)
{
SceneManager.LoadScene("GameOver");
}
}
}
Here is an example snippet of how to use DontDestroyOnLoad along with the SceneLoaded delegates.
using UnityEngine;
using UnityEngine.SceneManagement;
public class ExampleScript : MonoBehaviour
{
private float score;
private void Awake()
{
var objs = FindObjectsOfType(typeof(ExampleScript));
if (objs.Length > 1)
{
Destroy(this.gameObject);
}
DontDestroyOnLoad(this.gameObject);
}
private void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if(scene.name == "gameOver")
{
// display the time here as we are showing the score
Debug.Log(score);
}
else
{
// we loaded into another scene - presumably your game scene, so reset the score
score = 0;
}
}
}
As it is DontDestroyOnLoad, you will need to check if the current scene contains the object already and destroy it. As you have two scripts running your logic, you might need to slightly tweak it so that one of the managers is able to communicate to one another to pull your score or move it to the same script. I have greatly over-generalized your issue as I was not sure which part you did not understand.
Edit: Here is the more in-depth answer on how to achieve what you would like to do.
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class TestScript : MonoBehaviour
{
private float score; // our current score
private bool updateScore = false; // whether or not we should update our score UI every frame
private Text ScoreText = null; // our text object that updates our score
private void Awake()
{
// as the object is DontDestroyOnLoad, we need to check if another instance exists
// if one does, we need to delete it as if multiple exist in one scene, there could be issues
// if a player continually replays your scene where this object starts, then multiple will exist
var objs = FindObjectsOfType(typeof(TestScript));
if (objs.Length > 1)
{
Destroy(this.gameObject);
}
DontDestroyOnLoad(this.gameObject);
}
private void OnEnable()
{
// add the callback for when a scene is loaded
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
// remove the callback from when a scene is loaded
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
// grab the new reference to out score UI
ScoreText = GameObject.Find("Score").GetComponent<Text>();
// when we have the gameover scene, display our final score
if (scene.name == "gameover")
{
// display the time here as we are showing the score
ScoreText.text = "Final Score: " + score.ToString("#");
updateScore = false;
}
else
{
// we loaded into another scene - presumably your game scene, so reset the score
score = 0;
updateScore = true;
}
}
private void Update()
{
// if we are in the game scene and we should update score, update the score however you like
if(updateScore)
{
score += Time.deltaTime;
ScoreText.text = "Current Score: " + score.ToString("#");
}
// this is here solely for testing - instead of a real game just hit space to end the game and restart it
if(Input.GetKeyDown(KeyCode.Space))
{
if(SceneManager.GetActiveScene().name == "gameover")
{
SceneManager.LoadScene(0);
}
else
{
SceneManager.LoadScene("gameover");
}
}
}
}
Here is an example of the script working as well as the two scene hierarchies. For this to work exactly as I have it, you will need two scenes. In your build settings, the first scene will be your game scene, and then there needs to be some other scene in the build settings with the name gameover. As well, you will need to have some sort of UnityEngine.UI.Text component that is called Score in both scenes.
All of this can be changed, but this is what you need to do to get it to work as I have it set up.
Hello i have a problem with animation controller script used to play animations depending on which key is pressed
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimationController : MonoBehaviour
{
function UpdateAnimations()
{
if (Input.GetKeyDown(KeyCode.W))
{
animation.CrossFade("goup");
}
else if (Input.GetKeyDown(KeyCode.A))
{
animation.CrossFade("goleft");
}
else if (Input.GetKeyDown(KeyCode.D))
{
animation.CrossFade("goright");
}
else if (Input.GetKeyDown(KeyCode.S))
{
animation.CrossFade("godown");
}
}
void Start()
{
}
// Update is called once per frame
void Update()
{
UpdateAnimations();
}
It says that "Component.animation" is too old, and i should use GetComponent but i don't know how to
First of all you most probably mean void instead of function as your code is in c# not unityscript (which is also long deprecated by now)
And then Yes, how old is that code you got there? The direct accesses to things like Component.animation, Component.renderer, Component.camera were deprecated years ago ^^
As the error already tells you rather use e.g. Component.GetComponent like e.g.
public class AnimationController : MonoBehaviour
{
// Reference this via the Inspector in Unity
// via drag and drop. Then you don't need GetComponent at all
[SerializeField] private Animation _animation;
private void Awake()
{
// or as fallback get it on runtime
if(!_animation) _animation = GetCompoenent<Animation>();
}
// Update is called once per frame
private void Update()
{
UpdateAnimations();
}
private void UpdateAnimations()
{
if (Input.GetKeyDown(KeyCode.W))
{
_animation.CrossFade("goup");
}
else if (Input.GetKeyDown(KeyCode.A))
{
_animation.CrossFade("goleft");
}
else if (Input.GetKeyDown(KeyCode.D))
{
_animation.CrossFade("goright");
}
else if (Input.GetKeyDown(KeyCode.S))
{
_animation.CrossFade("godown");
}
}
}
How have you defined "animation" in your code?
you could try adding animation reference in the top of the code:
private Animation animation;
and in your Start() or Awake() method, add:
// will add reference to the animation to be the Animation component
// in this GameObject
animation = GetComponent<Animation>();
so I’m trying to create a respawn system as a beginner, and everything seems to be working the first time but the second time it seems to be unbehaving. If anyone knows how to help me, I would appreciate it
LevelControl:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelControl : MonoBehaviour
{
public int index;
public string levelName;
public GameObject GameOverPanel;
public static LevelControl instance;
private void Awake()
{
if (instance == null)
{
DontDestroyOnLoad(gameObject);
instance = GetComponent<LevelControl>();
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
//Loading level with build index
SceneManager.LoadScene(index);
//Loading level with scene name
SceneManager.LoadScene(levelName);
//Restart level
//SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
public void LoadLevel1()
{
SceneManager.LoadScene("Game");
}
public GameObject GetGameOverScreen()
{
return GameOverPanel;
}
}
PlayerMovement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public float runSpeed = 40f;
float horizontalMove = 0f;
bool jump = false;
bool crouch = false;
// Update is called once per frame
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
if (Input.GetButtonDown("Jump"))
{
jump = true;
}
if (Input.GetButtonDown("Crouch"))
{
crouch = true;
}
else if (Input.GetButtonUp("Crouch"))
{
crouch = false;
}
}
void FixedUpdate()
{
// Move our character
controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump);
jump = false;
//FindObjectOfType<GameManager>().EndGame();
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Enemy")
{
//Destroy(FindObjectOfType<CharacterController2D>().gameObject);
GameObject.Find("Player").SetActive(false);
LevelControl.instance.GetGameOverScreen().SetActive(true);
}
}
}
Error In Unity Video: https://imgur.com/a/Sr0YCWk
If your wondering what I'm trying to do, well, when the 2 colliders of the Player and Enemy collide, I want a restart button to pop up, and the Character to get destroyed, and after that restart the level as is.
You didn't provide much but I try to work with what we have.
In LevelController you have
private void Awake()
{
if (instance == null)
{
DontDestroyOnLoad(gameObject);
instance = GetComponent<LevelControl>();
}
}
First of all just use
instance = this;
;)
Then you are doing
LevelControl.instance.GetGameOverScreenn().SetActive(true);
I don't see your setup but probably GetGameOverScreenn might not exist anymore after the Scene reload while the instance still does due to the DontDestroyOnLoad.
Actually, why even use a Singleton here? If you reload the entire scene anyway you could just setup the references once via the Inspector and wouldn't have to worry about them later after scene changes...
Also
GameObject.Find("Player").SetActive(false);
seems odd .. isn't your PlayerController attached to the Player object anyway? You could just use
gameObject.SetActive(false);
Ok, Normally it would be easier just to do this:
if (collision.gameObject.tag == "Enemy")
{
//Destroy(FindObjectOfType<CharacterController2D>().gameObject);
gameObject.SetActive(false);
LevelControl.instance.GetGameOverScreen().SetActive(true);
But this will NOT work if you want to attach the script to any other gameobjects for any reason. If you are then first make a game object variable containing the player, like this:
public GameObject Player = GameObject.Find("Player");
Then say
Player.SetActive(false);
This creates a player gameobject which you can access by calling the variable.
When my player dies the score continues on and does not reset, it continues the score from the previous session. I would like to reset back to 0 once the player dies, I've added the two scripts
Score script:
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine;
public class ScoreScript : MonoBehaviour {
public static int scoreValue = 0;
Text score;
// Use this for initialization
void Start () {
score = GetComponent<Text>();
}
// Update is called once per frame
void Update () {
score.text = " " + scoreValue;
}
}
Player Script:
using UnityEngine;
using UnityEngine.SceneManagement;
public class Player : MonoBehaviour {
public float jumpForce = 10f;
public Rigidbody2D rb;
public SpriteRenderer sr;
public string currentColor;
public Color colorCyan;
public Color colorYellow;
public Color colorMagenta;
public Color colorPink;
void Start ()
{
SetRandomColor();
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Jump") || Input.GetMouseButtonDown(0))
{
rb.velocity = Vector2.up * jumpForce;
}
}
void OnTriggerEnter2D (Collider2D col)
{
if (col.tag == "ColorChanger")
{
ScoreScript.scoreValue += 1;
SetRandomColor();
Destroy(col.gameObject);
return;
}
if (col.tag != currentColor)
{
Debug.Log("GAME OVER!");
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
void SetRandomColor ()
{
int index = Random.Range(0, 4);
switch (index)
{
case 0:
currentColor = "Cyan";
sr.color = colorCyan;
break;
case 1:
currentColor = "Yellow";
sr.color = colorYellow;
break;
case 2:
currentColor = "Magenta";
sr.color = colorMagenta;
break;
case 3:
currentColor = "Pink";
sr.color = colorPink;
break;
}
}
}
It looks like scoreValue is a static variable, meaning it's maintained globally rather than per-instantiation of the ScoreScript behavior.
First off, I would change scoreValue to not be static. Then, just like you have for components such as RigidBody2D, I would add a public reference to the ScoreScript in your Player, drag that object to that field in the Unity editor, and then whenever making changes to scoreValue, use your new local reference to the ScoreScript. (So, scoreScript rather than ScoreScript).
Since like all behaviours, the ScoreScript will be reconstructed when the scene resets, this means it will then start at 0. It's not restarting right now because loading a new scene just remakes objects, it doesn't restart the entire scripting environment along with global static variables.
You need to be modifying the static variable inside of your ScoreScript whenever the conditions for death are validated in your Player component.
Judging by the source, it looks like the line:
if (col.tag != currentColor)
denotes the end of a game. If this is the case, you'll want to reference ScoreScript.score after the if statement and set the value of this static variable to 0 to reset the score upon death.
I am making a pinball game in Unity, and I have an issue. When the pinball collides with a cylinder to add points to the score, it does not work. I have tagged the cylinders in Unity and have attached this script to the pinball. It doesn't even show up in the debug log.
Thanks for any advice.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Score : MonoBehaviour {
public int scorePoint = 10;
public int MaxScore;
public Text ScoreText;
// Use this for initialization
void Start () {
ScoreText = GetComponent<Text>();
ScoreText.text = "Score: " + scorePoint;
}
void OnTriggerEnter (Collider other)
{
if (other.gameObject.tag == "Cylinder")
{
Debug.Log("Collision detected");
scorePoint+=10;
}
}
// Update is called once per frame
void Update()
{
}
}
Make sure you have a box collider on each object. OnTriggerEnter is only called when two box collider hit each other. This is the most likely culprit of why its not working but without more information I can't guarantee it.