Building a Unity front-end app that communicates with a PHP/MySQL back-end. Right now I am working on the register and login portions of it. In the Unity editor, all works perfectly, on the browser front end registration is working fine as well. But as soon as I take the working build in Unity and build it to test on my Google Pixel phone, registration and login both fail on my phone. The error message I am getting on Login is "Error parsing response from server, please try again!" which is in my UILogin.cs. Yet there is nothing else attached. I tried following the Unity documentation for debugging, adb, and DDMS to get access to find out what is happening but I have failed on all those ventures. Is there something particularly different about Android and WWW objects or web communications? Here is a portion of my UILogin.cs and also will include the Login.php.
UILogin.cs
IEnumerator AttemptLogin(bool quickLogin)
{
CreateLoadingScreen();
DeactivateForm();
WWWForm form = new WWWForm();
form.AddField("email", Email.text);
form.AddField("password", Password.text);
WWW www = new WWW(URL.GetLoginURL, form);
yield return www;
DestroyLoadingScreen();
ActivateForm();
ParseResult(www.text, quickLogin);
}
void ParseResult(string result, bool quickLogin)
{
byte resultCode;
if (!byte.TryParse(result, out resultCode))
Result.text = "Error parsing response from server, please try again!";
else if (resultCode == 0)
{
if (RememberToggle.isOn && !quickLogin) // Remember me
{
PlayerPrefs.SetInt("remember", 1);
PlayerPrefs.SetString("email", Email.text);
PlayerPrefs.SetString("password", Password.text);
}
else if (!quickLogin)
{
TemporaryAccount.Email = Email.text;
TemporaryAccount.Password = Password.text;
}
SceneManager.LoadScene(3);
}
else // Failure
{
if (quickLogin)
ShowForm();
Result.text = WebError.GetLoginError(resultCode);
}
}
Login.php
<?php
require "conn.php";
$stmt = $pdo->prepare("SELECT * FROM account WHERE email=:email");
$stmt->bindParam(":email", $_POST['email']);
$stmt->execute();
$count = $stmt->rowCount(); // gets count of records found
if($count > 0) {
$result = $stmt->fetch(); // gets resultset
if(!password_verify($_POST['password'], $result[4]))
echo "2";
else
echo "0";
}
else {
echo "1";
}
?>
Any ideas?
Update #1
I printed www.text and www.error after the yield return www; Text is null and error says: Unknown Error.
Update #2
Interestingly enough, I get Unknown Error from this as well:
Clickme.cs
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class Clickme : MonoBehaviour
{
public Text Result;
public void OnClick()
{
StartCoroutine(RunScript());
}
IEnumerator RunScript()
{
WWW www = new WWW("http://www.familypolaris.com/helloWorld.php");
yield return www;
if (www.text == "")
Result.text = "Result was empty, error: " + www.error;
}
}
HelloWorld.php
<?php
echo "Hello World!";
?>
I figured it out, so I will post the answer here. After somebody commented that they tried my code and it worked just fine, I decided to try another device here. That device also failed to register and login. This told me something was wrong with my build settings. My first idea was to switch build type from Gradle to Internal, and that solved the problem for both my devices immediately.
Related
I'm able to load audio using UnityWebRequestMultimedia.GetAudioClip in the Unity Editor with the following code but when I run it on Android I am unable to load any files from the user's device.
void Start() {
audio = GetComponent<AudioSource>();
string fullPath = Path.Combine("file://" + previewSong);
StartCoroutine(GetAudioClip(fullPath));
}
IEnumerator GetAudioClip(string fullPath)
{
using (var uwr = UnityWebRequestMultimedia.GetAudioClip(fullPath, AudioType.MPEG))
{
((DownloadHandlerAudioClip)uwr.downloadHandler).streamAudio = true;
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
{
debugSongPath2.text = uwr.error;
yield break;
}
DownloadHandlerAudioClip dlHandler = (DownloadHandlerAudioClip)uwr.downloadHandler;
if (dlHandler.isDone)
{
audio.clip = dlHandler.audioClip;
if (audio.clip != null)
{
audio.clip = DownloadHandlerAudioClip.GetContent(uwr);
Debug.Log("Playing song using Audio Source!");
}
else
{
Debug.Log("Couldn't find a valid AudioClip.");
}
}
else
{
Debug.Log("The download process is not completely finished.");
}
}
}
The errors I experience vary depending on how I form the start of the URL.
Path.Combine("file:/" + previewSong);
malformed URL
Path.Combine("file://" + previewSong);
http:/1.1 404 not found
Path.Combine("file:///" + previewSong);
unknown error
Path.Combine("file:////" + previewSong);
unknown error
When I output the URLs on my phone they look correct. Here's an example path:
file:///storage/emulated/0/Music/Deorro/Deorro - Five Hours.mp3
I was previously loading audio from this URL successfully with WWW.GetAudioClip but that's obsolete. This leads me to believe the URL is correct. I've tried building with and without Development Mode. Not sure what else to try. I'd like to get this working with UnityWebRequestMultimedia but if there is an alternative, more effective way of loading local files I'm open to it.
Change your build settings to give write access to external sd card. I am using below code to get audio from specified location in android. I tried your code but somehow its not working.
IEnumerator GetAudioClip2(string fullPath)
{
debugSongPath2.text = previewSong;
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(fullPath, AudioType.MPEG))
{
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
AudioClip myClip = DownloadHandlerAudioClip.GetContent(www);
audioSource.clip = myClip;
audioSource.Play();
}
}
}
My full path was "file:///storage/emulated/0/Samsung/Music/Over the Horizon.mp3"
The issue was with the new Android 11 scoped storage which disables READ_EXTERNAL_STORAGE. I had to add the following to my AndroidManifest.xml:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage
This question already has answers here:
How to connect to database from Unity
(3 answers)
Closed 5 years ago.
I'm looking around for the easiest solution of how to connect to mysql database and for example, retrieve and update data. I've tried doing my research, but I couldn't find anything really. I mean, I would bet there's a simple way. I've worked with PHP before and I would think that its relatively easy to connect to database using C#.
Can anybody please show me a sample code of how to connect to mysql database? Also, how to retrieve and update data? Please and thank you!
I don't know what you mean by easy, but I've used www form.
Followed this tutorial series from youtube to begin.
In short; you will create www forms and send required data to php code. With the answer from php code you can do your tasks. I will try to provide an example.
Unity C# Login Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoginScript : MonoBehaviour {
public GameObject inputUsernameText;
public GameObject inputPasswordText;
public string inputUsername;
public string inputPassword;
public string userUsername;
public string userPassword;
public string[] userDataArray;
string loginURL ="YOUR LOGIN PHP CODE URL HERE" ;
public bool isLoginButtonPressed;
void Awake() {
DontDestroyOnLoad(transform.gameObject);
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (isLoginButtonPressed)
{
StartCoroutine(loginToDB (inputUsername, inputPassword));
isLoginButtonPressed = false;
}
}
IEnumerator loginToDB(string username, string password)
{
WWWForm form = new WWWForm();
form.AddField("usernamePost", username);
form.AddField("passwordPost", password);
WWW www = new WWW (loginURL, form);
yield return www;
//Debug.Log (www.text);
userDataArray = userEkipIDString.Split ('|');
userUsername = userDataArray [0];
userPassword = userDataArray [1];
isLoginButtonPressed = false;
SceneManager.LoadScene("MainMenuScene", LoadSceneMode.Single);
}
public void loginButtonPressedFunc()
{
inputUsername = inputUsernameText.GetComponent<Text> ().text.ToString ();
inputPassword = inputPasswordText.GetComponent<Text> ().text.ToString ();
isLoginButtonPressed = true;
}
}
What this script does is, it get a username and password from Unity's input field and send it to php code. If username and password is correct it loads another scene.
PHP Code
<?php
$servername = "YOUR HOST NAME ex:localhost";
$username = "YOUR DB USER NAME";
$password = "YOUR DB PASSWORD";
$dbName = "YOUR DB NAME";
$user_username = $_POST["usernamePost"];
$user_password = $_POST["passwordPost"];
//Make Connection
$conn = mysqli_connect($servername,$username,$password,$dbName);
//Check Connection
if(!$conn)
{
die("Connection Failed. " . mysqli_connect_error());
}
//else echo ("Connection Success.");
$sql ="Select user, pass from "YOUR TABLE NAME" where user = '".$user_username."' "; //You can write your own query here
$result = mysqli_query($conn,$sql);
//Get the result and confirm login
if(mysqli_num_rows($result)>0)
{
//show data for each row
while($row = mysqli_fetch_assoc($result))
{
if($row['pass'] == $user_password)
{
//echo "Login Success";
echo "".$row['user']."|".$row['pass']."" ;
}
else
{
echo "Wrong Password";
}
}
}
else
{
echo "User not found";
}
?>
You can adjust this logic to insert, update and delete
Hope this helps. Cheers!
I am trying to get data from my MySQL server to my Unity project. I tried to get the data like so:
public string awsurl = "ec2-174-129-82-141.compute-1.amazonaws.com/connect_to_server.php";
IEnumerator GetScores()
{
print("get scores start");
WWW aws_get = new WWW(awsurl);
yield return aws_get;
print("getscore here");
if (aws_get.error != null)
{
print("There was an error getting aws: " + aws_get.error);
}
else
{
print(aws_get.text); // this is a GUIText that will display the scores in game.
}
}
I have a php script on my server to handle the interaction because I am having trouble using the MySqlConnection library for my unity project.
Here is my php script:
$address = "localhost"
$dbusername = "root";
$dbpassword = "root";
$db_name = "watshoes";
$db_conn = new mysqli($address, $dbusername, $dbpassword, $db_name);
if(isset($_POST['username'])) $username = $_POST['username'];
if(isset($_POST['user_id'])) $user_id = $_POST['user_id'];
if(isset($password)) $password =$_POST['password'];
$stmt = $db_conn->prepare("SELECT image FROM ImageText");
// "s" means the database expects a string
$stmt->bind_param("s", $user_id);
if($stmt->execute())
{
/* bind result variables */
$stmt->bind_result($image);
/* fetch value */
$stmt->fetch();
echo $image;
}
else
{
echo "query failed";
}
$stmt->close();
$db_conn->close();
But every time I run the code I get this error:There was an error getting aws: Failed to connect to ec2-174-129-82-141.compute-1.amazonaws.com port 80: Timed out
Thanks for looking at the code and please let me know if there is anything else I can do to help.
You have to add a rule to open the port 80 using security groups (Inbound tab)
How your rule should look:
By default the port 80 is close in EC2 AWS instances.
And the URL is malformed in Unity
Add http:// to your server URL
In editor will work ok without http:// but it will fail in android.
So my project as of now is almost working:
It connects to facebook
It takes the Facebook ID and sends it to a script/iterator to handle connection
That script then sends off a concatenated string to a php url, which correctly checks my dataTable for an entry, and if not creates an entry
After that the php code echo's a text reply: OldUser/NewUserCreated/NewUserFailed
And here's where my problem starts:
the aim is to get the text from the echo, then check that string, if it works then unity moves on to the next scene and goes on, however when checking the string it fails for some reason, before I explain further here's my iterator that handles the connection:
IEnumerator Connect()
{
//call databasequeries and get sDBConnect
string sConnectPhp = GameObject.FindGameObjectWithTag("DBConnector").GetComponent<DatabaseQueries>().sDBConnect;
//now ready the url with the necessary code for php's get, and the FacebookID
string url = sConnectPhp + "?UserID=" + sFacebookID;
WWW wwwGet = new WWW(url);
yield return wwwGet;
string sTemp = wwwGet.text.ToString();
if(wwwGet.error == null)
{
print (sTemp);
if(sTemp == "OldUser")
{
//if successfully connected set to true
print ("connectToDatabase: successful");
bDatabaseConnected = true;
}
else if(sTemp == "NewUserCreated")
{
//if successfully connected set to true
print ("connectToDatabase: successful");
bDatabaseConnected = true;
}
else if(sTemp == "NewUserFailed")
{
//game connection has failed
print ("connectToDatabase: failed");
bDatabaseConnected = false;
bConnectionFailed = true;
}
}
else
{
//game connection has failed
print ("connectToDatabase: failed");
bDatabaseConnected = false;
bConnectionFailed = true;
}
}
Now my problem is that sTemp is printing in the unity console: OldUser, and it's not matching my if else condition? I have tried copying wwwGet.text without ToString but that doesn't work either - printing shows OldUser, but it doesn't match the condition
My only guess is that I haven't used ToString correctly, but my searches have shown it being used for Decimal and currency conversion, and as said without toString sTemp is not matching, any ideas as to why it's not matching?
Firstly I must point out that I am very new to C#.
I am developing an application using Unity3D, and part of the application requires that I parse a JSON file stored on my server.
The problem that I am having is that sometimes everything works perfectly, and other times the app hangs on the downloading the JSON. I don't receive any errors, the script just never reaches 100% on the progress.
Here is my code:
public IEnumerator DownloadJSONFile(string url)
{
Debug.Log("JSON URL: "+ url);
mJsonInfo = new WWW(url);
yield return mJsonInfo;
mIsJSONRequested = true;
}
private void LoadJSONData(string jsonUrl)
{
Debug.LogWarning("LoadJSONData, url= "+jsonUrl);
if(!mIsJSONRequested){
StartCoroutine(DownloadJSONFile(jsonUrl));
} else {
if(mJsonInfo.progress >= 1)
{
if(mJsonInfo.error == null )
{
//** PARSE THE JSON HERE **//
}else
{
Debug.LogError("Error downloading JSON");
mIsLoadingData = false;
}
} else {
Debug.LogWarning("!! ### JSON DOWNLOADING: "+mJsonInfo.progress+"%");
if(mJsonInfo.error != null )
{
Debug.LogError("Error downloading JSON");
Debug.LogError("JSON Error:"+mJsonInfo.error);
mIsLoadingData = false;
}
}
}
}
Like I said, 50% of the time the JSON data gets loaded nearly instantly, and 50% of the time the progress never reaches 1. I never receive an error in form the mJsonInfo.error variable.
Any suggestions as to what I am doing wrong would be greatly appreciated!
You need to wait until the download is complete.
As stated in the documentation you need to:
var www = new WWW(...);
yield return www;
So you need to modify the return type of your method from void to IEnumerator.
private IEnumerator LoadJSONData(string jsonUrl)
{
Debug.LogWarning("LoadJSONData, url= "+jsonUrl);
if(!mIsJSONRequested)
{
// Gets the json book info from the url
mJsonInfo = new WWW(jsonUrl);
yield return mJsonInfo; //Wait for download to complete
mIsJSONRequested = true;
}
else
{
...
}
}
isDone is that you need,
WWW lWWW = new WWW(...)
if(lWWW.isDone)
then parse it
I found the problem, I thought I would post my solution for anyone else experiencing the same problem.
The solution in the end was the JSON file on the server. I was using PHP (CakePHP) to generate the JSON, when opening the PHP generated file via the browser the response time was instant, but from my mobile app for some reason it would hang. So I changed my server side code to actually create and updated an actual JSON file, and now everything works fine.