Syncing UI Canvas to Photon Network | PunRPC - c#

I have an issue where I cannot sync UI Canvas information to PhotonNetwork. It syncs just fine without Photon, and I get correct information when I debug it. But if i start it with photon, it does not sync.
Code below:
void Start()
{
PV = GetComponent<PhotonView>();
Debug.Log("I know who is : " + PV);
}
void Update()
{
PV.RPC("DisplayHP", RpcTarget.All);
DisplayHP();
ShootTest();
Debug.Log("Player HP : " + playerHP);
}
}
[PunRPC]
void DisplayHP()
{
if(PV.IsMine)
{
showHP.text = playerHP.ToString();
}
}
}
possibly I am using it in wrong way, can someone please shed some lights what I am doing wrong in here? This is just an example from Health Canvas, other canvas also acting exactly same as health canvas.
Full script below :
[SerializeField] float playerHP = 100f;
[SerializeField] TextMeshProUGUI showHP;
[SerializeField] AudioClip audioClip;
public int armorCheck;
public int energyCheck;
float energyBack = 25;
//public PhotonView PV;
void Start()
{
// PV = GetComponent<PhotonView>();
}
public void EnergyPot()
{
//if(PV.IsMine)
//{
Ammo currentAmmo = GetComponent<Ammo>();
int energyCheck = GetComponent<Ammo>().GetCurrentAmmo(AmmoType.EnergyDrink);
if (energyCheck > 0)
{
playerHP = energyBack + playerHP;
if (playerHP >= 100)
{
playerHP = 100;
currentAmmo.ReduceCurrentAmmo(AmmoType.EnergyDrink);
}
}
//}
}
public void TakeDamage(float damage)
{
// if (PV.IsMine)
//{
Ammo currentAmmo = GetComponent<Ammo>();
int armorCheck = GetComponent<Ammo>().GetCurrentAmmo(AmmoType.Armor);
if (armorCheck <= 0)
{
playerHP -= damage;
if (playerHP <= 0)
{
GetComponent<DeathHandler>().HandleDeath();
AudioSource.PlayClipAtPoint(audioClip, Camera.main.transform.position);
GetComponent<Animator>().SetTrigger("Dead_Player");
}
}
else
{
currentAmmo.ReduceCurrentAmmo(AmmoType.Armor);
}
}
//}
//public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
//{
// if(stream.IsWriting)
// {
// //DisplayHP();
// stream.SendNext(playerHP);
// }
// else if (stream.IsReading)
// {
// //DisplayHP();
// playerHP = (float)stream.ReceiveNext();
// }
//}
void Update()
{
DisplayHP();
ShootTest();
}
void ShootTest()
{
if (Input.GetMouseButtonDown(0))
{
GetComponent<Animator>().SetBool("Shoot_Player", true);
// GetComponent<Animator>().SetTrigger("ShootPlayer");
}
// GetComponent<Animator>().SetBool("Shoot_Player", false);
}
void DisplayHP()
{
//if(PV.IsMine)
//{
showHP.text = playerHP.ToString();
//Debug.Log("PV works under DisplayHP, code : " + PV);
Debug.Log("Player HP : " + playerHP);
//}
}
}

You are only syncing a parameter less method call which updates a display .. but your are never updating the information to display: playerHP
PhotonView.RPC takes the method name, RpcTarget and then optionally as many parameters as you like / your method expects.
void Start()
{
PV = GetComponent<PhotonView>();
Debug.Log("I know who is : " + PV);
}
private void Update()
{
if(PV.IsMine)
{
ShootTest();
Debug.Log("Player HP : " + playerHP);
}
}
// only executed every 0.2 seconds to reduce traffic
void FixedUpdate()
{
if(PV.IsMine)
{
// pass in the value to sync
PV.RPC(nameof(DisplayHP), RpcTarget.Others, playerHP);
DisplayHP(playerHP);
}
}
[PunRPC]
void DisplayHP(float hp)
{
// receive the synced value if needed
playerHP = hp;
showHP.text = hp.ToString();
}
Actually to avoid more redundant network traffic you should use a property which automatically updates the display whenever it is changed and only sends the remote call whenever the playerHP actually changes like e.g.
[SerializeField] private float _playerHP;
private float playerHP
{
get => _playerHP;
set
{
_playerHP = value;
showHP.text = playerHP.ToString();
if(PV.IsMine)
{
// sync the change to others
PV.RPC(nameof(RemoteSetHP), RpcTarget.Others, _playerHP);
}
}
}
[PunRPC]
void RemoteSetHP(float hp)
{
// this executes the setter on all remote players
// and thus automatically also updates the display
playerHP = hp;
}
so whenever you set
playerHP = XY;
it automatically updates the display and if it is your photon view it sends the remote call to others and also update the value and display there.

