How to assign a value from another script variable? - c#

I accessing another script but her value is by default null.
I want to increase a score when colliding with the obstacle(+5).
Code:
playerscore.cs
public static class playerscore
{
public static int Score = 0; //static variable
}
TouchControll.cs
public Text scoretext;
void Awake()
{
//when I game quit and reenter the game then display the last score
PlayerPrefs.GetInt("score", playerscore.Score);
//this data on my ram not in harddisk
playerscore.Score = PlayerPrefs.GetInt("score", playerscore.Score);
//last score text update when I Reenter the game
scoretext.text = PlayerPrefs.GetInt("score").ToString();
print(scoretext.text);
//pass a score one scene to another scene
PlayerPrefs.SetInt("score", playerscore.Score);
scoretext.text = ("" + playerscore.Score);
PlayerPrefs.SetInt("score", playerscore.Score);
}
void OnCollisionEnter2D(Collision2D col)
{
//Debug.Log("oncollisionenter");
//when my player reaches the finish line then the score add=100; //work fine
if (col.gameObject.tag == "successfinishtag")
{
playerscore.Score += 100;
PlayerPrefs.SetInt("score", playerscore.Score);
scoretext.text = ("" + playerscore.Score);
//Debug.Log("scoreadd:" + playerscore.Score);
}
}
problem is here
I want the when my player collided with the obstacle then increment my score(+5) but the issue is not increasing my score
obstacle.cs
int incrementscore = 5;
TouchControll touchcontroll;
void Start()
{
GetComponent<TouchControll>();
}
//here player colliding with the obstacle
void OnTriggerEnter2D(Collider2D other)
{
foreach (Transform child in transform)
{
//Debug.Log("Inside foreach");
if (child.tag == "obstacleobject")
{
Animator anim = gameObject.GetComponent<Animator>();
anim.Play("animone");
}
}
playerscore.Score = PlayerPrefs.GetInt("score", playerscore.Score);
print(playerscore.Score);
Debug.Log(touchcontroll); //null
if (touchcontroll!= null)//null by default if(null != null) condition false
{
IncrementScore();
touchcontroll.scoretext.text = playerscore.Score.ToString();
}
}
void IncrementScore()
{
//Debug.Log("Inside Increment score");
playerscore.Score = playerscore.Score + incrementscore;
PlayerPrefs.GetInt("score", playerscore.Score);
//print(PlayerPrefs.GetInt("score", playerscore.Score));
PlayerPrefs.SetInt("score", playerscore.Score);
touchcontroll.scoretext.text = playerscore.Score.ToString();
}
I want the when my player collided with the obstacle then increment my score(+5) but the issue is not increasing my score how to solve the problem plz help.
How to solve this problem??

You're not assigning the result of GetComponent back to anything. Change obstacle.cs:
TouchControll touchcontroll;
void Start()
{
touchcontroll = GetComponent<TouchControll>();
}
However, GetComponent() only returns something if there is an instance of whatever object attached to the current game object. Are obstacle.cs and TouchControll.cs both attached to the current GameObject?
If not GetComponent is not going to work, use FindObjectOfType() instead:
void Start()
{
touchcontroll = FindObjectOfType<TouchControll>();
}
Here are the relevant pages from Unity scripting API for more info:
https://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html
https://docs.unity3d.com/ScriptReference/Object.FindObjectOfType.html

I have used in my game this scenario, where Player collide with coin and it increment coin value smoothly in my case. And I have also noticed there is simple difference with your script from me. U have to used FindObjectOfType<> and also have to called public int incrementscore = 5; Where U didn't use any access modifier. Below also include my code, U can take a look and get the idea. Hopefully this will work for U. thanks
public class CoinScript : MonoBehaviour
{
public int coinValue;
private LevelManager gameLevelManager;
// Start is called before the first frame update
void Start()
{
gameLevelManager = FindObjectOfType<LevelManager>();
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Triggered");
if (other.tag == "Player")
{
gameLevelManager.AddCoins(coinValue);
Destroy(gameObject);
}
}
}
//In LevelManager scripts
public void AddCoins(int numberOfCoins)
{
coins += numberOfCoins;
coinText.text = "Coins : " + coins;
}

Be simply , no use PlayerPrefs to other place
public static class playerscore
{
public static int Score
{
get { return PlayerPrefs.GetInt("score", 0);}
set { PlayerPrefs.SetInt("score", value); }
}
}

Related

how can i increase a number inside OnTriggerEnter

