I'm using Unity Mirror for networking my app so that a central server (not host) can send commands to the clients it is connected to.
On play, the "game" will make the program a client or server automatically on play, so i don't have to use the Client/Server only buttons provided by the NetworkManagerHUD.
Currently I'm facing 2 problems:
Client disconnects right after a connection with server is made. When I override the OnClientConnect function, I put the line base.OnClientConnect(conn). After stepping into the original function, I conclude it is the autoCreatePlayer set to true that is causing this problem. (the server and client are two instances of the program running on the same computer as I can only test using localhost).
public override void OnClientConnect(NetworkConnection conn)
{
base.OnClientConnect(conn); //This line causes the error message
clientConnected = true;
GameObject[] prefabs = Resources.LoadAll<GameObject>("NetworkingComponents");
foreach (var prefab in prefabs)
{
NetworkClient.RegisterPrefab(prefab);
}
GameObject[] gos = Resources.LoadAll<GameObject>("NetworkingComponents");
}
Perhaps the most critical issue. Referring to the previous problem, if i did remove the line
base.OnClientConnect(conn), client can connect, but all networked gameobjects (with NetworkIdentity) are still not showing up when connected as client, even though the NetworkManagerHUD says the program is connected as client. (Strangely, they are showing up if connected as Server.)
Here is the rest of the overriden NetworkManager code.
public class MyNetworkManager : NetworkManager
{
public GameObject dropdown;
public Canvas canvas;
//---------------------------Networking stuff----------------------------------
public List<NetworkNode> networkedNodes { get; } = new List<NetworkNode>();
public List<Settings> networkedSettings { get; } = new List<Settings>();
public List<NetworkedVisualisersDisplay> visualisersDisplays { get; } = new List<NetworkedVisualisersDisplay>();
public List<Visualiser> visualisers{ get; } = new List<Visualiser>();
public static MyNetworkManager instance = null;
public NetworkedVisualisersDisplay visDisplayPrefab;
public NetworkNode networkNode;
private string homeName;
public volatile bool clientConnected = false;
public bool IsClientConnected()
{
return clientConnected;
}
//the purpose of having a delay is that we need to determine if the call to StartClient() actually started the player as a client. It could fail if it’s the first player instance on the network.
public IEnumerator DelayedStart()
{
//base.Start();
StartClient();
yield return new WaitForSeconds(2);
print("conn count " + NetworkServer.connections.Count);
if (!IsClientConnected())
{
NetworkClient.Disconnect();
print(“starting as server”);
StartServer();
clientConnected = false;
}
else
{
print("starting as client");
}
visDisplayPrefab = Resources.Load<NetworkedVisualisersDisplay>("NetworkingComponents/NetworkedVisualisersDisplay");
if (instance == null)
{
instance = this;
print("instance = " + this);
}
else
{
print("manager destroyed");
Destroy(gameObject);
}
yield return null;
}
//-----------------------------------------------------------------------------
public override void Start(){
StartCoroutine(DelayedStart());
}
public override void OnStartServer()
{
GameObject[] prefabs = Resources.LoadAll<GameObject>("NetworkingComponents");
foreach (var prefab in prefabs)
{
spawnPrefabs.Add(prefab);
}
}
public override void OnServerChangeScene(string scenename)
{
if (scenename.Equals("Visualisers"))
{
for (int i = 0; i < visualisersDisplays.Count; i++)
{
var conn = networkedNodes[i].connectionToClient;
NetworkedVisualisersDisplay visSceneInstance = Instantiate(visualisersDisplays[i]);
NetworkServer.Destroy(conn.identity.gameObject);
NetworkServer.ReplacePlayerForConnection(conn, visSceneInstance.gameObject);
}
}
else if (Settings.Instance.sceneNames.Contains(scenename))
{
for (int i = 0; i < visualisersDisplays.Count; i++)
{
var conn = visualisers[i].connectionToClient;
var visInstance = Instantiate(visualisers[i]);
NetworkServer.Destroy(conn.identity.gameObject);
NetworkServer.ReplacePlayerForConnection(conn, visInstance.gameObject);
}
}
}
public override void OnServerAddPlayer(NetworkConnection conn)
{
NetworkNode n = Instantiate(networkNode);
NetworkServer.AddPlayerForConnection(conn, n.gameObject);
NetworkNode.instance.DisplayMessage();
}
public override void OnClientConnect(NetworkConnection conn)
{
base.OnClientConnect(conn);
//we are connected as a client
clientConnected = true;
GameObject[] prefabs = Resources.LoadAll<GameObject>("NetworkingComponents");
foreach (var prefab in prefabs)
{
NetworkClient.RegisterPrefab(prefab);
}
}
}
Any help will be greatly appreciated!
I'm trying to save a variable using google play games cloud save. However it crashes when it signs in. I've definitely enabled it on the developer console. I never had this problem before I added the cloud save feature and it was just doing achievements and scoreboards. Also, when I'm not connected to the internet, it doesn't crash and locally saving the data works fine. Can any one help?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using System.Text;
public class playgamesscript : MonoBehaviour {
public static playgamesscript Instance { get; private set; }
const string SAVE_NAME = "Test";
bool isSaving;
textEdit textEditScript;
control controlScript;
bool isCloudDataLoaded;
// Use this for initialization
void Start () {
Instance = this;
textEditScript = GameObject.FindGameObjectWithTag("UIControl").GetComponent<textEdit>();
controlScript = GameObject.FindGameObjectWithTag("Control").GetComponent<control>();
if (!PlayerPrefs.HasKey(SAVE_NAME))
PlayerPrefs.SetString(SAVE_NAME, "0");
if (!PlayerPrefs.HasKey("IsFirstTime"))
PlayerPrefs.SetInt("IsFirstTime", 1);
LoadLocal();
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
if (control.signInAttempt == false)
{
SignIn();
}
}
void SignIn()
{
control.signInAttempt = true;
Social.localUser.Authenticate(success => { LoadData(); });
}
#region Saved Games
string GameDataToString()
{
return control.Highscore.ToString();
}
void StringToGameData(string cloudData, string localData)
{
if (PlayerPrefs.GetInt("IsFirstTime") == 1){
PlayerPrefs.SetInt("IsFirstTime", 0);
if (int.Parse(cloudData) > int.Parse(localData)){
PlayerPrefs.SetString(SAVE_NAME, cloudData);
}
}
else if (int.Parse(localData) > int.Parse(cloudData))
{
control.Highscore = int.Parse(localData);
AddScoreToLoeaderBoard(textEdit.leaderboardStat, control.Highscore);
isCloudDataLoaded = true;
SaveData();
return;
}
control.Highscore = int.Parse(cloudData);
isCloudDataLoaded = true;
}
void StringToGameData (string localData)
{
control.Highscore = int.Parse(localData);
}
void LoadData()
{
if (Social.localUser.authenticated)
{
isSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(SAVE_NAME, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else {
LoadLocal();
}
}
private void LoadLocal()
{
StringToGameData(PlayerPrefs.GetString(SAVE_NAME));
}
public void SaveData()
{
if (!isCloudDataLoaded)
{
SaveLocal();
return;
}
if (Social.localUser.authenticated)
{
isSaving = true;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(SAVE_NAME, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
SaveLocal();
}
}
private void SaveLocal()
{
PlayerPrefs.SetString(SAVE_NAME, GameDataToString());
}
private void ResolveConflict(IConflictResolver resolver, ISavedGameMetadata original, byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData)
{
if (originalData == null)
{
resolver.ChooseMetadata(unmerged);
} else if (unmergedData == null)
{
resolver.ChooseMetadata(original);
} else
{
string originalStr = Encoding.ASCII.GetString(originalData);
string unmergedStr = Encoding.ASCII.GetString(unmergedData);
int originalNum = int.Parse(originalStr);
int unmergedNum = int.Parse(unmergedStr);
if (originalNum > unmergedNum)
{
resolver.ChooseMetadata(original);
return;
} else if (unmergedNum> originalNum)
{
resolver.ChooseMetadata(unmerged);
}
resolver.ChooseMetadata(original);
}
}
private void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game)
{
if (status == SavedGameRequestStatus.Success)
{
if (!isSaving)
{
LoadGame(game);
} else
{
SaveGame(game);
}
}
else
{
if (!isSaving)
{
LoadLocal();
}else
{
SaveLocal();
}
}
}
private void LoadGame(ISavedGameMetadata game)
{
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game, OnSavedGameDataRead);
}
private void SaveGame(ISavedGameMetadata game)
{
string stringToSave = GameDataToString();
PlayerPrefs.SetString(SAVE_NAME, stringToSave);
byte[] dataToSave = Encoding.ASCII.GetBytes(stringToSave);
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game, update, dataToSave, OnSavedGameDataWritten);
}
private void OnSavedGameDataRead(SavedGameRequestStatus status, byte[] savedData)
{
if (status == SavedGameRequestStatus.Success)
{
string cloudDataString;
if (savedData.Length == 0)
{
cloudDataString = "0";
} else
cloudDataString = Encoding.ASCII.GetString(savedData);
string localDataString = PlayerPrefs.GetString(SAVE_NAME);
StringToGameData(cloudDataString, localDataString);
}
}
private void OnSavedGameDataWritten(SavedGameRequestStatus status, ISavedGameMetadata game)
{
}
#endregion /Saved Games
///
JNI DETECTED ERROR IN APPLICATION: can't call void com.google.android.gms.common.api.PendingResult.setResultCallback(com.google.android.gms.common.api.ResultCallback) on null object'
In unity I keep getting the error message "NullReferenceException: Object reference not set to an instance of an object" on this:
listOfBanks[0].Deposit(50);
and
accntBlnce.text = "Account Balance:\n" + listOfBanks[curBank].GetBalance().ToString("c");
I have 3 options listed in the drop down menu and when I Debug.Log the number of items in the array I get 3 as my count. But I can't do anything with them. The banks variable is set as the Dropdown object in the inspector as well as the accntBlnce as the text object in my panel.
The code is below.
Banks.cs
public class Banks : MonoBehaviour {
public Dropdown banks;
public Text accntBlnce;
public Bank[] listOfBanks;
public int curBank = 0;
void Start() {
listOfBanks = new Bank[banks.options.Count];
listOfBanks[0].Deposit(50);
}
void Update() {
curBank = banks.value;
accntBlnce.text = "Account Balance:\n" + listOfBanks[curBank].GetBalance().ToString("c");
}
}
Bank.cs
public class Bank{
public Bank() { }
public Bank(string orgn, float amntToRprt, float blnce) {
origin = orgn;
amountToReport = amntToRprt;
balance = blnce;
}
public string origin { get; set; }
public float amountToReport { get; set; }
public float balance { get; set; }
public bool Deposit(float amnt) {
if (amnt > 0) {
balance += amnt;
if(amnt > amountToReport) {
FlagForReport();
}
return true;
}
else
return false;
}
private void FlagForReport() {
throw new NotImplementedException();
}
public float GetBalance() {
return balance;
}
public bool Withdraw(float amnt) {
if (amnt > 0) {
if (balance >= amnt) {
balance -= amnt;
return true;
}
else
return false;
}
else
return false;
}
public bool Transfer(float amnt, Bank bank) {
if (amnt > 0) {
if (balance >= amnt) {
if(bank.Deposit(amnt))
balance -= amnt;
return true;
}
else
return false;
}
else
return false;
}
}
This is the fourth time array question is asked this week with the-same problem and the-same solution.
You declared the array here:
listOfBanks = new Bank[banks.options.Count];
but you did not create new instance of each Bank script before calling
listOfBanks[0].Deposit(50); and listOfBanks[curBank].GetBalance().ToString("c").
Declaring array and setting the size is NOT the-same as creating new instance of a script.
The solution is to loop through the array and create new instance of each one.
In your Banks.cs, replace the code in your Start() function with the one below:
void Start()
{
//Declare how much Bank array should be created
listOfBanks = new Bank[banks.options.Count];
//Now Create instance of each bank
for (int i = 0; i < listOfBanks.Length; i++)
{
//Create new instance of each Bank class
//listOfBanks[i] = new Bank();
listOfBanks[i] = new Bank("", 50, 50);
}
listOfBanks[0].Deposit(50);
}
I get the following log during on-device debugging
Error:
*** [Play Games Plugin DLL] ERROR: Cloud load failed with status code 7
Basically the OnStateLoaded() callback function always returns the boolean success = false and I can't figure out the reason why.
All that the plugin debugging logs mention is "Cloud load failed with status code 7".
According to the android doc, 7 is a generic "developer error", see https://developer.android.com/reference/com/google/android/gms/appstate/AppStateStatusCodes.html#STATUS_DEVELOPER_ERROR
I tried a quick sample and everything worked ok. Here are my steps:
Created a new game in the play console
(https://play.google.com/apps/publish)
Made sure Saved Games is set
to ON
Linked an Android Application Remembering the application ID
(the number after the title) and the package ID
Created a new project in Unity
Added the play games plugin (Assets/Import Package.../Custom
Package)
Set the application ID (Google Play Games/Android Setup...)
Switched the platform to Android (File/Build Settings...)
Set the player settings (bundle identifier and the keystore info)
Added a new script component to the camera
Saved everything and hit build and run.
Here are the contents:
using UnityEngine;
using System.Collections;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using System;
public class SaveSample : MonoBehaviour {
System.Action<bool> mAuthCallback;
GameData slot0;
void Start () {
slot0 = new GameData(0,"waiting for login....");
mAuthCallback = (bool success) => {
if (success) {
Debug.Log("Authentication was successful!");
slot0.Data =" loading....";
slot0.LoadState();
}
else {
Debug.LogWarning("Authentication failed!");
}
};
// make Play Games the default social implementation
PlayGamesPlatform.Activate();
// enable debug logs
PlayGamesPlatform.DebugLogEnabled = true;
//Login explicitly for this sample, usually this would be silent
PlayGamesPlatform.Instance.Authenticate(mAuthCallback, false);
}
protected void OnGUI() {
Screen.fullScreen = true;
int buttonHeight = Screen.height / 20;
int buttonWidth = Screen.width / 5;
GUI.skin.label.fontSize = 60;
GUI.skin.button.fontSize = 60;
Rect statusRect = new Rect(10,20,Screen.width,100);
Rect dataRect = new Rect( 10, 150, Screen.width,100);
Rect b1Rect = new Rect(10, 400, buttonWidth, buttonHeight);
Rect b2Rect = new Rect(b1Rect.x + 20 + buttonWidth,
b1Rect.y, buttonWidth, buttonHeight);
if(!Social.localUser.authenticated) {
if(GUI.Button(b1Rect, "Signin")) {
Social.localUser.Authenticate(mAuthCallback);
}
}
else {
// logged in, so show the load button and the contents of the saved data.
if(GUI.Button(b1Rect, "Load")) {
slot0.LoadState();
}
GUI.Label(dataRect, slot0.Data);
}
if(GUI.Button(b2Rect, "Save")) {
// just save a string, incrementing the number on the end.
int idx = slot0.Data.IndexOf("_");
if (idx > 0) {
int val = Convert.ToInt32(slot0.Data.Substring(idx+1));
val++;
slot0.Data = "Save_" + val;
}
else {
slot0.Data = "Save_0";
}
slot0.SaveState();
}
GUI.Label(statusRect, slot0.State);
}
// Class to handle save/load callbacks.
public class GameData : OnStateLoadedListener {
int slot;
string data;
string state;
public GameData(int slot, string data) {
this.slot = slot;
this.data = data;
this.state = "Initialized, modified";
}
public void LoadState() {
this.state += ", loading";
((PlayGamesPlatform)Social.Active).LoadState(0, this);
}
public void SaveState() {
byte[] bytes = new byte[data.Length * sizeof(char)];
System.Buffer.BlockCopy(data.ToCharArray(), 0, bytes, 0, bytes.Length);
this.state += ", saving";
((PlayGamesPlatform) Social.Active).UpdateState(slot, bytes, this);
}
public void OnStateLoaded(bool success, int slot, byte[] data) {
if (success) {
Debug.Log ("Save game slot : " + slot + " loaded: " + data);
if (data != null) {
char[] chars = new char[data.Length / sizeof(char)];
System.Buffer.BlockCopy(data, 0, chars, 0, data.Length);
this.data = new string(chars);
this.state = "loaded";
} else {
Debug.Log ("Saved data is null");
this.data = "";
this.state = "loaded, but empty";
}
} else {
// handle failure
Debug.LogWarning ("Save game slot : " + slot + " failed!: ");
this.data = "";
this.state = "loading failed!";
}
}
public byte[] OnStateConflict(int slot, byte[] local, byte[] server) {
// resolve conflict and return a byte[] representing the
// resolved state.
Debug.LogWarning("Conflict in saved data!");
state = "conflicted";
// merge or resolve using app specific logic, here
byte[] resolved = local.Length > server.Length ? local : server;
char[] chars = new char[resolved.Length / sizeof(char)];
System.Buffer.BlockCopy(resolved, 0, chars, 0, resolved.Length);
this.data = new string(chars);
return resolved;
}
public void OnStateSaved(bool success, int slot) {
Debug.Log ("Save game slot : " + slot + " success: " + success);
state = "saved";
}
public string Data {
get {
return data;
}
set {
data = value;
state += ", modified";
}
}
public int Slot {
get {
return slot;
}
}
public string State {
get {
return state;
}
}
}
}
The error code 7 is because the Cloud Save API has been deprecated and is only currently accessible to existing games that have used the API. The Unity plugin version 0.9.11 has been updated to use the SavedGames API.
I tried a quick sample and everything worked ok. Here are my steps:
Created a new game in the play console
(https://play.google.com/apps/publish)
Made sure Saved Games is set to ON
Linked an Android Application Remembering the application ID
(the number after the title) and the package ID Created a new
project in Unity
Added the play games plugin (Assets/Import
Package.../Custom Package)
Set the application ID (Google Play
Games/Android Setup...)
Switched the platform to Android (File/Build
Settings...)
Set the player settings (bundle identifier and the
keystore info)
Added a new script component to the camera Saved
everything and hit build and run.
Here is my script:
using UnityEngine;
using System.Collections;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using System;
using GooglePlayGames.BasicApi.SavedGame;
public class SaveSample : MonoBehaviour {
System.Action<bool> mAuthCallback;
GameData slot0;
bool mSaving;
private Texture2D mScreenImage;
// Use this for initialization
void Start () {
slot0 = new GameData("New game");
mAuthCallback = (bool success) => {
if (success) {
Debug.Log("Authentication was successful!");
slot0.State = "Click load or save";
}
else {
Debug.LogWarning("Authentication failed!");
}
};
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
.EnableSavedGames()
.Build();
PlayGamesPlatform.InitializeInstance(config);
// Activate the Play Games platform. This will make it the default
// implementation of Social.Active
PlayGamesPlatform.Activate();
// enable debug logs (note: we do this because this is a sample; on your production
// app, you probably don't want this turned on by default, as it will fill the user's
// logs with debug info).
PlayGamesPlatform.DebugLogEnabled = true;
//Login explicitly for this sample, usually this would be silent
PlayGamesPlatform.Instance.Authenticate(mAuthCallback, false);
}
public void CaptureScreenshot() {
mScreenImage = new Texture2D(Screen.width, Screen.height);
mScreenImage.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
mScreenImage.Apply();
}
protected virtual void OnGUI() {
Screen.fullScreen = true;
int buttonHeight = Screen.height / 20;
int buttonWidth = Screen.width / 5;
GUI.skin.label.fontSize = 60;
GUI.skin.button.fontSize = 60;
Rect statusRect = new Rect(10,20,Screen.width,200);
Rect dataRect = new Rect( 10, 250, Screen.width,100);
Rect b1Rect = new Rect(10, 800, buttonWidth, buttonHeight);
Rect b2Rect = new Rect(b1Rect.x + 20 + buttonWidth, b1Rect.y, buttonWidth, buttonHeight);
if(!Social.localUser.authenticated) {
if(GUI.Button(b1Rect, "Signin")) {
Social.localUser.Authenticate(mAuthCallback);
}
}
else {
if(GUI.Button(b1Rect, "Load")) {
mSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.ShowSelectSavedGameUI("Select game to load",
4,false,false,SavedGameSelected);
}
GUI.Label(dataRect, slot0.Data);
}
if(GUI.Button(b2Rect, "Save")) {
int idx = slot0.Data.IndexOf("_");
if (idx > 0) {
int val = Convert.ToInt32(slot0.Data.Substring(idx+1));
val++;
slot0.Data = "Save_" + val;
}
else {
slot0.Data = "Save_0";
}
mSaving = true;
CaptureScreenshot();
((PlayGamesPlatform)Social.Active).SavedGame.ShowSelectSavedGameUI("Save game progress",
4,true,true,SavedGameSelected);
}
GUI.Label(statusRect, slot0.State);
}
public void SavedGameSelected(SelectUIStatus status, ISavedGameMetadata game) {
if (status == SelectUIStatus.SavedGameSelected) {
string filename = game.Filename;
Debug.Log("opening saved game: " + game);
if(mSaving && (filename == null || filename.Length == 0)) {
filename = "save" + DateTime.Now.ToBinary();
}
if (mSaving) {
slot0.State = "Saving to " + filename;
}
else {
slot0.State = "Loading from " + filename;
}
//open the data.
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithAutomaticConflictResolution(filename,
DataSource.ReadCacheOrNetwork,
ConflictResolutionStrategy.UseLongestPlaytime,
SavedGameOpened);
} else {
Debug.LogWarning("Error selecting save game: " + status);
}
}
public void SavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game) {
if(status == SavedGameRequestStatus.Success) {
if( mSaving) {
slot0.State = "Opened, now writing";
byte[] pngData = (mScreenImage!=null) ?mScreenImage.EncodeToPNG():null;
Debug.Log("Saving to " + game);
byte[] data = slot0.ToBytes();
TimeSpan playedTime = slot0.TotalPlayingTime;
SavedGameMetadataUpdate.Builder builder = new
SavedGameMetadataUpdate.Builder()
.WithUpdatedPlayedTime(playedTime)
.WithUpdatedDescription("Saved Game at " + DateTime.Now);
if (pngData != null) {
Debug.Log("Save image of len " + pngData.Length);
builder = builder.WithUpdatedPngCoverImage(pngData);
}
else {
Debug.Log ("No image avail");
}
SavedGameMetadataUpdate updatedMetadata = builder.Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game,updatedMetadata,data,SavedGameWritten);
} else {
slot0.State = "Opened, reading...";
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game,SavedGameLoaded);
}
} else {
Debug.LogWarning("Error opening game: " + status);
}
}
public void SavedGameLoaded(SavedGameRequestStatus status, byte[] data) {
if (status == SavedGameRequestStatus.Success) {
Debug.Log("SaveGameLoaded, success=" + status);
slot0 = GameData.FromBytes(data);
} else {
Debug.LogWarning("Error reading game: " + status);
}
}
public void SavedGameWritten(SavedGameRequestStatus status, ISavedGameMetadata game) {
if(status == SavedGameRequestStatus.Success) {
Debug.Log ("Game " + game.Description + " written");
slot0.State = "Saved!";
} else {
Debug.LogWarning("Error saving game: " + status);
}
}
public class GameData {
private TimeSpan mPlayingTime;
private DateTime mLoadedTime;
string mData;
string mState;
static readonly string HEADER = "GDv1";
public GameData(string data) {
mData = data;
mState = "Initialized, modified";
mPlayingTime = new TimeSpan();
mLoadedTime = DateTime.Now;
}
public TimeSpan TotalPlayingTime {
get {
TimeSpan delta = DateTime.Now.Subtract(mLoadedTime);
return mPlayingTime.Add(delta);
}
}
public override string ToString () {
string s = HEADER + ":" + mData;
s += ":" + TotalPlayingTime.TotalMilliseconds;
return s;
}
public byte[] ToBytes() {
return System.Text.ASCIIEncoding.Default.GetBytes(ToString());
}
public static GameData FromBytes (byte[] bytes) {
return FromString(System.Text.ASCIIEncoding.Default.GetString(bytes));
}
public static GameData FromString (string s) {
GameData gd = new GameData("initializing from string");
string[] p = s.Split(new char[] { ':' });
if (!p[0].StartsWith(HEADER)) {
Debug.LogError("Failed to parse game data from: " + s);
return gd;
}
gd.mData = p[1];
double val = Double.Parse(p[2]);
gd.mPlayingTime = TimeSpan.FromMilliseconds(val>0f?val:0f);
gd.mLoadedTime = DateTime.Now;
gd.mState = "Loaded successfully";
return gd;
}
public string Data {
get {
return mData;
}
set {
mData = value;
mState += ", modified";
}
}
public string State {
get {
return mState;
}
set {
mState = value;
}
}
}
}
I used LibUSbDotNet for read USB data from my Hardware using Event Driven operation. My hardware pumps out data at two different intervals. (2000 ms and 300 ms). The buffer size is 7 bytes.
The code works fine for sometimes afterwards the reading is slowed. instead of 2000 and 300 ms the data receives at 4000 and 2000 ms.
Please help me resolve this issue guys...
regards
John
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LibUsbDotNet;
using LibUsbDotNet.DeviceNotify;
using LibUsbDotNet.Main;
namespace ATE_BackEnd
{
public partial class Main_Form : Form
{
public static IDeviceNotifier UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();
UsbDeviceFinder MyUsbFinder;
UsbDevice MyUsbDevice;
UsbEndpointReader EPReader;
UsbEndpointWriter EPWriter;
int bytesWritten;
public DateTime LastDataEventDate = DateTime.Now;
public Main_Form()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
UsbDeviceNotifier.OnDeviceNotify += OnDeviceNotifyEvent;
}
void OpenUSB(int VendorID, int ProductID)
{
toolStripStatusLabel.Text = "Opening USB";
MyUsbFinder = new UsbDeviceFinder(VendorID, ProductID);
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
if (MyUsbDevice == null) { USBConnection_label.Text = "USB Not Connected"; CloseUSB(); }
else
{
USBConnection_label.Text = "USB Connected";
USBInfo_label.Text = "VID = " + MyUsbDevice.Info.Descriptor.VendorID.ToString() +
", PID = " + MyUsbDevice.Info.Descriptor.ProductID.ToString();
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
wholeUsbDevice.SetConfiguration(1);
wholeUsbDevice.ClaimInterface(0);
}
EPReader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep01, 7);
EPWriter = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
EPReader.DataReceived += OnUsbDataReceived;
EPReader.DataReceivedEnabled = true;
}
}
void WriteUSB(int Site)
{
toolStripStatusLabel.Text = "Writing Data...";
ErrorCode ECWriter = EPWriter.Write(Encoding.Default.GetBytes(Site.ToString()), 100, out bytesWritten);
if (ECWriter != ErrorCode.None) throw new Exception(UsbDevice.LastErrorString);
}
void CloseUSB()
{
toolStripStatusLabel.Text = "Closing USB";
if (MyUsbDevice != null)
{
if (MyUsbDevice.IsOpen)
{
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
wholeUsbDevice.ReleaseInterface(0);
}
MyUsbDevice.Close();
}
EPReader.DataReceived -= OnUsbDataReceived;
EPReader.DataReceivedEnabled = false;
EPReader.Dispose();
EPWriter.Dispose();
}
MyUsbDevice = null;
UsbDevice.Exit();
}
void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)
{
toolStripStatusLabel.Text = "Device Notify Message: " + e.EventType.ToString();
if (e.EventType.ToString() == "DeviceRemoveComplete") { USBConnection_label.Text = "USB Disconnected"; CloseUSB(); }
else if (e.EventType.ToString() == "DeviceArrival") { USBConnection_label.Text = "USB Connected"; OpenUSB(4660, 1); }
}
void OnUsbDataReceived(object sender, EndpointDataEventArgs e)
{
toolStripStatusLabel.Text = "Receiving Data!!!";
byte[] s1stat = e.Buffer;
S1SOT_textBox.Text = s1stat[0].ToString();
S2SOT_textBox.Text = s1stat[1].ToString();
S1EOT_textBox.Text = s1stat[2].ToString();
S2EOT_textBox.Text = s1stat[3].ToString();
S1BIN_textBox.Text = s1stat[4].ToString();
S2BIN_textBox.Text = s1stat[5].ToString();
TowerLamp_textBox.Text = s1stat[6].ToString();
Time_label.Text = (DateTime.Now - LastDataEventDate).TotalMilliseconds.ToString();
LastDataEventDate = DateTime.Now;
}
private void Main_Form_FormClosing(object sender, FormClosingEventArgs e)
{
toolStripStatusLabel.Text = "Closing App";
CloseUSB();
}
private void Main_Form_Load(object sender, EventArgs e)
{
toolStripStatusLabel.Text = "Opening App";
OpenUSB(4660, 1);
}
private void Write_button_Click(object sender, EventArgs e)
{
CloseUSB();
OpenUSB(4660, 1);
WriteUSB(Write_comboBox.SelectedIndex+1);
}
}
}