Better way than playerprefs? [duplicate] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I was wondering... What's the best way to save data in Unity games. JSONs? If so, how? Thanks

Here are some of the different Ways and Methods to Save data for Unity Projects:
Platform-Independent: One way of saving data in Unity3D in a Platform-independent way is to use the PlayerPrefs class. PlayerPrefs is a static class and it is very easy to use but not reliable.
PERSISTENCE - SAVING AND LOADING DATA using DontDestroyOnLoad, PlayerPrefs, and data serialization Video Tutorial by unity.
Server Side: You can also use a Server for saving data (like a combination of PHP and MySQL Database). You can use it to save Score Data, user profiles, inventory, etc., Learn More From Unity Wiki. You can also use third-party solutions like firebase etc.
For saving the in-game data to a Hard drive in a format that can be understood and loaded later on, use a .NET/Mono feature known as Serialization. Learn More
Simple JSON guide about Unity is available at Unity Wiki or officially you can see JSON serialization
SQLite (an embedded database for your app) is another great option for you to get the Free Package, it is simple and easy (and my favorite) if you know SQL.
Scriptable Object: it's a data container. Useful for unchanging data. Suitable for large unchanging data and amazingly reduce your project's memory.
The above is taken from my blog post on Data Saving Techniques for Unity3d Applications.

You can use many assets that are available for free and paid in asset store.
Save Game Free - XML and JSON saving and loading.
Syntax:
Saver.Save<T> (T data, string fileName);
Example:
Saver.Save<MyData> (myData, "myData"); // The .json extension will be added automatically
Save Game Pro - Binary saving and loading. fast and secure. Easy to use.
Syntax:
SaveGame.Save<T> (T data, string identifier);
Example:
SaveGame.Save<int> (score, "score");

If you want to store your data in server there is a simple way with PHP and MySQL. What you have to do is:
STEP 1:
Get what ever data you want from your server just in single string (code is below):
<?php
//SERVER CONNECTION
$server_name = "localhost";
$server_user = "Er.Ellison";
$server_pass = "supersecretPassword";
$server_db = "game_test_db";
$connection = new mysqli($server_name , $server_user , $server_pass , $server_db);
if(!$connection) {
die("Connection failed !" . mysqli_connect_error());
}
// QUERY
$query = "SELECT * FROM items";
$result = mysqli_query($connection , $query);
if(mysqli_num_rows($result) > 0){
while($row = mysqli_fetch_array($result)){
echo "id:" . $row['id'] . "|username:" . $row['username'] . "|type:" . $row['type'] . "|score:" . $row['score'] . ";";
}
}
?>
And note that you MUST SEPARATE ANY string you want with a ; or any thing that you are comfortable with that and remember that we going to use it in C# in Unity.
STEP 2:
Now you should get the data from your web like this (it will be a long string):
STEP 3:
Now go to the Unity and create a C# script and attached that to what ever object in your scene and open the script up, then use this kind of code to manipulate the data that you retrieved from your database:
public class DataLoader : MonoBehaviour {
public string[] items;
// Use this for initialization
IEnumerator Start () {
WWW itemsData = new WWW ("http://localhost/_game/test/itemsdata.php");
yield return itemsData;
string itemsDataStrign = itemsData.text;
print (itemsDataStrign);
items = itemsDataStrign.Split (';');
print (GetDataValue(items[0] , "cost:"));
}
string GetDataValue(string data, string index) {
string value = data.Substring (data.IndexOf(index) + index.Length);
if (value.Contains ("|")) {
value = value.Remove (value.IndexOf("|"));
}
return value;
}
}
STEP 4:
You just NOW retrieved data from database, check the image from unity console:
I made this for who that may be, like me, stuck in database problems!

Related

TensorflowSharp - TFException: Attempting to use uninitialized value