so i'm trying to increase my score every time i hit a wall (IsTrigger) but when i try to increase it, it doesn't work and still 100
so this is the code im having problem with
public Text scoreText;
public int score = 0;
void Start()
{
scoreText.text = score.ToString();
}
// Add Some Score To The Text When The Player Hit The CheckPoint
void OnTriggerEnter(Collider collider)
{
if (collider.name == "Player")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
}
When doing the trigger/collision test, make sure you add one
Debug.Log() outside of the condition check. In your case,
void OnTriggerEnter(Collider collider)
{
if (collider.name == "Player")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
Debug.Log("Just want make sure it indeed triggered.");
}
In most case, other than the issue with the code, it is highly possible the Rigidbody component is not added to the GO.
Another part which I am not sure since I am not using Unity for quite a long time now. You can move the UI text update code outside of the trigger if you want.
You need to update the text after changing the value, in your case you have to update "scoreText" according to the new "score" value. The simple way to do it is like that:
public Text scoreText;
public int score = 0;
void Start()
{
scoreText.text = score.ToString();
}
// Add Some Score To The Text When The Player Hit The CheckPoint
void OnTriggerEnter(Collider collider)
{
if (collider.name == "Player")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
}
It is better to have a method called "ChangeScore" which includes updating the "score" value and updating the "scoreText" at the same time. It is better to do so since you might forget to update the text in other cases if you have to change the score somewhere else.
Example:
[Tooltip("The player's initial score.")]
[SerializeField] private int initScore = 0;
// Serialized since you have to set the reference for it.
[SerializeField] private Text scoreText;
private int score = 0;
void Start()
{
ChangeScore(initScore);
}
// Method used to change the current player's score and update the text.
void ChangeScore(int changeValue)
{
this.score += changeValue;
scoreText.text = score.ToString();
}
// Add Some Score To The Text When The Player Hit The CheckPoint
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.name == "Player")
{
ChangeScore(100);
Debug.Log(score);
}
}
Another side note: I wouldn't use tags or names while checking colliding, its better to check if the colliding object got the PlayerController script
if(collider.GetComponent<PlayerController>())
instead of
if (collider.gameObject.name == "Player")
i fixed it i put the code on the Player script not on the CheckPoint script
void OnTriggerEnter(Collider collider)
{
if (collider.tag == "ScoreCheckPoint")
{
score += 100;
scoreText.text = score.ToString();
Debug.Log(score);
}
}

Variable is giving different values in different areas of the script (and when accessed in other scripts) and not updating the value

