How to get other player's value in Unity when I use Mirror Network? - unity3d

Hello? I'm studying the MIRROR Network Now.
enter image description here
However, I have a problem about getting other player's value. This image explain what I want to do.
enter image description here
I create 3 projects. One is server(local host) and other is Client A , the other is Client B.
Firstly, I wrote code like this :
public class PlayerManager : NetworkBehaviour
{
[SyncVar(hook = nameof(onValueChanged))]
int value = 0;
private void Update()
{
if(isServer && Input.GetKeyDown("x"))
{
Message();
}
}
public override void OnStartServer()
{
Debug.Log("Here is Game Room Scene, Player add Successfully");
}
[Command]
private void Hola()
{
value++;
Debug.Log("Received Hola from the client!");
Debug.Log("Server Value : " + value);
ReplyHola();
}
[TargetRpc]
private void ReplyHola()
{
Debug.Log("Received Hola from Client!");
}
[ClientRpc]
private void Message()
{
Debug.Log("Ping...");
}
[ClientRpc]
private void UpdateValue(int value)
{
this.value = value;
}
private void onValueChanged(int oldValue, int newValue)
{
Debug.Log("New Value Detective :");
Debug.Log("Old Value : " + oldValue);
Debug.Log("New Value : " + newValue);
Debug.Log("Sum Value : " + PlayerStat.Value);
}
}
3 Projects have all same code. I referenced code from this video(https://www.youtube.com/watch?v=8tKFF0RP9Jw).
And, I wrote code about sum client A and B's code like this:
private void SumDatas()
{
foreach(var playerObj in FindObjectsOfType(typeof(GameObject)) as GameObject[])
{
if(gameObject.name == "Player(Clone)")
{
PlayerStat.Value += GameObject.Find("Player(Clone)").transform.GetComponent<PlayerManager>().GetValue();
}
}
}
PlayerStat is a static class and Code is like this:
public static class PlayerStat
{
public static int Value { get; set; }
}
Is there anybody help me?

I solved this problem. I will not delete this question for other people who will have same problem with me.
I add this code at my server project, Client A and B project:
[SyncVar(hook = nameof(onValueChanged))]
int value = 0;
int myValue = 0;
private void Update()
{
myValue = PlayerStat.Value;
}

Related

Start highest unlocked level(scene) on button click

Im new in developing so need some help for my game!
On my game I have 2 buttons one is "Play" and other "Level Select"
I stuck at the "Play" button, need to make a script that is always loading the highest level that is unlocked, not current but highest.
Here is the code that im using for level manager
public List<Button> levelButton;
public Sprite lockimage;
public bool delete;
private void Start()
{
int saveIndex = PlayerPrefs.GetInt("SaveIndex");
for (int i = 0; i < levelButton.Count; i++)
{
if (i <= saveIndex)
{
levelButton[i].interactable = true;
}
else
{
levelButton[i].interactable = false;
levelButton[i].GetComponent<Image>().sprite = lockimage;
}
}
}
public void LevelSelect()
{
int level = int.Parse(EventSystem.current.currentSelectedGameObject.name);
SceneManager.LoadScene(level);
}
public void PlayGame()
{
//code here
}
public void ResetGame()
{
PlayerPrefs.SetInt("SaveIndex", 0);
SceneManager.LoadScene(0);
}
public void DontResetGame()
{
SceneManager.LoadScene(0);
}
}
SceneManager.LoadScene(PlayerPrefs.GetInt("SaveIndex"));
edit: adding some info/context.
I realized that you set level buttons interactivity on the start functions based on the int save_index value you get from PlayerPrefs.
From there, I assumed that you could load the level directly using that same value on the PlayGame function.
Do note that the code I wrote will throw an error, if the "SaveIndex" key is not yet on PlayerPrefs

Boolean not changing values from one class to another