I'm attempting to import a model created in Keras/Tensorflow and use it for inference in a Unity project.
I have successfully imported the model and validated by printing names of input and output nodes in the graph. Though, when I try to get the output value from the runner, I get this exception.
TFException: Attempting to use uninitialized value action_W
[[Node: action_W/read = IdentityT=DT_FLOAT, _class=["loc:#action_W"], _device="/job:localhost/replica:0/task:0/cpu:0"]]
TensorFlow.TFStatus.CheckMaybeRaise (TensorFlow.TFStatus incomingStatus, System.Boolean last) (at <6ed6db22f8874deba74ffe3e566039be>:0)
TensorFlow.TFSession.Run (TensorFlow.TFOutput[] inputs, TensorFlow.TFTensor[] inputValues, TensorFlow.TFOutput[] outputs, TensorFlow.TFOperation[] targetOpers, TensorFlow.TFBuffer runMetadata, TensorFlow.TFBuffer runOptions, TensorFlow.TFStatus status) (at <6ed6db22f8874deba74ffe3e566039be>:0)
TensorFlow.TFSession+Runner.Run (TensorFlow.TFStatus status) (at <6ed6db22f8874deba74ffe3e566039be>:0)
RecordArbitraryData.ModelPredict (System.Single[,] input) (at Assets/Scripts/Spells/RecordArbitraryData.cs:230)
RecordArbitraryData.FixedUpdate () (at Assets/Scripts/Spells/RecordArbitraryData.cs:95)
Here are the two functions I use. InstantiateModel is called OnStart() in my unity script. And ModelPredict is called when the user passes an input to the script.
void InstantiateModel(){
string model_name = "simple_as_binary";
//Instantiate Graph
graphModel = Resources.Load (model_name) as TextAsset;
graph = new TFGraph ();
graph.Import (graphModel.bytes);
session = new TFSession (graph);
}
void ModelPredict(float[,] input){
using (graph) {
using (session) {
//Assign input tensors
var runner = session.GetRunner ();
runner.AddInput (graph [input_node_name] [0], input);
//Calculate and access output of graph
runner.Fetch (graph[output_node_name][0]);
Debug.Log ("Output node name: " + graph [output_node_name].Name);
float[,] recurrent_tensor = runner.Run () [0].GetValue () as float[,];
//var results = runner.Run();
//Debug.Log("Prediciton: " + results);
}
}
}
Any help appreciated - TensorflowSharp is very new to me.
I was able to figure out most of my problems. I'm currently at a point where my model is predicting in unity, but only predicting the first of four classes. My guess is it has something to do with the weights not getting initialized correctly from the checkpoint files? Edit: My values weren't being normalized before being passed to neural network.
Preface: Mozilla Firefox works best for displaying tensorboard; it took me a long time to realize that google chrome was causing my graph to be invisible (tensorboard is how I was able to figure out the nodes that needed to be used for input and output).
First Issue: I was renaming a .pb file into a .bytes file. This is incorrect because the model’s weights come from the checkpoint file, and are given to the nodes held in the .pb file. This was causing the uninitialized variables. These variables were used for training, which were removed after using the freeze_graph function.
Second Issue: I was using the file created called ‘checkpoint’, which was throwing an error. I then changed the name of the checkpoint to ‘test’ and used this in the freeze_graph function. When calling the checkpoints file, I was required to use ‘test.ckpt’. I assume this function knows to grab the three files automatically based on the .ckpt? ‘Test’ without ‘.ckpt’ did not work.
Third Issue: when using the freeze_graph function, I needed to export the .pb file in keras/tf with text=False. I tested True and False; True threw an error about “bad wiring”.
Fourth Issue: Tensorboard was very difficult to use without any organization. Using tf.name_scope helped a lot with not only visualization, but making sure I was using/referencing the correct nodes in TensorFlowSharp. In keras I found it helpful to separate the final Dense layer and Activation into their own scopes so I could find the correct output node. The rest of my network was put into a ‘body’ scope, and the sole input layer in ‘input’ scope. The name_scope function prepends ‘scopename/’ to the node name. I don't think it’s necessary, but it helped me.
Fifth Issue: The version of tensorflowsharp released as a unity package is not up to date. This caused an issue with a keras placeholder for ‘keras_training_phase’. In keras, you pass this along with an input like [0] + input. I tried to do the same by creating a new TFTensor(bool), but I was getting an error ‘inaccessible due to its protection level. This was an error with the implicit conversion between bool and TFTensor in my unity TensorFlowSharp version. To fix this I had to use a function found in this stackoverflow solution where the .bytes file is read in, the placeholder for keras_training_phase is found, and is swapped out for a bool constant set to false. This worked for me because my model was pretrained in python, so it may not be a great fix for someone that’s trying to train and test the model. A condition for removing this node with the freeze_graph function would really be useful.
Hope someone finds this useful!