I am making a tower defense game and everytime I summon an enemy, i add 1 to the enemyCount variable. and everytime the enemy reaches the endpoint, I subtract 1 to the same variable. Default value is zero.
For some reason the variable gives different values in different parts of the script. I have 2 other scripts that has access to enemyCount. One is the PlayerUI script which just displays it, and the other is the enemyMovement script which is suppose to subtract 1 to it everytime the enemy object is destroyed.
The value of enemyCount in PlayerUI is 0, and it updates when the subtraction happens so it becomes -1.
Now when i run the game again, it retains the value of -1, and when subtracted to -2, its -2 that is displayed on the next run.
The value of enemyCount when I log it in the update function inside the script is that it updates to +1 when the enemy is summoned but doesnt update when the enemy is destroyed.
Can anyone point out what i did wrong?
WaveSpawner script:
public Transform enemyPrefab;
private Transform[] spawners;
private bool summonWave = false;
private float countDown = 2;
private int enemyPerWave = 1;
private int waveCtr = 0;
private int enemyCount;
void Awake() {
spawners = new Transform[transform.childCount];
for (var i = 0; i < spawners.Length; i++) {
spawners[i] = transform.GetChild(i);
}
}
void Start() {
enemyCount = 0;
}
void Update() {
if(countDown <= 0) {
summonWave = true;
countDown = 999;
}
if (summonWave) {
StartCoroutine(waveSpawner());
}else {
countDown -= Time.deltaTime;
}
Debug.Log(enemyCount); //GIVES THE RIGHT VALUE BUT DOESNT SUBTRACT 1 WHEN ENEMY IS DESTROYED
}
public int getEnemyCount() { //Accessed by the PlayerUI script. just to display it onscreen.
Debug.Log(enemyCount); // GIVES A VALUE OF N-1
return enemyCount;
}
public void reduceEnemyCount() { //Accessed by the EnemyMovement script.
enemyCount--; //IF THE ENEMY REACHES THE END, THIS FUNCTION IS CALLED AND THEN THE ENEMY OBJECT IS DESTROYED
}
IEnumerator waveSpawner() {
waveCtr++;
summonWave = false;
for (int i = 0; i < enemyPerWave; i++) {
summonEnemies();
yield return new WaitForSeconds(0.3f);
}
}
void summonEnemies() {
enemyCount += 1; //ADDS 1 TO THE VARIABLE EVERY TIME I SPAWN AN ENEMY UNIT. IN THIS CASE JUST 1
Instantiate(enemyPrefab, spawners[0].position, spawners[0].rotation);
//Instantiate(enemyPrefab, spawners[1].position, spawners[1].rotation);
//Instantiate(enemyPrefab, spawners[2].position, spawners[2].rotation);
//Instantiate(enemyPrefab, spawners[3].position, spawners[3].rotation);
}
}
EnemyMovement script:
public WaveSpawner spawner;
private float speed = 35f;
private int numberOfCycles = 2;
private Transform target;
private Transform startingPoint;
private int cycleCtr = 0;
private bool isDestroyed;
void Start() {
target = getClosestWaypoint(Waypoints.points);
startingPoint = target;
isDestroyed = false;
}
void Update() {
Vector3 dir = target.position - transform.position;
transform.Translate(dir.normalized * speed * Time.deltaTime, Space.World);
if (Vector3.Distance(transform.position, target.position) <= 0.2f && !isDestroyed) {
if (cycleCtr == numberOfCycles) {
spawner.reduceEnemyCount(); //subtracts the enemyCount in WaveSpawner
isDestroyed = true;
Destroy(gameObject); //destroying the enemy unit
} else {
if (target.name == startingPoint.name) {
cycleCtr++;
}
target = getToNextWaypoint(target);
}
}
}
PlayerUI script:
public Text enemyCount_UI;
[SerializeField]
private WaveSpawner spawner;
private int enemyCount_var;
void Start() {
enemyCount_UI.text = "Enemy count: 0";
enemyCount_var = 0;
}
void Update() {
enemyCount_var = spawner.getEnemyCount();
enemyCount_UI.text = "Enemy count: " + enemyCount_var.ToString();
}
I believe it is because you have assigned WaveSpawner prefab to EnemyMovement prefab and PlayerUI object. And you also probably have instance of WaveSpawner added somewhere in the scene.
Let's call WaveSpawner (from prefab) a PrefabSpawner and WaveSpawner (from scene) a SceneSpawner. When game is started, SceneSpawner is created. It has its own value of enemy count. When you spawn a prefab of EnemyMovement it is referencing PrefabSpawner, not SceneSpawner. What happens, is that SceneSpawner always incremets its own enemyCount, while EnemyMovement decreases count on PrefabSpawner. Because PlayerUI is also accessing PrefabSpawner it sees its value instead of SceneSpawner.
Try changing the spawning to this:
void summonEnemies() {
enemyCount += 1; //ADDS 1 TO THE VARIABLE EVERY TIME I SPAWN AN ENEMY UNIT. IN THIS CASE JUST 1
var enemyInstnace = Instantiate(enemyPrefab, spawners[0].position, spawners[0].rotation);
enemyInstance.spawner = this;
}
Rather than having WaveSpawner script on both PlayerUI and EnemyMovement, you'll want to make sure they are accessing the same instance of the script.
If you haven't already, create an empty game object to be your "wave spawner" in the scene and drop the WaveSpawner script on that.
Then update PlayerUI and EnemyMovement to get a reference to that game object, and then its WaveSpawner script
public Text enemyCount_UI;
[SerializeField]
private GameObject waveSpawnerGameObject;
private WaveSpawner spawner;
private int enemyCount_var;
void Start() {
enemyCount_UI.text = "Enemy count: 0";
enemyCount_var = 0;
}
void Awake()
{
// Get the reference here
spawner = waveSpawnerGameObject.GetComponent<WaveSpawner>();
}
void Update() {
enemyCount_var = spawner.getEnemyCount();
enemyCount_UI.text = "Enemy count: " + enemyCount_var.ToString();
}
And do the same for your enemy movement and enemy prefabs

Saving Highscore with PlayerPrefs, then moving it to next scene (GameOver Screen)?