Additional to my comment, here is an example. Let's assume you have Text for your HP and for other player HP. First, you change your HP by calling UpdateHP method, you update Text for your HP and send RPC to others, that updates otherHp on their clients (because you will be 'other' on their machines) with your new value for your HP.
public Text myHpText;
public Text otherHpText;
void UpdateHp(int hp)
{
myHpText.text = hp.ToString();
PV.RPC("UpdateOtherText", RpcTarget.Others, myHp);
}
[PunRPC]
void UpdateOtherText(int hp)
{
otherHpText.text = hp.ToString();
}

Related

Unity C# Health/Damage Script works as intended but returns Object Reference error [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 months ago.
Does anyone know why im getting this error?
Object reference not set to an instance of an object
HealthBar.TakeDamage (System.Int32 damage) (at Assets/Scripts/HealthBar.cs:61)
HealthBar.Update () (at Assets/Scripts/HealthBar.cs:36)
the code seems to work as intended when i try to run "TakeDamage()" but i recieve that error after it executes even though its giving me the correct behavior.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthBar : MonoBehaviour
{
public CharacterStats stats;
public Slider slider;
// Start is called before the first frame update
void Start()
{
slider.value = slider.maxValue;
}
// Updates the Current Hp Text
public Text valueText;
public void OnSliderChanged(float value)
{
valueText.text = value.ToString();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
HealDamage(30);
Debug.Log("Space");
}
if (Input.GetKeyDown(KeyCode.E))
{
TakeDamage(10);
Debug.Log("E");
}
if (Input.GetKeyDown(KeyCode.Q))
{
TempMaxHealth(5f,20);
Debug.Log("Q");
}
if (Input.GetKeyDown(KeyCode.T))
{
SetHealth(20);
Debug.Log("T");
}
if (Input.GetKeyDown(KeyCode.P))
{
PoisonDamage(2f,10);
Debug.Log("P");
}
}
// Take X amount of Damage
void TakeDamage(int damage)
{
if (stats.Armor.GetValue() <= damage) {
damage -= stats.Armor.GetValue();
damage = Mathf.Clamp(damage, 0, int.MaxValue);
slider.value -= damage;
}
if (slider.value <= 0)
{
Dead();
}
}
// Death Status
void Dead()
{
Debug.Log("You Are Dead");
//filler for death scene
}
// Heal X amount of Damage
void HealDamage(int damage)
{
if (slider.value < slider.maxValue)
{
slider.value += damage;
}
}
// Set Max Health Permanently
public void SetMaxHealth(int health)
{
slider.maxValue = health;
}
// Set Current Health
public void SetHealth(int health)
{
slider.value = health;
}
// Increase MaxHealthPermanently
public void IncreaseMaxHealth(int health)
{
slider.maxValue = slider.maxValue + health;
}
// Temporarily increase Max Health. waitTime = 5f ~ 5 seconds
public void TempMaxHealth(float waitTime,int health)
{
StartCoroutine(TempHealthTime(waitTime, health)); // start time function
}
IEnumerator TempHealthTime(float waitTime, int health)
{
slider.maxValue += health; // adds boost
yield return new WaitForSeconds(waitTime);
Debug.Log("Coroutine ended: " + Time.time + " seconds");
slider.maxValue -= health; // remove boost
}
public void PoisonDamage(float waitTime,int health)
{
StartCoroutine(PoisonDuration(waitTime, health));
}
IEnumerator PoisonDuration(float waitTime,int health)
{
slider.value -= health;
if (slider.value <= 0)
{
slider.value = 1;
}
yield return new WaitForSeconds(waitTime);
if (slider.value > 1)
{
PoisonDamage(waitTime, health);
}
else Debug.Log("Coroutine ended: " + Time.time + " seconds" + slider.value);
}
}
This is because either stats or stats.Armor returns null. If that's excepted, you can do this
// Take X amount of Damage
void TakeDamage(int damage)
{
// note here the use of `?`, this basically says that if is null, use null and don't check after the dot.
var armorValue = stats?.Armor?.GetValue();
if (armorValue is null)
return null;
if (armorValue <= damage) {
damage -= armorValue;
damage = Mathf.Clamp(damage, 0, int.MaxValue);
slider.value -= damage;
}
if (slider.value <= 0)
{
Dead();
}
}