Update C# code through website or database

I've searched through the web and seen a lot of talk about a WWW method of retrieving content from a web server or a database and using values but I would like a method where I don't have to continuously update my code in monodevelop and then build the projects as big projects sometimes take up to an hour to build so basically patching over a server.
So can the WWW method be used to do this? Like for instance lets say I have a code like this
int level;
int currentLevel;
if(level != currentLevel){
level = currentLevel;
}
Now this code is having complications because the level is not always up to date and I have to change methods into something like this so tht the level stays updated
int level;
int currentLevel;
private void Update(){
if(level != currentLevel){
level = currentLevel;
}
}
Now instead of rebuilding my entire project I would like to put this in maybe a database or some sort and then when the game launches it checks the database to make sure the code matches the code on the database if the code matches then it starts the game if not it updates
FYI I am building for WebGL HTML5
You can't do that. What you can do is to make make a decision based on what you receive from WWW but the action to do must exist already before it can used. You can't create a new action during run-time.
For example, make decision if ad should be displayed in your app.
WWW www = new WWW("url");
yield return www;
if(www.text=="AdEnabled"){
displayAd();
}
You can also run JavaScript code from Unity but that's not helpful to your question. You can't do more than that.

Reading in a complex text file to input into database

I am working on a program that will read in a text file and then insert areas of the text file into different columns on a database. The text file is generally set up like this:
"Intro information"
"more Intro information"
srvrmgr> "information about system"
srbrmgr> list parameters for component *ADMBatchProc*
"Headers"
*Name of record* *alias of record* *value of record*
The columns create a table containing all of the setting information for this component. One all of the settings are listed, the file moves to another component and returns all the information for that component in a new table. I need to read in the component and the information on the tables without the headers or the other information. I will then need to be able to transfer that data into a database. The columns are fixed width on each table within the file.
Any recommendations about how to approach this are welcome. I have never read in a file this complex so I dont really know how to approach ignoring alot of information while trying to get other information ready for a database. Also the component value I am trying to gather always follows the word component on a line that starts with "srvrmgr".
The '*' represents areas that will be put into datbase.
Siebel Enterprise Applications Siebel Server Manager, Version 8.1.1.11 [23030] LANG_INDEPENDENT
Copyright (c) 1994-2012, Oracle. All rights reserved.
The Programs (which include both the software and documentation) contain
proprietary information; they are provided under a license agreement containing
restrictions on use and disclosure and are also protected by copyright, patent,
and other intellectual and industrial property laws. Reverse engineering,
disassembly, or decompilation of the Programs, except to the extent required to
obtain interoperability with other independently created software or as specified
by law, is prohibited.
Oracle, JD Edwards, PeopleSoft, and Siebel are registered trademarks of
Oracle Corporation and/or its affiliates. Other names may be trademarks
of their respective owners.
If you have received this software in error, please notify Oracle Corporation
immediately at 1.800.ORACLE1.
Type "help" for list of commands, "help <topic>" for detailed help
Connected to 1 server(s) out of a total of 1 server(s) in the enterprise
srvrmgr> configure list parameters show PA_NAME,PA_ALIAS,PA_VALUE
srvrmgr>
srvrmgr> list parameters for component ADMBatchProc
PA_NAME PA_ALIAS PA_VALUE
---------------------------------------------------------------------- ------------------------------------- --------------------------------------------------------------------------------------------------------------------
ADM Data Type Name ADMDataType
ADM EAI Method Name ADMEAIMethod Upsert
ADM Deployment Filter ADMFilter
213 rows returned.
srvrmgr> list parameters for component ADMObjMgr_enu
PA_NAME PA_ALIAS PA_VALUE
---------------------------------------------------------------------- ------------------------------------- --------------------------------------------------------------------------------------------------------------------
AccessibleEnhanced AccessibleEnhanced False
This is the beginning of the text file. It a produced in a system called Siebel to show all of the settings for this environment. I need to pull the component name (there are multiple on the actual file but the ones shown here are 'ADMBatchProc' and 'ADMObjMgr_enu'), and then the data shown on the table below it that was created by Siebel. The rest of the information is irrelevant for the purpose of the task I need.
I would recommend using Test-Driven Development techniques in this case. I'm guessing that your possible variations of input format are near infinite.
Try this:
1) Create an interface that will represent the data operations or parsing logic you expect the application to perform. For example:
public interface IParserBehaviors {
void StartNextComponent();
void SetTableName(string tableName);
void DefineColumns(IEnumerable<string> columnNames);
void LoadNewDataRow(IEnumerable<object> rowValues);
DataTable ProduceTableForCurrentComponent();
// etc.
}
2) Gather as many small examples of discrete inputs that have well-defined behaviors as possible.
3) Inject a behaviors handler into your parser. For example:
public class Parser {
private const string COMPONENT_MARKER = "srvrmgr";
private readonly IParserBehaviors _behaviors;
public Parser(IParserBehaviors behaviors) {
_behaviors = behaviors;
}
public void ReadFile(string filename) {
// bla bla
foreach (string line in linesOfFile) {
// maintain some state
if (line.StartsWith(COMPONENT_MARKER)) {
DataTable table = _behaviors.ProduceTableForCurrentComponent();
// save table to the database
_behaviors.StartNextComponent();
}
else if (/* condition */) {
// parse some text
_behaviors.LoadNewDataRow(values);
}
}
}
}
4) Create tests around the expected behaviors, using your preferred mocking framework. For example:
public void FileWithTwoComponents_StartsTwoNewComponents() {
string filename = "twocomponents.log";
Mock<IParserBehaviors> mockBehaviors = new Mock<IParserBehaviors>();
Parser parser = new Parser(mockBehaviors.Object);
parser.ReadFile(filename);
mockBehaviors.Verify(mock => mock.StartNextComponent(), Times.Exactly(2));
}
This way, you will be able to integrate under controlled tests. When (not if) someone runs into a problem, you can distill what case wasn't covered, and add a test surrounding that behavior, after extracting the case from the log being used. Separating concerns this way also allows your parsing logic to be independent from your data operation logic. The needs of parsing specific behaviors seems to be central to your application, so it seems like a perfect fit for creating some domain-specific interfaces.
You'll want to read the text file using StreamReader:
using (FileStream fileStream = File.OpenRead(path))
{
byte[] data = new byte[fileStream.Length];
for (int index = 0; index < fileStream.Length; index++)
{
data[index] = (byte)fileStream.ReadByte();
}
Console.WriteLine(Encoding.UTF8.GetString(data)); // Displays: your file - now you can decide how to manipulate it.
}
Perhaps then you'll use Regex to capture the date you'd like to insert:
You might insert into the db like this:
using (TransactionScope transactionScope = new TransactionScope())
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command1 = new SqlCommand(
“INSERT INTO People ([FirstName], [LastName], [MiddleInitial])
VALUES(‘John’, ‘Doe’, null)”,
connection);
SqlCommand command2 = new SqlCommand(
“INSERT INTO People ([FirstName], [LastName], [MiddleInitial])
VALUES(‘Jane’, ‘Doe’, null)”,
connection);
command1.ExecuteNonQuery();
command2.ExecuteNonQuery();
}
transactionScope.Complete();
}
Examples adapted from Wouter de Kort's C# 70-483.