I have a game that involves destroying falling clocks in under a minute to beat the highscore. I currently have a script that keeps track of the score when a clock is hit. I'm attempting to display the highscore with this screen and save it with PlayerPrefs. While it will update the current score when a clock is it, it will not update the existing highscore text or save it upon starting the program again.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PickUp : MonoBehaviour
{
public GameObject explosionEffect;
public Rigidbody2D Clock;
public AudioClip pickupSound;
AudioSource audioSource;
public Text Score;
public Text highscore;
int Amount = 0;
public float SpeedUp = 1;
// Use this for initialization
void Start()
{
audioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter2D(Collider2D other)
{
{
if (other.tag == "Clock")
{
Destroy(Instantiate(explosionEffect.gameObject, transform.position, transform.rotation), 5f);
audioSource.PlayOneShot(pickupSound, 1F);
Amount++;
Score.text = Amount.ToString() + " Clocks" ;
//Code of concern.
if (Amount > PlayerPrefs.GetInt("Highscore", 0))
{
PlayerPrefs.SetInt("Highscore", Amount);
highscore.text = "Highscore: " + Amount.ToString();
PlayerPrefs.Save();
Debug.Log("HS");
}
//Speeds up the clocks when hit, until a limit is met.
if (Clock.velocity.y >= -30)
{
Clock.velocity += Vector2.down * SpeedUp;
Debug.Log("Speed is now " + Clock.velocity);
}
}
}
}
}
I'm also trying to figure out how to transfer that information over to a Gameover Scene. I'm not sure if I should rely on PlayerPrefs (if that can do the job, I don't know) or look into json to do that.

Counter to victory in Unity

have been having a problem while working in Unity. I simply want to increase a score every time a collision is made, but my code just isn't helping. I know it sounds basic but I've been looking around in the site for quite some time now and I haven't found an answer yet.
Here's the script:
I have already checked and the "VictoryScreen" is already made and built.
public class PaintScriptGreen : MonoBehaviour {
public GameObject CylGreen;
private int score = 0;
private Vector3 tempPos;
private Quaternion tempRot;
private GameObject tempCyl;
void Awake ()
{
}
public void AddScore (int scoreValue)
{
score += scoreValue;
}
void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Cylinder" && col.gameObject.tag != "TreeHolder")
{
tempPos = col.gameObject.transform.position;
tempRot = col.gameObject.transform.rotation;
Destroy (col.gameObject);
tempCyl = Instantiate(CylGreen, tempPos, tempRot) as GameObject;
AddScore (1);
if (score >= 4)
{
Application.LoadLevel ("VictoryScreen");
}
}
if ((col.gameObject.tag != "Player")&&(col.gameObject.tag != "PlayPart"))
{
// destroy self bullet
Destroy (this.gameObject);
}
}
if ((col.gameObject.tag != "Player")&&(col.gameObject.tag != "PlayPart"))
{
// destroy self bullet
Destroy (this.gameObject);
}
This is probably the culprit. You're destroying "this" anytime the above conditions aren't true. Is this script on the bullet? If so, you'll need to move the scoring mechanism to an object that isn't getting destroyed OR make it a static variable. I don't like static variables, but it is a possible solution.

How to save high score?

I am trying to save high score in my game. The high score is updated with the score during play. However, after level restarts, both (current score and high score) becomes zero.
How can I do this? What mistake I am doing?
Here is my code:
Generate
public class Generate : MonoBehaviour
{
private static int score;
public GameObject birds;
private string Textscore;
public GUIText TextObject;
private int highScore = 0;
private int newhighScore;
private string highscorestring;
public GUIText highstringgui;
// Use this for initialization
void Start()
{
PlayerPrefs.GetInt ("highscore", newhighScore);
highscorestring= "High Score: " + newhighScore.ToString();
highstringgui.text = (highscorestring);
InvokeRepeating("CreateObstacle", 1f, 3f);
}
void Update()
{
score = Bird.playerScore;
Textscore = "Score: " + score.ToString();
TextObject.text = (Textscore);
if (score > highScore)
{
newhighScore=score;
PlayerPrefs.SetInt ("highscore", newhighScore);
highscorestring = "High Score: " + newhighScore.ToString ();
highstringgui.text = (highscorestring);
}
else
{
PlayerPrefs.SetInt("highscore",highScore);
highscorestring="High Score: " + highScore.ToString();
highstringgui.text= (highscorestring);
}
}
void CreateObstacle()
{
Instantiate(birds);
}
}
Bird
public class Bird : MonoBehaviour {
public GameObject deathparticales;
public Vector2 velocity = new Vector2(-10, 0);
public float range = 5;
public static int playerScore = 0;
// Use this for initialization
void Start()
{
rigidbody2D.velocity = velocity;
transform.position = new Vector3(transform.position.x, transform.position.y - range * Random.value, transform.position.z);
}
// Update is called once per frame
void Update () {
Vector2 screenPosition = Camera.main.WorldToScreenPoint(transform.position);
if (screenPosition.x < -10)
{
Die();
}
}
// Die by collision
void OnCollisionEnter2D(Collision2D death)
{
if(death.transform.tag == "Playercollision")
{
playerScore++;
Destroy(gameObject);
Instantiate(deathparticales,transform.position,Quaternion.identity);
}
}
void Die()
{
playerScore =0;
Application.LoadLevel(Application.loadedLevel);
}
}
The problem is your variable highScore. It is always 0. In the game you ask
if (score > highScore)
And because you set highScore = 0 while declaring that variable, score is always greater.
My suggestion is that you should declare it without value:
private int highScore;
In Start() you should give it value of saved high-score if it exists, and if it doesn't, give it 0 value:
highScore = PlayerPrefs.GetInt("highscore", 0);
That should work for you.
This line in Start(), won't actually do anything.
PlayerPrefs.GetInt ("highscore", newhighScore);
The second parameter is the default return value, if the given key doesn't exist.
But you're not using the return value for anything.
I think what you meant to do is:
newhighScore = PlayerPrefs.GetInt("highscore");
The default value will be 0, when not set explicitly.

Categories