I'm currently working on this Clash Royale style game in Java FX and I have a game timer in one class that I set in my test condition. However, when I check its value over on the GameView class it's always false.
I've looked at many examples and the latest I tried making my properties static in my timer class but that didn't have any effect either. Hoping someone could steel me in the right direction. Thanks!
public class GameTimer {
public int seconds = 180;
public static boolean endGame;
public static boolean returnBool () {
return endGame;
}
public static boolean isEndGame() {
return endGame;
}
public static void setEndGame(boolean endGame) {
GameTimer.endGame = endGame;
}
Timer timer = new Timer();
TimerTask task = new TimerTask(){
public void run(){
seconds--;
System.out.println("180 / " + seconds);
if (seconds == 170){
System.out.println("170 seconds hit the spot" );
endGame = true;
this.cancel();
}
}
};
public void start(){
timer.scheduleAtFixedRate(task, 1000, 1000);
isEndGame();
}
}
public class GameViewManager {
public void gameTimer() {
GameTimer timer = new GameTimer();
timer.start();
//System.out.println(timer.returnBool());
if (timer.isEndGame()){
//gameStage.close();
System.out.println("test");
}
}
}

Using PlayerPrefs (unity)

I have recently been creating a game with tutorials. Unfortunately, they didn't cover a save score feature. Thanks to another user, I was able to figure out that I needed to use playerprefs. I watched tutorials online, but none of them were helpful. If you can, please help me!
Gold Per Sec Script:
using UnityEngine;
using System.Collections;
public class GoldPerSec : MonoBehaviour {
public UnityEngine.UI.Text gpsDisplay;
public Click click;
public ItemManager[] items;
void Start () {
StartCoroutine(AutoTick ());
}
void Update () {
gpsDisplay.text = GetGoldPerSec() + " Money Per Sec";
}
public float GetGoldPerSec() {
float tick = 0;
foreach (ItemManager item in items) {
tick += item.count * item.tickValue;
}
return tick;
}
public void AutoGoldPerSec() {
click.gold += GetGoldPerSec() / 10;
}
IEnumerator AutoTick() {
while (true) {
AutoGoldPerSec();
yield return new WaitForSeconds(0.10f);
}
}
}
Gold Per Click script:
using UnityEngine;
using System.Collections;
public class Click : MonoBehaviour {
public UnityEngine.UI.Text gpc;
public UnityEngine.UI.Text goldDisplay;
public float gold = 0.00f;
public int goldperclick = 1;
void Update () {
goldDisplay.text = "" + gold.ToString("F0");
gpc.text = "Money Per Click: " + goldperclick;
}
public void Clicked(){
gold += goldperclick;
}
}
My idea was for the game to save when the game is quit, and load as soon as you load the game back up. I am a complete beginner, if anyone can tell me how to do this, please tell me! Thanks! :D
You can use unity's existing functions to achieve this.
For saving data use unity's OnApplicationQuit function like this
void OnApplicationQuit() {
PlayerPrefs.SetFloat("key", value);
}
And for Restoring the values use unity's Awake function like this
void Awake(){
value = PlayerPrefs.GetFloat("key");
}
Please note that PlayerPrefs is an easy way to save data but also an very unsafe way. The player can easily manipulate his "goldValue" since it's just stored as an integer in some file on his device. PlayerPrefs should usually just be used for values the player can changed any way within in game, like volume setting etc.
EXAMPLE CODE
void Save()
{
string filename = "/filename.dat";
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath+filename);
bf.Serialize(file, goldValue); //Use can easily use e.g. a List if you want to store more date
file.Close();
}
bool Load()
{
string filename = "/filename.dat";
if (File.Exists(Application.persistentDataPath + filename))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + filename, FileMode.Open);
goldValue=(int) bf.Deserialize(file);
file.Close();
return true;
}
return false;
}
Add the following code to Click class:
void Awake()
{
LoadData();
}
void OnApplicationQuit()
{
SaveData();
}
void SaveData()
{
PlayerPrefs.SetFloat("gold",gold);
}
void LoadData()
{
gold = PlayerPrefs.GetFloat("gold",0f);
}

I'm stuck at slick graphics