Shuffling an array and assigning it to different buttons in Unity

I have an array that I am shuffling and then assigning to buttons. Depending on the item in the array, the button will perform a different function. This is currently my code, and it works, but is extremely inelegant.
I am currently shuffling the array first, then assigning the first 2 items of the shuffled array to the button text, and then using if statements to check whether or not the string matches so that it will execute a specific code for that string.
There is definitely a better way to do this, but I can't seem to figure it out.
public TextMeshProUGUI firstChoiceText;
public TextMeshProUGUI secondChoiceText;
public GameObject player;
public string[] upgrades =
{
"Speed Up",
"Fire Rate Up",
"Damage Up",
"Max Health Up"
};
public void Shuffle(string[] array)
{
for (int i = 0; i < array.Length; i++)
{
string tmp = array[i];
int rand = Random.Range(0, array.Length);
array[i] = array[rand];
array[rand] = tmp;
}
firstChoiceText.text = upgrades[0];
secondChoiceText.text = upgrades[1];
}
// Start is called before the first frame update
void Start()
{
Shuffle(upgrades);
}
public void FirstChoice()
{
Debug.Log("first choice clicked");
if (firstChoiceText.text == "Speed Up")
{
player.GetComponent<PlayerController>().playerSpeed += 1;
}
else if (firstChoiceText.text == "Fire Rate Up")
{
player.GetComponent<PlayerController>().fireRate -= 0.05f;
}
else if (firstChoiceText.text == "Damage Up")
{
player.GetComponent<PlayerController>().playerDamage *= 1.1f;
}
else if (firstChoiceText.text == "Max Health Up")
{
GameManager.maxHealth += 5;
player.GetComponent<PlayerController>().Heal(5);
}
Time.timeScale = 1;
gameObject.SetActive(false);
Shuffle(upgrades);
}
public void SecondChoice()
{
Debug.Log("second choice clicked");
if (secondChoiceText.text == "Speed Up")
{
player.GetComponent<PlayerController>().playerSpeed += 1;
}
else if (secondChoiceText.text == "Fire Rate Up")
{
player.GetComponent<PlayerController>().fireRate -= 0.05f;
}
else if (secondChoiceText.text == "Damage Up")
{
player.GetComponent<PlayerController>().playerDamage *= 1.1f;
}
else if (secondChoiceText.text == "Max Health Up")
{
GameManager.maxHealth += 5;
player.GetComponent<PlayerController>().Heal(5);
}
Time.timeScale = 1;
gameObject.SetActive(false);
Shuffle(upgrades);
}
One solution would be to create a Dictionary<string, Action<Player>> where your Action delegate corresponds to your string key and call the method via Action delegate based on the string key of the Dictionary, also moved your shuffle logic into it's own private method to reduce code duplication:
//Dictionary to hold string key/Action delegate pairs
private Dictionary<string, Action<Player>> _actions = new Dictionary<string, Action<string>>
{
{"Speed Up", (player) => player.GetComponent<PlayerController>().playerSpeed += 1;},
{"Fire Rate Up", (player) => player.GetComponent<PlayerController>().fireRate -= 0.05f;}
{"Damage Up", (player) => player.GetComponent<PlayerController>().playerDamage *= 1.1f;},
{"Max Health Up", (player) => { GameManager.maxHealth += 5;
player.GetComponent<PlayerController>().Heal(5); } }
};
//You could reduce your First And Second Choice down to using the
//dictionary to call the cooresponding Action delegate:
public void FirstChoice()
{
Debug.Log("first choice clicked");
_actions[firstChoiceText.text](player);
DoShuffle();
}
public void SecondChoice()
{
Debug.Log("second choice clicked");
_actions[secondChoiceText.text](player);
DoShuffle();
}
//Moved this into a method to reduce repetitive code
private void DoShuffle()
{
Time.timeScale = 1;
gameObject.SetActive(false);
Shuffle(upgrades);
}
You could create a base class for upgrades, and then use inheritance to split up all the logic that is now in the if statements to separate upgrade classes deriving from this base class. In the Unity world you might want to use ScriptableObjects for this.
public abstract class Upgrade : ScriptableOject
{
public abstract void Apply(PlayerController player);
}
[CreateAssetMenu(menuName = "Upgrades/Speed Up", fileName = "Speed Up")]
public sealed class SpeedUp : Upgrade
{
public override void Apply(PlayerController player)
{
player.playerSpeed += 1;
}
}
[CreateAssetMenu(menuName = "Upgrades/Fire Rate Up", fileName = "Fire Rate Up")]
public sealed class FireRateUp : Upgrade
{
public override void Apply(PlayerController player)
{
player.fireRate -= 0.05f;
}
}
Then you could create one scriptable object asset for each upgrade, and then assign all of them to your script into an Upgrade[] field.
[SerializeField] private TextMeshProUGUI firstChoiceText;
[SerializeField] private TextMeshProUGUI secondChoiceText;
[SerializeField] private PlayerController player;
[SerializeField] private Upgrade[] upgrades;
private Upgrade firstUpgrade;
private Upgrade secondUpgrade;
public void ApplyFirstUpgrade()
{
Debug.Log("first choice clicked");
ApplyUpgrade(firstUpgdade);
}
public void ApplySecondUpgrade()
{
Debug.Log("second choice clicked");
ApplyUpgrade(secondUpgrade);
}
private void Awake() => RandomizeUpgrades();
private void RandomizeUpgrades()
{
firstUpgrade = GetRandomUpgrade();
secondUpgdade = GetRandomUpgrade(firstChoice);
}
private Upgrade GetRandomUpgrade() => upgrades[Random.Range(0, upgrades.Length)];
private Upgrade GetRandomUpgrade(Upgrade ignore)
{
if(upgrades.Length < 2)
{
Debug.LogError("At least 2 upgrades need to be assigned before calling GetRandomUpgrade.", this);
return;
}
Upgrade resultCandiate = GetRandomUpgrade();
if(resultCandiate != ignore)
{
return result;
}
return GetRandomUpgdate(ignore);
}
private void ApplyUpgrade(Upgrade upgrade)
{
upgrade.Apply();
Time.timeScale = 1;
gameObject.SetActive(false);
RandomizeUpgrades();
}
The benefit with this sort of approach is that you can add more abilities easily without having to make any modifications to existing code, and without ending up with one giant class with hundreds of lines of code.