WPF datagrid binding with remote/online mysql in c# [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Hello i am trying to connect my datagrid in WPF with c#, my database is mysql in remote server and it is in shared hosting account the ip of shared box server is like xx.xxx.xxx.xxx and my account is like yyyyyyyw so the direct ip is http://xx.xxx.xxx.xxx/~yyyyyyyw/ how can i connect and get the data from my database?
I am working in VS10 with DevExpress Tools if anyone is familiar with this it would be more useful.
There are several possibilities to achieve your goal - given you have sufficient access to the specified server. You could - for example - set up the MySQL database that your user can access the DB directly via ADO.Net (with MySQL Connector/Net, https://dev.mysql.com/downloads/connector/net/).
If this is not possible, you could write some sort of PHP-Script, which runs server-side and gets the desired data from your DB, stores it in some kind of schema (XML, JSON, Base64 encoded binary data - whatever you'd like) and returns it. You'd just have to make sure that you protect the channel appropriately, for example with password protection (but no plain text, of course - the password should definitively be encrypted and best of with some sort of handshake, that one can't simply copy your request and get the data - or you could use HTTPS). Then you can just call
http://xx.xxx.xxx.xxx/~yyyyyyyw/getdata.php?id=1 from your application and it returns something like
<root>
<dataset id='1'>
<timestamp>
2013-12-05T11:52:00
</timestamp>
<text>
This is a sample dataset!
</text>
</dataset>
</root>
This could for example be a PHP-script like the following (please note, that this is a very basic example completely disregarding security concerns)
<?php
$id = $_GET['id'];
$mysql = mysql_connect('localhost', 'root', '12345');
mysql_select_db('yourdatabase', $mysql);
$query = "SELECT id,timestamp,text FROM dataset WHERE id=$id";
$result = mysql_query($query, $mysql);
echo "<root>\r\n";
while($row = mysql_fetch_row($result))
{
$rowid = $row[0];
$rowtimestamp = $row[1];
$rowtext = $row[2];
echo "<dataset id='$rowid'>\r\n";
echo " <timestamp>\r\n";
echo " $rowtimestamp\r\n";
echo " </timestamp>\r\n";
echo " <text>\r\n";
echo " $rowtext\r\n";
echo " </text>\r\n";
echo "</dataset>\r\n";
}
echo "</root>";
?>
By adjusting the URL-Request and the SQL-Query to your needs, you can cover more complex cases, like calling the URL like http://xx.xxx.xxx.xxx/~yyyyyyyw/getdata.php?from=2013-01-01T00:00:00&to=2013-12-31T23:59:59 and adjusting the script to
$from = $_GET["from"];
$to = $_GET["to"];
...
$query = "SELECT id,timestamp,text FROM dataset WHERE timestamp>='$from' AND timestamp<='$to'";
This would for example give you all datasets written within the year 2013.
From you application you can parse this XML (please see How does one parse XML files? or Parse XML document in C#) to objects (e.g. of class MyDataSet), store them in an
IList<MyDataSet>
and let this be returned by a property of an object, for example your main window (Warning: No good practice)
class MainWindow : Window
{
IList<MyDataSet> _dataSets;
public IList<MyDataSet> DataSets
{
get {
return dataSets;
}
}
}
and then set the ItemSource property of the DataGrid to the list. With the AutoGenerateColumns property of the DataGrid a column for each publicly accessible Property of MyDataSet is generated, if you don't like this and want to have the full control over the contents of the grid, it's possibly by defining the rows in the DataGrid.Columns node and bind them to the appropriate Property (the property Content in this case)
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Content}"></DataGridTextColumn>
</DataGrid.Columns>
This should do as a start.

Import Microsoft Access Database in Mysql database

I have a particular situation where my client require to import (periodically) an ms-access database into his mysql website database (so it's a remote database).
Because the hosting plan is a shared hosting (not a vps), the only way to do it is through PHP through an SQL query, because I don't have ODBC support on hosting.
My current idea is this one (obviusly the client has a MS-Windows O.S.):
Create a small C# application that convert MS-Access database into a big SQL query written on a file
The application will then use FTP info to send the file into a specified directory on the website
A PHP script will then run periodically (like every 30 minutes) and check if file exists, eventually importing it into the database
I know it's not the best approach so I'm proposing a question to create a different workaround for this problem. The client already said that he wants keep using his ms-access database.
The biggest problem I have is that scripts can last only 30 seconds, which is obviusly a problem to import data.
To work around the 30-second limit, call your script repeatedly, and keep track of your progress. Here's one rough idea:
if(!file_exists('upload.sql')) exit();
$max = 2000; // the maximum number you want to execute.
if(file_exists('progress.txt')) {
$progress = file_get_contents('progress.txt');
} else {
$progress = 0;
}
// load the file into an array, expecting one query per line
$file = file('upload.sql');
foreach($file as $current => $query) {
if($current < $progress) continue; // skip the ones we've done
if($current - $progress >= $max) break; // stop before we hit the max
mysql_query($query);
}
// did we finish the file?
if($current == count($file) - 1) {
unlink('progress.txt');
unlink('upload.sql');
} else {
file_put_contents('progress.txt', $current);
}

Categories

Resources