I'm trying to make a game, using slick2d, and lwjgl. I don't get why this code doesn't work
firstStage.java
package net.CharlesDickenson;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class firstStage extends BasicGameState {
public bossVar bossChecker() {
if(isBeforeMiddleBoss) return bossVar.beforeBoss;
if(isMiddleBoss) return bossVar.Middle;
if(isBeforeBoss) return bossVar.beforeBoss;
if(isBoss) return bossVar.Boss;
return null;
}
#SuppressWarnings("static-access")
public firstStage(int state) {
this.state = state;
}
#Override
public void init(GameContainer _arg0, StateBasedGame _arg1)
throws SlickException {
scoreBoard = new Image("res/scoreBoard.png");
backs = new Image("res/1stageBack.gif");
isBeforeMiddleBoss = true;
isMiddleBoss = false;
isBeforeBoss = false;
isBoss = false;
_arg0.setShowFPS(false);
}
#Override
public void render(GameContainer arg0, StateBasedGame _arg1, Graphics _g)
throws SlickException {
this._g = _g;
new Mob().getGraphics(_g);//i passed graphics
new Char().getGraphics(_g);//i passed graphics
new Bullet().getGraphics(_g);//i passed graphics
_g.drawImage(scoreBoard, 550, 5);
_g.drawImage(backs, 10, 10);
_g.drawString(fps, 580, 570);
_g.drawString("High Score-> Not avaiable", 560, 60);
_g.drawString("Score-> " + currScore, 595, 80);
}
#Override
public void update(GameContainer _arg0, StateBasedGame _arg1, int arg2)
throws SlickException {
fps = "Frame Per Second-> " + _arg0.getFPS();
bossVar b = bossChecker();
switch(b) {
case beforeMiddle :
break;
case Boss :
break;
default:
break;
}
}
#SuppressWarnings("static-access")
#Override
public int getID() {
return this.state;
}
private static int state;
private static int currScore = 0;
private static final int originX = 270;
private static final int originY = 490;
public static int X = originX;
public static int Y = originY;
private static String fps;
private Image scoreBoard;
private Image backs;
private Graphics _g;
public boolean isBeforeMiddleBoss;
public boolean isMiddleBoss;
public boolean isBeforeBoss;
public boolean isBoss;
}
Char.java
package net.CharlesDickenson;
import org.lwjgl.input.Keyboard;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
public class Char extends Bullet implements Entity {
#Override
public void getGraphics(Graphics _g) {
this._g = _g;//so i got graphics, but
if(!isInit) return;
_g.drawImage(Char, getCharX(), getCharY());//this codes doesn't works.
}
#Override
public int getCharX() {
switch(VarTracker.stage) {
case 1:
return firstStage.X;
}
return 0;
}
#Override
public int getCharY() {
switch(VarTracker.stage) {
case 1:
return firstStage.Y;
}
return 0;
}
public void setCharX(int i) {
System.out.println("asdgagsd");
switch(VarTracker.stage) {
case 1:
firstStage.X += i;
}
}
public void setCharY(int i) {
System.out.println("asdgagsd");
switch(VarTracker.stage) {
case 1:
firstStage.Y += i;
}
}
#Override
public void update() {
if(!isInit) return;
_g.drawImage(Char, getCharX(), getCharY());//this code doesn't work, too.
up = Keyboard.isKeyDown(Keyboard.KEY_UP);
down = Keyboard.isKeyDown(Keyboard.KEY_DOWN);
left = Keyboard.isKeyDown(Keyboard.KEY_LEFT);
right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
z = Keyboard.isKeyDown(Keyboard.KEY_Z);
if(up && !shift) {
setCharY(6);
}
if(down && !shift) {
setCharY(-6);
}
if(left && !shift) {
setCharX(-6);
}
if(right && !shift) {
setCharX(6);
}
if(up && shift) {
setCharY(2);
}
if(down && shift) {
setCharY(-2);
}
if(left && shift) {
setCharX(-2);
}
if(right && shift) {
setCharX(2);
}
if(z) {
new Bullet().isFiring = true;
}
if(!z) {
new Bullet().isFiring = false;
}
}
#Override
public void init() {
System.out.println("<Char> Initializing...");
isInit = false;
try {
Char = new Image("res/char.png");
} catch (SlickException e) {
e.printStackTrace();
}
isInit = true;
System.out.println("<Char> Done with init()");
}
private boolean up;
private boolean down;
private boolean left;
private boolean right;
private boolean shift;
private boolean z;
private boolean isInit;
private Image Char;
private Graphics _g;
}
I passed graphics to other class using getGraphics method, to put a image, but it doesn't work.
at render method, it worked, but I can't put a image in other class.
The reason that it doesn't work is that you are using Graphics incorrectly. When Slick2d draws something, it uses the render method. This method is passed an instance of Graphics, to which you can draw stuff. When the call ends the Graphics object is no longer useful for anything. There is thus no reason to pass it to anything that doesn't use it immediately.
What you want to do is create a render method in your Mob, Char and Bullet classes. Make instances of said classes outside of the render method, for instance in init and store them in some data structure, for instance a List. In the render method, you simple traverse the list and call render or draw on each element. A quick example:
// Give the Entity interface two methods if they don't exist already:
public interface Entity {
void render(Graphics g);
void update(int delta);
}
// In firststage.java
List<Entity> list;
// In the init() method
public void init(GameContainer container, StateBasedGame game)
throws SlickException {
...
list = new ArrayList<Entity>();
list.add(new Mob());
list.add(new Char());
list.add(new Bullet());
}
// In the render method
public void render(GameContainer container, StateBasedGame game, Graphics g)
throws SlickException {
...
for (Entity e : list) {
e.draw(g);
}
}
// In the update method
public void update(GameContainer container, StateBasedGame game, int delta)
throws SlickException {
...
for (Entity e : list) {
e.update(delta);
}
}
TL;DR version: The Graphics object exists only to be drawn to in a single render call.
Render is called many times a second, so object creation in that method is not recommended.
Object oriented programming is good at modeling objects. Games tend to model a lot of objects. Make use of it.