Passing data between scenes Errors

I have made a game manager making sure my data gets passed on from the first scene on to the next scene. Within the game manager, I have added certain scripts to ensure it gets passed. As you can see in the picture underneath.
The problem is that the score adds up at the first level, let's say I have 5 points. I go to level 2 and the UI shows my score as 0 (even tho I have nothing put as text within the score text) I kill 1 monster and the UI shows 6. So how can I put the UI to be showing it at all times? (Constant refresh?)
The second problem is that while the score manager does work. The health script cancels everything out when switching levels.
The user starts with 10 health. Takes damage in the first scene, but in the second scene, the user still has 10 health for some reason?
Game Manager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
public ActionButton PopupPrefab;
private ActionButton currentlySpawnedPopup;
public static GameManager instance = null;
void Awake () {
if (instance == null) {
instance = this;
} else if (instance != this) {
Destroy (gameObject);
}
Application.targetFrameRate = 60;
}
void Update () {
//if (Input.GetKeyDown(KeyCode.R)) {
// RestartScene ();
//}
}
public void InvokeRestartScene (float time) {
Invoke ("RestartScene", time);
}
public void RestartScene () {
SceneManager.LoadScene (0);
}
public void SpawnPopup (Vector2 position) {
DespawnPopup ();
currentlySpawnedPopup = Instantiate (PopupPrefab, position, Quaternion.identity) as ActionButton;
}
public void DespawnPopup () {
if (currentlySpawnedPopup != null) {
currentlySpawnedPopup.DestroySelf();
currentlySpawnedPopup = null;
}
}
public void FadePopup () {
if (currentlySpawnedPopup != null) {
currentlySpawnedPopup.FadeMe ();
currentlySpawnedPopup = null;
}
}
}
Score Manager
using UnityEngine;
using System;
using System.Collections;
public class ScoreManager : MonoBehaviour
{
public static ScoreManager Instance { get; private set; }
public int Score { get; private set; }
public int HighScore { get; private set; }
public bool HasNewHighScore { get; private set; }
public static event Action<int> ScoreUpdated = delegate {};
public static event Action<int> HighscoreUpdated = delegate {};
private const string HIGHSCORE = "HIGHSCORE";
// key name to store high score in PlayerPrefs
void Awake()
{
if (Instance)
{
DestroyImmediate(gameObject);
}
else
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
}
void Start()
{
Reset();
}
public void Reset()
{
// Initialize score
Score = 0;
// Initialize highscore
HighScore = PlayerPrefs.GetInt(HIGHSCORE, 0);
HasNewHighScore = false;
}
public void AddScore(int amount)
{
Score += amount;
// Fire event
ScoreUpdated(Score);
if (Score > HighScore)
{
UpdateHighScore(Score);
HasNewHighScore = true;
}
else
{
HasNewHighScore = false;
}
}
public void UpdateHighScore(int newHighScore)
{
// Update highscore if player has made a new one
if (newHighScore > HighScore)
{
HighScore = newHighScore;
PlayerPrefs.SetInt(HIGHSCORE, HighScore);
HighscoreUpdated(HighScore);
}
}
}
Health Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class Health : MonoBehaviour {
public UnityEvent OnTakeDamageEvent;
public UnityEvent OnTakeHealEvent;
public UnityEvent OnDeathEvent;
[Header ("Max/Starting Health")]
public int maxHealth;
[Header ("Current Health")]
public int health;
[Header ("IsDeathOrNot")]
public bool dead = false;
[Header ("Invincible")]
public bool invincible = false;
public bool becomeInvincibleOnHit = false;
public float invincibleTimeOnHit = 1f;
private float invincibleTimer = 0f;
[Header ("Perform Dead Events after x time")]
public float DieEventsAfterTime = 1f;
void Start () {
health = maxHealth;
}
void Update () {
if (invincibleTimer > 0f) {
invincibleTimer -= Time.deltaTime;
if (invincibleTimer <= 0f) {
if (invincible)
invincible = false;
}
}
}
public bool TakeDamage (int amount) {
if (dead || invincible)
return false;
health = Mathf.Max (0, health - amount);
if (OnTakeDamageEvent != null)
OnTakeDamageEvent.Invoke();
if (health <= 0) {
Die ();
} else {
if (becomeInvincibleOnHit) {
invincible = true;
invincibleTimer = invincibleTimeOnHit;
}
}
return true;
}
public bool TakeHeal (int amount) {
if (dead || health == maxHealth)
return false;
health = Mathf.Min (maxHealth, health + amount);
if (OnTakeHealEvent != null)
OnTakeHealEvent.Invoke();
return true;
}
public void Die () {
dead = true;
if (CameraShaker.instance != null) {
CameraShaker.instance.InitShake(0.2f, 1f);
}
StartCoroutine (DeathEventsRoutine (DieEventsAfterTime));
}
IEnumerator DeathEventsRoutine (float time) {
yield return new WaitForSeconds (time);
if (OnDeathEvent != null)
OnDeathEvent.Invoke();
}
public void SetUIHealthBar () {
if (UIHeartsHealthBar.instance != null) {
UIHeartsHealthBar.instance.SetHearts (health);
}
}
}
I have thought of adding the following script on to my Health Script
But then I get the following error messages:
" Cannot implicitly convert type 'int' to 'bool'"
"The left-hand side of an assignment must be a variable, property or indexer"
void Awake()
{
if (health)
{
DestroyImmediate(gameObject);
}
else
{
(int)health = this;
DontDestroyOnLoad(gameObject);
}
}
The problem is that the score adds up at the first level, let's say I have 5 points. I go to level 2 and the UI shows my score as 0 (even tho I have nothing put as text within the score text) I kill 1 monster and the UI shows 6. So how can I put the UI to be showing it at all times? (Constant refresh?)
You can make one of the scripts set the UI text score when the scene is loaded.
void Start(){
// Loads the scoreText on start
scoreText.text = yourCurrentScore.ToString();
// Will work unless it has a "DontDestroyOnLoad" applied to it
}
The second problem is that while the score manager does work. The
health script cancels everything out when switching levels. The user
starts with 10 health. Takes damage in the first scene, but in the
second scene, the user still has 10 health for some reason?
In your health script, you had this:
void Start () {
health = maxHealth;
}
This resets your health everytime the scene loads and starts (Aka when you load to the next level). This causes the issue.
" Cannot implicitly convert type 'int' to 'bool'"
if (health)
The () for the if statement should be a condition (a question).
For example, doing health < 0 is valid since its saying "Is health less than 0?"
Doing health is not, since its just saying "10" (or some number).
"The left-hand side of an assignment must be a variable, property or
indexer"
(int)health = this;
If you wanted to change the value of health, just do health = 10 or health = some_Variable_That_Is_An_Integer

