Sorry, I that I included all the code but I really can't find the error: I play and save and after I buy something with the BuyTaxes or Buymarket and quit and stop it and play it again it shows all the UI shows and all the prices for the market and the discount use are set to 0. But I cant figure out why.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameScript : MonoBehaviour
{
public Text GoldText;
public Text ArmyPowerText;
public Text PlayerNametext;
public Text Button1Text;
public Text Button2Text;
public int gold;
public int armypower;
public string PlayerName;
public int Level;
public int Income;
public int incomeboost;
public int discount;
public float lvlremainder;
public GameObject ButtonHolder;
public Slider LevelBar;
public float LevelProgress;
private float FillSpeed = 0.5f;
public GameObject UIHolder;
public GameObject StartForm;
public InputField NameInput;
public GameObject ArmyUI;
public GameObject InvestUI;
public GameObject LaboratoryUI;
private float time = 0.0f;
public float IncomePerdiod = 5f;
public bool GameStart = true;
//Invest Prices
//Market
public int marketprice;
public int marketlevel;
public Text marketpricetext;
public Text markettext;
//Taxes
public int taxesprice;
public int taxeslevel;
public Text taxespricetext;
public Text taxestext;
void Start()
{
Load();
if(GameStart == true)
{
gold = 100;
armypower = 0;
Level = 1;
LevelProgress = 0;
//Laboratory
discount = 1;
Income = 1;
incomeboost = 1;
//Invest
marketlevel = 0;
taxeslevel = 0;
ArmyUIHide();
InvestUIHide();
ButtonHide();
UIHide();
StartForm.SetActive(true);
Save();
}
if (GameStart == false)
{
StartForm.SetActive(false);
ArmyUIHide();
InvestUIHide();
ButtonShow();
UIShow();
Save();
}
}
void Update()
{
if(time >= IncomePerdiod)
{
time = 0.0f;
gold += Income * incomeboost;
}
time += Time.deltaTime;
Save();
GoldText.text = "Gold: " + gold;
ArmyPowerText.text = "Army Power: " + armypower;
PlayerNametext.text = PlayerName + " LVL " + Level;
//Market
markettext.text = "Market LVL " + marketlevel;
marketpricetext.text = marketprice.ToString();
marketprice = 50 * discount;
//Taxes
taxestext.text = "Taxes LVL " + taxeslevel;
taxespricetext.text = taxesprice.ToString();
taxesprice = 250 * discount;
if (LevelBar.value < LevelProgress)
{
LevelBar.value += FillSpeed * Time.deltaTime;
}
if (LevelBar.value > LevelProgress)
{
LevelBar.value = LevelProgress;
}
if (LevelProgress >= 1)
{
Level++;
LevelProgress = 0;
}
}
public void Save()
{
//UI
PlayerPrefs.SetString("gold", gold.ToString());
PlayerPrefs.SetString("armypower", armypower.ToString());
PlayerPrefs.SetString("GameStart", GameStart.ToString());
PlayerPrefs.SetString("PlayerName", PlayerName.ToString());
PlayerPrefs.SetString("Level", Level.ToString());
PlayerPrefs.SetString("LevelProgress", LevelProgress.ToString());
//Laboratory
PlayerPrefs.SetString("discount", discount.ToString());
PlayerPrefs.SetString("Income", Income.ToString());
PlayerPrefs.SetString("incomeboost", incomeboost.ToString());
//Invest
PlayerPrefs.SetString("marketlevel", marketlevel.ToString());
PlayerPrefs.SetString("taxeslevel", taxeslevel.ToString());
}
public void Load()
{
//UI
gold = int.Parse(PlayerPrefs.GetString("gold", "100"));
armypower = int.Parse(PlayerPrefs.GetString("armypower", "0"));
GameStart = bool.Parse(PlayerPrefs.GetString("GameStart", "true"));
PlayerName = PlayerPrefs.GetString("PlayerName", "Guest");
Level = int.Parse(PlayerPrefs.GetString("Level", "1"));
LevelProgress = int.Parse(PlayerPrefs.GetString("LevelProgress", "0"));
//Laboratory
discount = int.Parse(PlayerPrefs.GetString("discount", "1"));
Income = int.Parse(PlayerPrefs.GetString("Income", "1"));
incomeboost = int.Parse(PlayerPrefs.GetString("incomeboost", "1"));
//Invest
marketlevel = int.Parse(PlayerPrefs.GetString("marketlevel", "50"));
taxeslevel = int.Parse(PlayerPrefs.GetString("taxeslevel", "250"));
}
public void ButtonHide()
{
ButtonHolder.SetActive(false);
}
public void ButtonShow()
{
ButtonHolder.SetActive(true);
}
public void UIHide()
{
UIHolder.SetActive(false);
}
public void UIShow()
{
UIHolder.SetActive(true);
}
public void ArmyUIShow()
{
ArmyUI.SetActive(true);
}
public void ArmyUIHide()
{
ArmyUI.SetActive(false);
}
public void LaboratoryUIShow()
{
LaboratoryUI.SetActive(true);
}
public void LaboratoryUIHide()
{
LaboratoryUI.SetActive(false);
}
public void InvestUIShow()
{
InvestUI.SetActive(true);
}
public void InvestUIHide()
{
InvestUI.SetActive(false);
}
public void EnterName()
{
PlayerName = NameInput.text;
StartForm.SetActive(false);
UIShow();
GameStart = false;
ButtonShow();
}
public void ArmyClick()
{
ArmyUIShow();
ButtonHide();
LaboratoryUIHide();
InvestUIHide();
}
public void InvestClick()
{
InvestUIShow();
ButtonHide();
LaboratoryUIHide();
ArmyUIHide();
}
public void LaboratoryClick()
{
ArmyUIHide();
ButtonHide();
LaboratoryUIShow();
InvestUIHide();
}
public void Home()
{
ArmyUIHide();
InvestUIHide();
ButtonShow();
LaboratoryUIHide();
}
//Buy Invest
public void BuyMarket()
{
if(gold >= marketprice && marketlevel < 5)
{
marketlevel++;
Income += 1;
gold -= marketprice;
if (LevelProgress < 1f - 0.05f)
{
LevelProgress += 0.15f;
}
else
{
lvlremainder += (LevelProgress + 0.05f - 1f);
Level++;
LevelProgress = 0;
LevelProgress += lvlremainder;
}
}
}
public void BuyTaxes()
{
if (gold >= taxesprice && taxeslevel < 10)
{
taxeslevel++;
Income += 3;
gold -= taxesprice;
if (LevelProgress < 1f - 0.15f)
{
LevelProgress += 0.15f;
}
else
{
lvlremainder += (LevelProgress + 0.15f - 1f);
Level++;
LevelProgress = 0;
LevelProgress += lvlremainder;
}
}
}
The saving system in your code is not developed correctly, remove the Save() method call from the Start and Update methods, and call it only when the necessary event occurs, such as the end of the game.
Do local prop like this to save data:
private int Gold
{
get => PlayerPrefs.GetInt("gold");
set => PlayerPrefs.SetInt("gold", value);
}
I found the fault I parsed as int for a float that messed the whole saving system up!
Related
I created a reverse timer for the system of lives. i.e., life should be added after 00:00 if the field is empty. I need the timer to work before all the hearts are full, i.e. when one heart is full, the timer turns on again, if all the hearts are in place, then it's just 00:00. I did this:
public int lives;
public int maxLives;
public Image[] Live;
public Sprite FullHearts;
public Sprite EmptyHearts;
//Timer
[SerializeField] private int minutes;
[SerializeField] private int seconds;
private int m, s;
[SerializeField]
private Text timerText;
private void updateTimer()
{
s--;
if (s < 0)
{
if (m == 0)
{
stopTimer();
return;
}
else {
m --;
s= 59;
}
}
writeTimer(m, s);
Invoke("updateTimer", 1f);
}
public void writeTimer(int m, int s) {
if (s < 10)
{
timerText.text = m.ToString() + ":0" + s.ToString();
}
else
{
timerText.text = m.ToString() + ":" + s.ToString();
}
}
public void stopTimer()
{
CancelInvoke();
}
public void StartTimer()
{
m = minutes;
s= seconds;
writeTimer(m, s);
Invoke("updateTimer", 1f);
}
public void setLives()
{
if (lives < maxLives)
{
StartTimer();
lives++;
Debug.Log("Life: " + lives);
}
if (lives > maxLives)
{
lives = maxLives;
}
for (int i = 0; i < Live.Length; i++)
{
if (i < Mathf.RoundToInt(lives))
{
Live[i].sprite = FullHearts;
}
else
{
Live[i].sprite = EmptyHearts;
}
if(i< maxLives)
{
Live[i].enabled = true;
}
else
{
Live[i].enabled = false;
}
}
}
public void TakeHit(int damage)
{
lives -= damage;
if (lives < 1)
{
lives = 0;
}
for (int i = 0; i < Live.Length; i++)
{
if (i < Mathf.RoundToInt(lives))
{
Live[i].sprite = FullHearts;
}
else
{
Live[i].sprite = EmptyHearts;
}
}
}
but for some reason it does not start, please tell me what the error is possible?
I'm using NetCode for GameObject 1.0.0 pre.5 in unity
and I keep getting the following error when I'm trying to send a ServerRPC
Assets\scrips\Weapons\Grenades.cs(72,13): error - Don't know how to serialize PlayerMessenger - implement INetworkSerializable or add an extension method for FastBufferWriter.WriteValueSafe to define serialization.
the method that give the error is Grenades.SetHealthDownServerRpc()
how take's an PlayerMassenger class instace
here's the my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
namespace BeanBoxers.Weapons
{
[System.Serializable]
[implement : INetworkSerializable]
public class Grenades : NetworkBehaviour
{
public string PlayerTag;
public GameObject Particals;
public double Timer = 10;
public bool IsThouned = false;
public bool? Team {get; private set;} = null;
public float HitRadius = 5;
public float Demage = 120;
public float effectTime = .15f;
void Start()
{
Particals.SetActive(false);
if(!IsServer) {return;}
GetComponent<NetworkObject>().Spawn();
}
// Update is called once per frame
void Update()
{
if (!IsThouned) {return; }
else
{
Timer -= Time.deltaTime;
}
if (Timer <= 0)
{
explod();
}
}
public void explod()
{
Particals.SetActive(true);
IsThouned = false;
Collider[] hitColliders = Physics.OverlapSphere(transform.position, HitRadius);
foreach (var hitCollider in hitColliders)
{
if (!IsOwner) {break;}
if (hitCollider.tag == PlayerTag)
{
BeanBoxers.Player.PlayerMessenger Player = hitCollider.gameObject.GetComponent<BeanBoxers.Player.PlayerMessenger>();
if (Player.Team != Team || Team == null)
{
Vector3 HitDistanceVec3 = hitCollider.gameObject.transform.position - transform.position;
float Distance = Mathf.Abs(Mathf.Sqrt(HitDistanceVec3.x * HitDistanceVec3.x + HitDistanceVec3.y * HitDistanceVec3.y + HitDistanceVec3.z * HitDistanceVec3.z));
SetHealthDownServerRpc(Player ,Mathf.Abs(Mathf.Sin(90 / Distance)) * Demage);
}
}
}
GetComponent<MeshRenderer>().enabled = false;
Destroy(transform.gameObject, effectTime);
}
public void setTeam(bool? team)
{
Team = team;
}
[ServerRpc]
private void SetHealthDownServerRpc(BeanBoxers.Player.PlayerMessenger player, float Demage)
{
player.SetHealth(player.GetHealth() - Demage);
}
}
}
PlayerMassenger:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
using TMPro;
namespace BeanBoxers.Player
{
[System.Serializable]
public class PlayerMessenger : NetworkBehaviour
{
protected static BeanBoxers.Guns.GunsTM GunsTaskManager = new BeanBoxers.Guns.GunsTM();//Managed the guns
//you can get from him a gun like so: GunsTaskManager.GetGun(<Gun name>);
public LayerMask groundMask;//a ground mask
public dynamic Gun{get; private set;}// store the gun from the GunsTM to a variable
public GameObject groundCheck{get; private set;}// store the GameObject that checks if the player touching
public CharacterController controller{get; private set;}// control the player
public GameObject GrenadePath{get; private set;}//store the force for the grande to fly to
private int MaxHealth = 100;//max health
public NetworkVariable<float> Health{get; private set;} = new NetworkVariable<float>(100);//my health
public float HealthRegnertion{get; private set;} = 3;// how fast the player does regnertion
public float gravity = -10.0f;//gravity
public float speed{get; private set;} = 100;//current speed
public float Ospeed{get; private set;}// oriaginal speed
private float groundDistnce = 0.4f;//the radus of the spire that chack if the payer touching th ground
private Vector3 velocity = new Vector3(0, 0, 0);//the player velocity
public float JumpVelocity{get; private set;} = 10f;// jump velocity
private bool isGrounded;// store if the player is grouded or not
public bool isSlideing{get; private set;} = false;//store if the player is slideing or not
private Vector3 slideScale = new Vector3(1.3f, 0.5f, 1.3f);//player scale
public float MaxSlideTime{get; private set;} = 10;// max slideing time
public float SlideingTime{get; private set;} = 0;//current slideing time
public bool isDead{get; private set;} = false;//is the player dead
private float RespawnTime = 5f;//how mach time is take the player to do a respawn
public bool? Team{get; private set;} = null;//true; red team, false; blue team, null; free for all
private string GunName = "PickerKicker";// my current gun name
public bool ShootTriger{get; private set;} = false;// am I polling the triger
public int GrandesLeft{get; private set;} = 3;
public int MaxNumberOfHoldedGrenades{get; private set;} = 3;
public bool IsHoldingGrenade{get; private set;} = false;
public float GrandeHoldTimer{get; private set;} = 0;
public float MaxHoldGrandeTime{get; private set;} = 5;
public int SmookeGrandesLeft{get; private set;} = 3;
public int MaxNumberOfHoldSmookeGrenades{get; private set;} = 3;
public bool IsHoldingSmookeGrenade{get; private set;} = false;
public float SmookeGrandeHoldTimer{get; private set;} = 0;
public float MaxHoldSmookeGrandeTime{get; private set;} = 5;
public int MortarLeft{get; private set;} = 3;
public int MaxNumberOfHoldedMortor{get; private set;} = 6;
public RayCheck Ray{get; private set;}// a RayCheck object
private GameObject UI;
private BeanBoxers.UI.Player.FaceTheCamera UIclass;
public double timer{get; private set;} = 0;// a timer
public NetworkVariable<bool> TryVariable = new NetworkVariable<bool>(false);
void Start()
{
groundCheck = transform.GetChild(0).gameObject;
Ospeed = speed;
controller = GetComponent<CharacterController>();
groundCheck.transform.parent = this.transform;
groundCheck.transform.localPosition = new Vector3(0, -1f, 0);
Ray = this.GetComponent<RayCheck>();
this.SetGunName(GunName);
EasterEggs();
groundMask = LayerMask.GetMask("Ground");
this.transform.position = new Vector3(0f, 10f, 0f);
if (IsOwner)
{
SetName(GameObject.Find("Menu").GetComponent<BeanBoxers.Multiplayer.MainMenu.MainMenu>().Name);
}
}
void Update()
{
//update UI
UIclass.update(this.transform.position, Health.Value, MaxHealth, name);
if (!isDead)
{
print(TryVariable);
//update
slideUpdate();
velocity.y += gravity * Time.deltaTime;
Vector3 move = new Vector3(velocity.x * speed, velocity.y, velocity.x * speed);
controller.Move(move * Time.deltaTime);
isGrounded = Physics.CheckSphere(groundCheck.transform.position, groundDistnce, groundMask);
if (isGrounded && velocity.y <= 0)
{
velocity.y = -2f;
}
//update the gun
Gun.Update();
//update the grenade
if (IsHoldingGrenade)
{
if (GrandeHoldTimer > MaxHoldGrandeTime)
{
GrandeHoldTimer = MaxHoldGrandeTime;
}
else
{
GrandeHoldTimer += Time.deltaTime;
}
}
//update the smooke grenade
if (IsHoldingSmookeGrenade)
{
if (SmookeGrandeHoldTimer > MaxHoldSmookeGrandeTime)
{
SmookeGrandeHoldTimer = MaxHoldSmookeGrandeTime;
}
else
{
SmookeGrandeHoldTimer += Time.deltaTime;
}
}
//check the ray cast
if (ShootTriger)
{
if (Gun.Shoot())
{
PlayerMessenger output = Ray.CheckWhatRayHit();
if (output != null)
{
output.SetHealth(output.GetHealth() - Gun.TakeDemage(this.transform.position, output.transform.position));
}
}
}
if (Health.Value <= 0)
{
isDead = true;
// ServerRpc();
if (!IsOwner) {return;}
DiedServerRpc();
//make Sure the player position update when he die
Disable();
Invoke("Spawn", 5);
}
else if (Health.Value < MaxHealth)
{
Health.Value += HealthRegnertion * Time.deltaTime;
}
}
}
public void Spawn()
{
Enable();
isDead = false;
timer = 0;
Health.Value = MaxHealth;
GrandesLeft = MaxNumberOfHoldedGrenades;
SmookeGrandesLeft = MaxNumberOfHoldSmookeGrenades;
MortarLeft = MaxNumberOfHoldedMortor;
}
public void SetGunName(string gunName)
{
if (!IsServer) {return;}
this.GunName = gunName;
Gun = GunsTaskManager.GetGun(GunName);
Gun.setParent(Ray.RayStarter);
}
public string GetGunName()
{
return GunName;
}
public void SetName(string name)
{
if (!IsServer) {return;}
this.name = name;
EasterEggs();
}
public string GetName(string name)
{
return name;
}
public void SetHealth(float Health)
{
if (!IsServer) {return;}
this.Health.Value = Health;
if (Health > 0) {return;}
DiedServerRpc();
}
public float GetHealth()
{
return Health.Value;
}
[ServerRpc]
private void DiedServerRpc()
{
DiedClientRpc();
}
[ClientRpc]
private void DiedClientRpc()
{
if (IsOwner) {return;}
//make Sure the player position update when he die
isDead = true;
Disable();
Invoke("Spawn", 5);
}
public void SetSpeed(float NewSpeed)
{
if (!IsServer) {return;}
speed = NewSpeed;
}
public void SetMaxHealth(int Max_Health)
{
if (!IsServer) {return;}
MaxHealth = Max_Health;
}
public void changeTeam(bool? team)
{
if (!IsServer) {return;}
Team = team;
}
private void Disable()
{
transform.gameObject.SetActive(false);
}
private void Enable()
{
transform.gameObject.SetActive(true);
}
private void EasterEggs()
{
if (name == "Eti Ben Simon") {MaxHealth *= 2; Health.Value = MaxHealth;}
}
public void shootTriger(bool val)
{
ShootTriger = val;
shootTrigerServerRpc(val);
}
[ServerRpc]
private void shootTrigerServerRpc(bool val)
{
ShootTriger = val;
shootTrigerClientRpc(val);
}
[ClientRpc]
private void shootTrigerClientRpc(bool val)
{
if(IsOwner) {return;}
ShootTriger = val;
}
public void Jump()
{
if(!IsOwner) {return;}
JumpServerRpc();
if (isGrounded)
{
velocity.y = JumpVelocity;
unslide();
}
}
[ServerRpc]
private void JumpServerRpc()
{
JumpClientRpc();
}
[ClientRpc]
private void JumpClientRpc()
{
if (isGrounded)
{
velocity.y = JumpVelocity;
unslide();
}
}
public void slide()
{
if(!IsOwner) {return;}
slideServerRpc();
if (isGrounded)
{
speed = Ospeed * 2;
isSlideing = true;
transform.localScale = slideScale;
}
}
[ServerRpc]
private void slideServerRpc()
{
slideClientRpc();
speed = Ospeed;
isSlideing = false;
Vector3 newScale = new Vector3(1f, 1f, 1f);
transform.localScale = newScale;
}
[ClientRpc]
private void slideClientRpc()
{
if(IsOwner) {return;}
if (isGrounded)
{
speed = Ospeed * 2;
isSlideing = true;
transform.localScale = slideScale;
}
}
public void unslide()
{
if(!IsOwner) {return;}
unslideServerRpc();
speed = Ospeed;
isSlideing = false;
Vector3 newScale = new Vector3(1f, 1f, 1f);
transform.localScale = newScale;
}
[ServerRpc]
private void unslideServerRpc()
{
unslideClientRpc();
speed = Ospeed;
isSlideing = false;
Vector3 newScale = new Vector3(1f, 1f, 1f);
transform.localScale = newScale;
}
[ClientRpc]
private void unslideClientRpc()
{
if(IsOwner) {return;}
speed = Ospeed;
isSlideing = false;
Vector3 newScale = new Vector3(1f, 1f, 1f);
transform.localScale = newScale;
}
public void slideUpdate()
{
if (isSlideing)
{
SlideingTime += Time.deltaTime;
}
else
{
SlideingTime -= Time.deltaTime / 2;
if (SlideingTime < 0)
{
SlideingTime = 0;
}
}
if (SlideingTime >= MaxSlideTime)
{
unslide();
}
}
public void ThrowGrenade()
{
if (!IsOwner) {return;}
if (GrandesLeft > 0)
{
Debug.Log("Grenade.Throw");
GameObject Grande = Instantiate(Resources.Load("3Dmodels/Weapons/Grenade")) as GameObject;
Grande.transform.position = GrenadePath.transform.position;
BeanBoxers.Weapons.Grenades G = Grande.GetComponent<BeanBoxers.Weapons.Grenades>();
Rigidbody GrenadeRigidbody = Grande.GetComponent<Rigidbody>();
G.setTeam(Team);
G.IsThouned = true;
GrenadeRigidbody.AddForce((GrenadePath.transform.position - transform.position) * GrandeHoldTimer * 170);
GrenadeRigidbody.AddTorque(new Vector3(UnityEngine.Random.Range(-180, 180), UnityEngine.Random.Range(-180, 180), UnityEngine.Random.Range(-180, 180)));
GrandeHoldTimer = 0;
IsHoldingGrenade = false;
GrandesLeft -= 1;
}
}
public void isHoldingGrenade(bool val)
{
if (!IsOwner) {return;}
IsHoldingGrenade = val;
}
[ServerRpc]
private void IsHoldingGrenadeServerRpc(bool val)
{
IsHoldingGrenade = val;
IsHoldingGrenadeClientRpc(val);
}
[ClientRpc]
private void IsHoldingGrenadeClientRpc(bool val)
{
if (IsOwner) {return;}
IsHoldingGrenade = val;
}
public void ThrowSmookeGrenade()
{
if (!IsOwner) {return;}
if (SmookeGrandesLeft < 0) {return;}
Debug.Log("SmookeGrenade.Throw");
GameObject Grande = Instantiate(Resources.Load("3Dmodels/Weapons/SmookeGrenade")) as GameObject;
Grande.transform.position = GrenadePath.transform.position;
BeanBoxers.Weapons.Grenades G = Grande.GetComponent<BeanBoxers.Weapons.Grenades>();
Rigidbody GrenadeRigidbody = Grande.GetComponent<Rigidbody>();
G.setTeam(Team);
G.IsThouned = true;
GrenadeRigidbody.AddForce((GrenadePath.transform.position - transform.position) * SmookeGrandeHoldTimer * 170);
GrenadeRigidbody.AddTorque(new Vector3(UnityEngine.Random.Range(-180, 180), UnityEngine.Random.Range(-180, 180), UnityEngine.Random.Range(-180, 180)));
SmookeGrandeHoldTimer = 0;
IsHoldingSmookeGrenade = false;
SmookeGrandesLeft -= 1;
}
public void isHoldingSmookeGrenade(bool val)
{
if (!IsOwner) {return;}
IsHoldingSmookeGrenade = val;
}
[ServerRpc]
private void IsHoldingSmookeGrenadeServerRpc(bool val)
{
IsHoldingSmookeGrenade = val;
IsHoldingSmookeGrenadeClientRpc(val);
}
[ClientRpc]
private void IsHoldingSmookeGrenadeClientRpc(bool val)
{
if (IsOwner) {return;}
IsHoldingSmookeGrenade = val;
}
public void PutMortar()
{
if (!IsOwner) {return;}
if (MortarLeft < 0) {return;}
GameObject mortor = Instantiate(Resources.Load("3Dmodels/Weapons/Mortor")) as
GameObject;
mortor.transform.position = GrenadePath.transform.position;
mortor.transform.Rotate(46f, GrenadePath.transform.eulerAngles.y + 180, -90f);
MortarLeft -= 1;
}
}
}
my scripts aren't the best, I know but anybody have any idea why I get the error? it will very help me
I guess you could first off try to do what the error says: "Implement INetworkSerializable". To Implement that Interface you would write: ...Grenades : Networkbehavior, INetworkSerializable. I don't know if [implement: ...] works so that is just a guess based off of your error.
I got some problem with my Tetris game on highscore, here's the game script
/// The width of the Grid...
public static int gridWidth = 10;
/// The weight of the Grid...
public static int gridWeight = 20;
/// The grid...
public static Transform[,] grid = new Transform[gridWidth, gridWeight];
public static bool startingAtLevelZero;
public static int startingLevel;
public int scoreOneLine = 50;
public int scoreTwoLine = 100;
public int scoreThreeLine = 400;
public int scoreFourLine = 1500;
public int currentLevel = 0;
private int numLinesCleared = 0;
public static float fallSpeed = 1.0f;
public AudioClip clearedLineSound;
public Text hud_score;
public Text hud_level;
public Text hud_lines;
private int numberOfRowsThisTurn = 0;
private AudioSource audioSource;
public static int currentScore = 0;
private GameObject previewTetromino;
private GameObject nextTetromino;
private bool gameStarted = false;
private int startingHighScore;
private int startingHighScore2;
private int startingHighScore3;
private Vector2 previewTetrominoPosition = new Vector2(-6.5f, 16);
// Start is called before the first frame update
void Start()
{
currentScore = 0;
hud_score.text = "0";
currentLevel = startingLevel;
hud_level.text = currentLevel.ToString();
hud_lines.text = "0";
SpawnNextTetromino();
audioSource = GetComponent<AudioSource>();
startingHighScore = PlayerPrefs.GetInt("highScore");
startingHighScore2 = PlayerPrefs.GetInt("highscore2");
startingHighScore3 = PlayerPrefs.GetInt("highscore3");
}
void Update()
{
UpdateScore();
UpdateUI();
UpdateLevel();
UpdateSpeed();
}
void UpdateLevel()
{
if ((startingAtLevelZero == true) || (startingAtLevelZero == false && numLinesCleared / 10 > startingLevel))
currentLevel = numLinesCleared / 10;
Debug.Log("current Level : " + currentLevel);
}
void UpdateSpeed()
{
fallSpeed = 1.0f - ((float)currentLevel * 0.1f);
Debug.Log("current Fall Speed : " + fallSpeed);
}
public void UpdateUI()
{
hud_score.text = currentScore.ToString();
hud_level.text = currentLevel.ToString();
hud_lines.text = numLinesCleared.ToString();
}
public void UpdateScore()
{
if (numberOfRowsThisTurn > 0)
{
if (numberOfRowsThisTurn == 1)
{
ClearedOneLine();
}
else if (numberOfRowsThisTurn == 2)
{
ClearedOneLine();
}
else if (numberOfRowsThisTurn == 3)
{
ClearedThreeLine();
}
else if (numberOfRowsThisTurn == 4)
{
ClearedFourLine();
}
numberOfRowsThisTurn = 0;
PlayLineClearedSound();
}
}
public void ClearedOneLine()
{
currentScore += scoreOneLine + (currentLevel * 20);
numLinesCleared++;
}
public void ClearedTwoLine()
{
currentScore += scoreTwoLine + (currentLevel * 25);
numLinesCleared += 2;
}
public void ClearedThreeLine()
{
currentScore += scoreThreeLine + (currentLevel * 30);
numLinesCleared += 3;
}
public void ClearedFourLine()
{
currentScore += scoreFourLine + (currentLevel * 40);
numLinesCleared += 4;
}
public void PlayLineClearedSound()
{
audioSource.PlayOneShot(clearedLineSound);
}
public void UpdateHighScore()
{
if (currentScore > startingHighScore)
{
PlayerPrefs.SetInt("highScore3", startingHighScore2);
PlayerPrefs.SetInt("highScore2", startingHighScore);
PlayerPrefs.SetInt("highscore", currentScore);
}
else if (currentScore > startingHighScore2)
{
PlayerPrefs.SetInt("highScore3", startingHighScore2);
PlayerPrefs.SetInt("highscore2", currentScore);
}
else if (currentScore > startingHighScore3)
{
PlayerPrefs.SetInt("highscore3", currentScore);
}
}
public bool CheckIsAboveGrid(Tetromino tetromino)
{
for (int x = 0; x < gridWidth; ++x)
{
foreach (Transform mino in tetromino.transform)
{
Vector2 pos = Round(mino.position);
if (pos.y > gridWeight - 1)
{
return true;
}
}
}
return false;
}
public bool IsFullRowAt (int y)
{
for (int x = 0; x < gridWidth; ++x)
{
if (grid [x, y] == null)
{
return false;
}
}
numberOfRowsThisTurn++;
return true;
}
public void DeleteMinoAt(int y)
{
for (int x = 0; x < gridWidth; ++x)
{
Destroy(grid[x, y].gameObject);
grid[x, y] = null;
}
}
public void MoveRowDown (int y)
{
for (int x = 0; x < gridWidth; ++x)
{
if (grid[x, y] != null)
{
grid[x,y -1] = grid[x, y];
grid[x, y] = null;
grid[x, y -1].position += new Vector3(0, -1, 0);
}
}
}
public void MoveAllRowsDown (int y)
{
for (int i = y; i < gridWeight; ++i)
{
MoveRowDown(i);
}
}
public void DeleteRow()
{
for (int y = 0; y < gridWeight; ++y)
{
if (IsFullRowAt(y))
{
DeleteMinoAt(y);
MoveAllRowsDown(y + 1);
--y;
}
}
}
public void UpdateGrid (Tetromino tetromino)
{
for (int y = 0; y < gridWeight; ++y)
{
for (int x = 0; x < gridWidth; ++x)
{
if (grid[x, y] != null)
{
if (grid[x,y].parent == tetromino.transform)
{
grid[x, y] = null;
}
}
}
}
foreach (Transform mino in tetromino.transform)
{
Vector2 pos = Round(mino.position);
if (pos.y < gridWeight)
{
grid[(int)pos.x, (int)pos.y] = mino;
}
}
}
public Transform GetTransformAtGridPosition (Vector2 pos)
{
if (pos.y > gridWeight -1)
{
return null;
}
else
{
return grid[(int)pos.x, (int)pos.y];
}
}
public void SpawnNextTetromino()
{
if (!gameStarted)
{
gameStarted = true;
nextTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), new Vector2(5.0f, 20.0f), Quaternion.identity);
previewTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), previewTetrominoPosition, Quaternion.identity);
previewTetromino.GetComponent<Tetromino>().enabled = false;
}
else
{
previewTetromino.transform.localPosition = new Vector2(5.0f, 20.0f);
nextTetromino = previewTetromino;
nextTetromino.GetComponent<Tetromino>().enabled = true;
previewTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), previewTetrominoPosition, Quaternion.identity);
previewTetromino.GetComponent<Tetromino>().enabled = false;
}
}
public bool CheckIsInsideGrid (Vector2 pos)
{
return ((int)pos.x >= 0 && (int)pos.x < gridWidth && (int)pos.y >= 0);
}
public Vector2 Round (Vector2 pos)
{
return new Vector2(Mathf.Round(pos.x), Mathf.Round(pos.y));
}
string GetRandomTetromino()
{
int randomTetromino = Random.Range(1, 8);
string randomTetrominoName = "Prefabs/Tetromino_T";
switch (randomTetromino)
{
case 1:
randomTetrominoName = "Prefabs/Tetromino_T";
break;
case 2:
randomTetrominoName = "Prefabs/Tetromino_Long";
break;
case 3:
randomTetrominoName = "Prefabs/Tetromino_Square";
break;
case 4:
randomTetrominoName = "Prefabs/Tetromino_J";
break;
case 5:
randomTetrominoName = "Prefabs/Tetromino_L";
break;
case 6:
randomTetrominoName = "Prefabs/Tetromino_S";
break;
case 7:
randomTetrominoName = "Prefabs/Tetromino_Z";
break;
}
return randomTetrominoName;
}
public void GameOver()
{
UpdateHighScore();
Application.LoadLevel("GameOver");
}
and here's the game menu script
public Text levelText;
public Text highScoreText;
public Text highScoreText2;
public Text highScoreText3;
// Start is called before the first frame update
void Start()
{
levelText.text = "0";
highScoreText.text = PlayerPrefs.GetInt("highscore").ToString();
highScoreText2.text = PlayerPrefs.GetInt("highscore2").ToString();
highScoreText3.text = PlayerPrefs.GetInt("highScore3").ToString();
}
public void PlayGame()
{
if (Game.startingLevel == 0)
Game.startingAtLevelZero = true;
else
Game.startingAtLevelZero = false;
Application.LoadLevel("tetris");
}
public void ChangedValue (float value)
{
Game.startingLevel = (int)value;
levelText.text = value.ToString();
}
public void LaunchGameMenu()
{
Application.LoadLevel("tetris menu");
}
When I got 1120 score in the Tetris game, it shows up in 2nd score instead of 3rd or 1st ,when I got 720 score, it doesn't show up in 3rd score, when I score 1300 It shows up in 2nd and 1120 in 3rd, but not in 1st, can somehow help me what is wrong?
It appears you have various typographical errors while typing the keys when accessing the player's PlayerPrefs. PlayerPrefs is case-sensitive.
↓↓↓
startingHighScore = PlayerPrefs.GetInt("highScore");
startingHighScore2 = PlayerPrefs.GetInt("highscore2");
startingHighScore3 = PlayerPrefs.GetInt("highscore3");
...
↓↓↓
highScoreText.text = PlayerPrefs.GetInt("highscore").ToString();
Consider the use of the nameof() command. The nameof() command allows you to treat a variable in-code as a string. This is SUPER helpful if you ever re-name the variable for example, the string will be renamed along with it. It also has the added bonus of giving you compilation errors if they are misspelled.
Example:
public Text levelText;
public Text highScoreText;
public Text highScoreText2;
public Text highScoreText3;
// Start is called before the first frame update
void Start()
{
levelText.text = "0";
highScoreText.text = PlayerPrefs.GetInt(nameof(highScoreText)).ToString();
highScoreText2.text = PlayerPrefs.GetInt(nameof(highScoreText2)).ToString();
highScoreText3.text = PlayerPrefs.GetInt(nameof(highScoreText3)).ToString();
}
I've made some code in Unity2d with c# and interface.
LevelingSystem.cs is putted in empty gameobject.
And i getting error:
StackOverflowException: The requested operation caused a stack overflow.
PlayerCap.get_actExp () (at Assets/Scripts/player/PlayerCap.cs:17)
PlayerCap.get<message truncated>
CapLevel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
interface ICapLevel
{
float multiplierA { get; set; }
float multiplierB { get; set; }
float multiplierC { get; set; }
float multiplierD { get; set; }
int lvlCap { get; set; }
List<double> expCap { get; set; }
float actExp { get; set; }
void GenerateExpPerLvl();
float RequiredExp(int level);
}
PlayerCap.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCap : ICapLevel
{
public float multiplierA { get { return multiplierA; } set { multiplierA = 280f; } }
public float multiplierB { get { return multiplierB; } set { multiplierB = 100f; } }
public float multiplierC { get { return multiplierC; } set { multiplierA = 1.15f; } }
public float multiplierD { get { return multiplierD; } set { multiplierD = 2.3f; } }
public int lvlCap { get { return lvlCap; } set { lvlCap = 210; } }
public List<double> expCap { get { return expCap; } set { expCap = new List<double>(); } }
public float actExp { get { return actExp; } set { actExp = 0f; } }
public void GenerateExpPerLvl()
{
Debug.Log("implementation successful");
for (int expLevel = 1; expLevel <= lvlCap; expLevel++)
{
expCap.Add(RequiredExp(expLevel - 1));
}
}
public float RequiredExp(int level)
{
double formulaRounded;
var formula = multiplierB * (Mathf.Pow(multiplierC, level - 1)) + multiplierA * (Mathf.Pow(level, multiplierD));
if (formula < 1000)
{
if ((formula % 10) == 0)
{
formulaRounded = formula;
return (float)formulaRounded;
}
else
{
formulaRounded = Math.Round((formula / 1000), 1, MidpointRounding.AwayFromZero);
}
}
else
{
formulaRounded = Math.Round((formula / 1000), 0, MidpointRounding.AwayFromZero);
}
return (float)formulaRounded * 1000;
}
}
LevelingSystem.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LevelingSystem : MonoBehaviour
{
//interface implementation
private PlayerCap _pCap;
private ICapLevel _ICap;
private List<double> _pExpCap;
private int pLvl;
private float _pActExp;
public void Awake()
{
_pCap = new PlayerCap();
_ICap = _pCap;
}
private void Start()
{
_pActExp = _ICap.actExp;
_ICap.GenerateExpPerLvl();
_pExpCap = _ICap.expCap;
}
public void AddExp(float amount)
{
_pActExp += amount;
StartCoroutine(CapLevelCheck(amount));
}
private IEnumerator CapLevelCheck(float amount)
{
while (true)
{
if (_pActExp >= _pExpCap[pLvl])
{
_pActExp -= (float)_pExpCap[pLvl];
AddLevel(1);
} else
{
Debug.Log("You Get " + amount + " Experience and you have " + pLvl + " Lvl. *Click noice!");
break; //otherwise loop will do in infinite
}
yield return 0;
}
}
public void AddLevel(int amount)
{
pLvl += amount;
}
public int GetActualLevel()
{
return pLvl;
}
}
Im try few things like get rid off for in method GenerateExpPerLvl() and error gones away so my suspicious thing is list variable but maybe im wrong.
Thanks for help :)
The problem is here:
public float actExp { get { return actExp; } set { actExp = 0f; } }
// ^ Problem here & ^ same problem here
You are calling your Property inside its own getter and setter. It creates an infinite loop... (everytime you call actExp it will call itself)
Instead you should just write (if there is no logic inside accessors):
public float actExp { get; set; }
I am a little lost here.
Basically, I need to access an array item, a string and display it. Here is the code.
namespace Test3_2_Practice
{
public partial class InterfaceImplementation : Form
{
//Array
ICombatant[] combatants = new ICombatant[2];
public InterfaceImplementation()
{
InitializeComponent();
}
private void btnTest_Click(object sender, EventArgs e)
{
combatants[0] = new PlayerCharacter ("Conan" , 500);
combatants[1] = new MonsterCharacter ("Bob" , 5);
combatants[2] = new MonsterCharacter ("Snake" , 15);
string output = "Fighters" + Environment.NewLine;
for (var i = 0; i < combatants.Length; i++)
{
var character = combatants[i];
output += "Character:" + combatants[i].
}
}
}
}
So I have my array, combatants composed of two types of instances. I want to access the name, "Conan" and add it to a string for output. How do I go about doing that? Here is the rest of the code if that helps. Thanks!
namespace Test3_2_Practice
{
//Interface
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
}
class PlayerCharacter : ICombatant
{
private string characterName;
private int currentHealth;
private int maxHealth;
public string CharacterName
{
get { return characterName; }
set { characterName = value; }
}
public int CurrentHealth
{
get { return currentHealth; }
set { currentHealth = value; }
}
public int MaxHealth
{
get { return maxHealth; }
set { maxHealth = value; }
}
public PlayerCharacter(string characterName, int maxHealth)
{
CharacterName = characterName;
CurrentHealth = MaxHealth = maxHealth;
}
//Damage Class
public int TakeDamage(int damageAmount)
{
if (damageAmount > currentHealth)
{
damageAmount = currentHealth;
return damageAmount;
}
else
{
currentHealth = currentHealth - damageAmount;
return damageAmount;
}
}
//Health Class
public string GetHealthDisplay()
{
return ("Health " + CurrentHealth.ToString() + "/" + MaxHealth).ToString();
}
}
class MonsterCharacter : ICombatant
{
private string monsterName;
private int health;
public string MonsterName
{
get { return monsterName; }
set { monsterName = value; }
}
public int Health
{
get { return health; }
set { health = value; }
}
public MonsterCharacter(string monsterName, int health)
{
MonsterName = monsterName;
Health = health;
}
//Damage Class
public int TakeDamage(int damageAmount)
{
if(damageAmount > health)
{
damageAmount = health;
return damageAmount;
}
else
{
health = health - damageAmount;
return damageAmount;
}
}
//Health Class
public string GetHealthDisplay()
{
return "Health " + Health;
}
}
}
Actually, since name is common to all implementer of interface that Name property should be included to interface itself like
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
public string CharacterName
{
get;
set;
}
}
In your current scenario, you will have to cast it specific concrete type before accessing it
var character = combatants[i];
if(character is PlayerCharacter)
output += "Character:" + ((PlayerCharacter)character).CharacterName;
It's better to make a good use of your interface. Create a new method in your interface:
interface ICombatant
{
int TakeDamage(int damageAmount);
string GetHealthDisplay();
string GetCombatantName(); // added this
}
Then implement in both classes which implements it:
class PlayerCharacter : ICombatant
{
// ... a lot of code ...
public string GetCombatantName()
{
return String.Format("Character: {0}", this.CharacterName);
}
}
class MonsterCharacter: ICombatant
{
// ... a lot of code ...
public string GetCombatantName()
{
return String.Format("Monster: {0}", this.MonsterName);
}
}
And use it like this:
private void btnTest_Click(object sender, EventArgs e)
{
combatants[0] = new PlayerCharacter("Conan", 500);
combatants[1] = new MonsterCharacter("Bob", 5);
combatants[2] = new MonsterCharacter("Snake", 15);
string output = "Fighters" + Environment.NewLine;
foreach (var combatant in combatants)
{
output += combatant.GetCombatantName();
}
}
So if one day you get ten distinct types of ICombatant (like AnimalCharacter, VirusCharacter), you don't have to nest a lot of ifs to check and cast types to get the proper property.
Interfaces are meant exactly to avoid this kind of stuff, hiding the implementation details.