GWT CEll Browser Real Time Update

has someone been able to correctly to update a cell browser at runtime, i.e. when u remove a node or add a node, the change is reflected immediately in the CEll Browser, because I am using a List and when i am making a change it is not being updated on the spot
You can use ListDataProvider setList(...) method for dynamic updates. Here is an example how I update cell browser via RPC:
private void loadAllData(final ListDataProvider<Data> dataProvider) {
dBservice.getAllData(new AsyncCallback<List<Data>>() {
public void onSuccess(List<Data> result) {
dataProvider.setList(result);
}
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
});
}
to refresh a cellBrowser you have to close all the child on the root node.
anyway something like this
for (int i = 0; i < cellBrowser.getRootTreeNode().getChildCount(); i++) {
cellBrowser.getRootTreeNode().setChildOpen(i, false);
}
the AsyncDataProvider calls refreshes data
private final class Model implements TreeViewModel{
private List<ZonaProxy> zonaList = null;
private List<CategoriaProxy> categoriaList = null;
public void setCategoriaList(List<CategoriaProxy> categoriaList) {
this.categoriaList = categoriaList;
}
public void setListZona(List<ZonaProxy> zonaList) {
this.zonaList = zonaList;
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public <T> NodeInfo<?> getNodeInfo(T value) {
CategoryDataProvider dataProvider1 = new CategoryDataProvider();
return new DefaultNodeInfo(dataProvider1, new CategoriaCell());
}
/**
* Check if the specified value represents a leaf node. Leaf nodes cannot be
* opened.
*/
public boolean isLeaf(Object value) {
if (value instanceof CategoriaProxy){
if (((CategoriaProxy) value).getLivello() == 3) {
return true;
}
}
return false;
}
}
private class CategoryDataProvider extends AsyncDataProvider<CategoriaProxy>
{
#Override
protected void onRangeChanged(HasData<CategoriaProxy> display)
{
requests.categoriaRequest().findAllCategorias(0, 8).with().fire(new Receiver<List<CategoriaProxy>>() {
#Override
public void onSuccess(List<CategoriaProxy> values) {
updateRowCount(values.size(), true);
updateRowData(0, values);
}
});
}
}
it Works.
Apparently it is not enough to change the data provider and refresh it.
You need also to force the affected cell to close and reopen it, as in this example
public void updateCellBrowser(String id) {
TreeNode node = getNode(cellBrowser.getRootTreeNode(),id);
if(node != null && ! node.isDestroyed()) {
TreeNode parent = node.getParent();
int index = node.getIndex();
parent.setChildOpen(index, false,true);
parent.setChildOpen(index, true, true);
}
}
In my particular example the cell ids are pathnames hence the following
implementation of getNode().
private TreeNode getNode(TreeNode node, String id) {
for(int i=0; i < node.getChildCount(); i++)
if(node.isChildOpen(i)) {
Object value = node.getChildValue(i);
if(value instanceof String) {
String nodeId = ((String) value);
if(id.equals(nodeId))
return node.setChildOpen(i, true);
if(id.startsWith(nodeId))
getNode(node.setChildOpen(i, true),id);
}
}
return null;
}