Getting text to stay when changing scenes and then destroying when entering another

I'm creating a game designed for vision-impaired gamers. My score text currently shows up during the gameplay. Once you lose it loads a new scene (End screen), but I want the score to stay when the end scene is loaded and then have it reset to 0 when the game screen is loaded again, then removed if the player decides to go back to the main menu.
This is what loads the next scene.
public int amount;
public void ChangeScene(int changeTheScene)
{
SceneManager.LoadScene(changeTheScene);
}
void Start()
{
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
amount += 1;
Debug.Log(amount);
if (amount == 10)
{
SceneManager.LoadScene(2);
}
}
}
}
And this is how i track the score
void Start()
{
count = 0;
SetCountText();
float x = Random.Range(325f, -600f);
float y = Random.Range(250f, -450f);
Debug.Log(x + "," + y);
prefab.GetComponent<RectTransform>().anchoredPosition = new Vector2(x, y);
loseObject.GetComponent<Lose>().amount = 0;
}
public void move()
{
float x = Random.Range(325f, -600f);
float y = Random.Range(250f, -450f);
Debug.Log(prefab.transform.position.x + "," + prefab.transform.position.y);
prefab.GetComponent<RectTransform>().anchoredPosition = new Vector2(x, y);
loseObject.GetComponent<Lose>().amount = 0;
count = count + 1;
SetCountText();
}
void SetCountText()
{
countText.text = "Count: " + count.ToString();
}
}
I'm not entirely sure if this would work, but to answer your question, I'm guessing this would do what you'd like.
using UnityEngine;
//This would be attached to said gameobject that displays the amount.
public class Amount : MonoBehaviour
{
public static Amount instance = null;
void Awake()
{
if (instance == null)
instance = this;
if (instance != this)
Destroy(gameObject);
DontDestroyOnLoad(gameObject);
}
}
//Here would be what's needed to set the amount's parent.
public class SetThatAmountsParentToThisGameObject : MonoBehaviour
{
void SetAmountParent()
{
Amount.instance.transform.SetParent(transform);
}
}
//And here you would destroy said gameobject that displays the amount.
public class DestroyThatAmount : MonoBehaviour
{
void DestroyIt()
{
Destroy(Amount.instance.gameObject);
}
}
Be advised that I haven't tested this and therefor am not sure if this will actually work. I'm writing it as an answer because you asked for an example and code is much cleaner and easier to read in answers.

How to Display high score using GUIText

Well, i'm pretty new with unity. I got a problem to display highscore. The score was display everytime enemy were shot. I want to display the highscore everytime the game end and be able to update everytime i got a new highscore. The score system using the GUI text. The example below.
Score:
Highscore:
To display the score, i'm using this script
using UnityEngine;
public class HealthScript : MonoBehaviour
{
public int hp = 1;
private GUIText scoreReference;
public bool isEnemy = true;
public void Damage(int damageCount)
{
hp -= damageCount;
if (hp <= 0)
{
// Dead!
Destroy(gameObject);
scoreReference.text = (int.Parse(scoreReference.text) + 1).ToString();
}
}
void Start()
{
scoreReference = GameObject.Find("Score").guiText;
}
// . . .
}
i got some idea to retrieve the value of the score, but it won't display. Please help me.. Thanks
we put a isDead boolaen and make it true when the player dies and when isDead is true we will show the score
int score;
int highscore;
bool isDead=false;
//initilizing
void OnGUI () {
if(isDead) //make this true when player dies
GUI.Label (new Rect (0,0,100,50),score.ToString());
}
void Awake(){
highscore=PlayerPrefs.GetInt("highscore");
}
public void Damage(int damageCount)
{
hp -= damageCount;
if (hp <= 0)
{
// Dead!
Destroy(gameObject);
score++; //increase score
if(score>highscore)
highscore=score;
}
}
public void onGameEnds(){
PlayerPrefs.SetInt("highscore",highscore);
}
this will be good
get { if (_highscore == -1)
_highscore = PlayerPrefs.GetInt("Highscore", 0);
return _highscore;
}
set {
if (value > _highscore) {
_highscore = value;
highscoreReference.text = _highscore.ToString();
PlayerPrefs.SetInt("Highscore", _highscore);
}
}
}

Categories