使用 PHP 和 MySQL 的 Unity 登录系统
在本教程中,我将展示如何使用 PHP 和 MySQL 在 Unity 中创建登录系统。
本教程需要一台带有 cPanel 以及 PHP 和 MySQLi(MySQL 的改进版本)的服务器。
请随意检查经济实惠的优质 VPS 托管或更便宜的 共享托管 替代方案。
第 1 步:设置 MySQL 数据库
- 登录 cPanel
- 单击“数据库”部分中的“MySQL 数据库”
- 在 "Create New Database" 部分下输入数据库的名称,然后单击 "Create Database"
创建数据库后,我们需要创建一个与其关联的用户:
- 在 "MySQL Users" 部分下输入用户名,然后输入密码(或者最好使用密码生成器生成强密码)。不要忘记将密码保存在某处,稍后会需要它。
最后,我们需要为数据库分配一个具有特定权限集的用户。
- 在 "Add User To Database" 部分下选择新创建的用户和数据库,然后单击 "Add"
单击 "Add" 后,您将看到权限列表。仅选择您打算将来使用的权限。最常见的是 DELETE、SELECT、INSERT 和 UPDATE:
- 单击 "Make Changes" 完成
第2步:创建MySQL表
MySQL表将存储用户提供的值,例如用户名、电子邮件、密码等。
- 单击数据库部分下的 "phpMyAdmin"
- 单击新创建的数据库,然后单击 SQL 选项卡
- 将以下代码粘贴到查询编辑器中,然后单击 "Go"
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
--
-- Table structure for table `sc_users`
--
CREATE TABLE `sc_users` (
`user_id` int(11) NOT NULL,
`username` varchar(20) CHARACTER SET utf8 NOT NULL,
`email` varchar(254) CHARACTER SET utf8 NOT NULL,
`password` char(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`registration_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Indexes for table `sc_users`
--
ALTER TABLE `sc_users`
ADD PRIMARY KEY (`user_id`),
ADD UNIQUE KEY `username` (`username`),
ADD UNIQUE KEY `email` (`email`);
--
-- AUTO_INCREMENT for table `sc_users`
--
ALTER TABLE `sc_users`
MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
COMMIT;
上面的查询将创建一个新表 'sc_users' 来存储用户数据。
第 3 步:编写服务器端逻辑
服务器端逻辑将由 PHP 脚本组成,这些脚本将接收并处理来自 Unity 的 Post 数据。
第一个文件是database.php,它将使用PHP MySQLi 扩展连接到MySQL 数据库。
数据库.php
<?php
$host = "localhost"; // Host name
$db_username = "DATABASE_USER"; // Mysql username
$db_password = "USER_PASSWORD"; // Mysql password
$db_name = "DATABASE_NAME"; // Database name
$mysqli_conection = mysqli_connect($host, $db_username, $db_password, $db_name)or die("cannot connect");
?>
将 DATABASE_USER、USER_PASSWORD、 和 DATABASE_NAME 替换为您的值。
第二个文件是register.php。该文件将从 Unity 接收发布数据并将新的用户记录插入数据库表中。
注册.php
<?php
if(isset($_POST["email"]) && isset($_POST["username"]) && isset($_POST["password1"]) && isset($_POST["password2"])){
$errors = array();
$emailMaxLength = 254;
$usernameMaxLength = 20;
$usernameMinLength = 3;
$passwordMaxLength = 19;
$passwordMinLength = 5;
$email = strtolower($_POST["email"]);
$username = $_POST["username"];
$password1 = $_POST["password1"];
$password2 = $_POST["password2"];
//Validate email
if(preg_match('/\s/', $email)){
$errors[] = "Email can't have spaces";
}else{
if(!validate_email_address($email)){
$errors[] = "Invalid email";
}else{
if(strlen($email) > $emailMaxLength){
$errors[] = "Email is too long, must be equal or under " . strval($emailMaxLength) . " characters";
}
}
}
//Validate username
if(strlen($username) > $usernameMaxLength || strlen($username) < $usernameMinLength){
$errors[] = "Incorrect username length, must be between " . strval($usernameMinLength) . " and " . strval($usernameMaxLength) . " characters";
}else{
if(!ctype_alnum ($username)){
$errors[] = "Username must be alphanumeric";
}
}
//Validate password
if($password1 != $password2){
$errors[] = "Passwords do not match";
}else{
if(preg_match('/\s/', $password1)){
$errors[] = "Password can't have spaces";
}else{
if(strlen($password1) > $passwordMaxLength || strlen($password1) < $passwordMinLength){
$errors[] = "Incorrect password length, must be between " . strval($passwordMinLength) . " and " . strval($passwordMaxLength) . " characters";
}else{
if(!preg_match('/[A-Za-z]/', $password1) || !preg_match('/[0-9]/', $password1)){
$errors[] = "Password must contain atleast 1 letter and 1 number";
}
}
}
}
//Check if there is user already registered with the same email or username
if(count($errors) == 0){
//Connect to database
require dirname(__FILE__) . '/database.php';
if ($stmt = $mysqli_conection->prepare("SELECT username, email FROM sc_users WHERE email = ? OR username = ? LIMIT 1")) {
/* bind parameters for markers */
$stmt->bind_param('ss', $email, $username);
/* execute query */
if($stmt->execute()){
/* store result */
$stmt->store_result();
if($stmt->num_rows > 0){
/* bind result variables */
$stmt->bind_result($username_tmp, $email_tmp);
/* fetch value */
$stmt->fetch();
if($email_tmp == $email){
$errors[] = "User with this email already exist.";
}
else if($username_tmp == $username){
$errors[] = "User with this name already exist.";
}
}
/* close statement */
$stmt->close();
}else{
$errors[] = "Something went wrong, please try again.";
}
}else{
$errors[] = "Something went wrong, please try again.";
}
}
//Finalize registration
if(count($errors) == 0){
$hashedPassword = password_hash($password1, PASSWORD_BCRYPT);
if ($stmt = $mysqli_conection->prepare("INSERT INTO sc_users (username, email, password) VALUES(?, ?, ?)")) {
/* bind parameters for markers */
$stmt->bind_param('sss', $username, $email, $hashedPassword);
/* execute query */
if($stmt->execute()){
/* close statement */
$stmt->close();
}else{
$errors[] = "Something went wrong, please try again.";
}
}else{
$errors[] = "Something went wrong, please try again.";
}
}
if(count($errors) > 0){
echo $errors[0];
}else{
echo "Success";
}
}else{
echo "Missing data";
}
function validate_email_address($email) {
return preg_match('/^([a-z0-9!#$%&\'*+-\/=?^_`{|}~.]+@[a-z0-9.-]+\.[a-z0-9]+)$/i', $email);
}
?>
最后一个文件是 login.php,它将接收凭据并根据 sc_users 表检查它们。
登录.php
<?php
if(isset($_POST["email"]) && isset($_POST["password"])){
$errors = array();
$email = $_POST["email"];
$password = $_POST["password"];
//Connect to database
require dirname(__FILE__) . '/database.php';
if ($stmt = $mysqli_conection->prepare("SELECT username, email, password FROM sc_users WHERE email = ? LIMIT 1")) {
/* bind parameters for markers */
$stmt->bind_param('s', $email);
/* execute query */
if($stmt->execute()){
/* store result */
$stmt->store_result();
if($stmt->num_rows > 0){
/* bind result variables */
$stmt->bind_result($username_tmp, $email_tmp, $password_hash);
/* fetch value */
$stmt->fetch();
if(password_verify ($password, $password_hash)){
echo "Success" . "|" . $username_tmp . "|" . $email_tmp;
return;
}else{
$errors[] = "Wrong email or password.";
}
}else{
$errors[] = "Wrong email or password.";
}
/* close statement */
$stmt->close();
}else{
$errors[] = "Something went wrong, please try again.";
}
}else{
$errors[] = "Something went wrong, please try again.";
}
if(count($errors) > 0){
echo $errors[0];
}
}else{
echo "Missing data";
}
?>
- 将所有 3 个文件上传到您的 public_html 文件夹。
第 4 步:将客户端逻辑编程为 Unity
客户端逻辑将包含一个 C# 脚本,它将数据发送到 PHP 脚本。
- 在 Unity 中创建 一个新脚本并将其命名为 SC_LoginSystem,然后将以下代码粘贴到其中:
SC_LoginSystem.cs
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class SC_LoginSystem : MonoBehaviour
{
public enum CurrentWindow { Login, Register }
public CurrentWindow currentWindow = CurrentWindow.Login;
string loginEmail = "";
string loginPassword = "";
string registerEmail = "";
string registerPassword1 = "";
string registerPassword2 = "";
string registerUsername = "";
string errorMessage = "";
bool isWorking = false;
bool registrationCompleted = false;
bool isLoggedIn = false;
//Logged-in user data
string userName = "";
string userEmail = "";
string rootURL = "http://YOUR_SITE.COM/"; //Path where php files are located
void OnGUI()
{
if (!isLoggedIn)
{
if (currentWindow == CurrentWindow.Login)
{
GUI.Window(0, new Rect(Screen.width / 2 - 125, Screen.height / 2 - 115, 250, 230), LoginWindow, "Login");
}
if (currentWindow == CurrentWindow.Register)
{
GUI.Window(0, new Rect(Screen.width / 2 - 125, Screen.height / 2 - 165, 250, 330), RegisterWindow, "Register");
}
}
GUI.Label(new Rect(5, 5, 500, 25), "Status: " + (isLoggedIn ? "Logged-in Username: " + userName + " Email: " + userEmail : "Logged-out"));
if (isLoggedIn)
{
if (GUI.Button(new Rect(5, 30, 100, 25), "Log Out"))
{
isLoggedIn = false;
userName = "";
userEmail = "";
currentWindow = CurrentWindow.Login;
}
}
}
void LoginWindow(int index)
{
if (isWorking)
{
GUI.enabled = false;
}
if (errorMessage != "")
{
GUI.color = Color.red;
GUILayout.Label(errorMessage);
}
if (registrationCompleted)
{
GUI.color = Color.green;
GUILayout.Label("Registration Completed!");
}
GUI.color = Color.white;
GUILayout.Label("Email:");
loginEmail = GUILayout.TextField(loginEmail);
GUILayout.Label("Password:");
loginPassword = GUILayout.PasswordField(loginPassword, '*');
GUILayout.Space(5);
if (GUILayout.Button("Submit", GUILayout.Width(85)))
{
StartCoroutine(LoginEnumerator());
}
GUILayout.FlexibleSpace();
GUILayout.Label("Do not have account?");
if (GUILayout.Button("Register", GUILayout.Width(125)))
{
ResetValues();
currentWindow = CurrentWindow.Register;
}
}
void RegisterWindow(int index)
{
if (isWorking)
{
GUI.enabled = false;
}
if (errorMessage != "")
{
GUI.color = Color.red;
GUILayout.Label(errorMessage);
}
GUI.color = Color.white;
GUILayout.Label("Email:");
registerEmail = GUILayout.TextField(registerEmail, 254);
GUILayout.Label("Username:");
registerUsername = GUILayout.TextField(registerUsername, 20);
GUILayout.Label("Password:");
registerPassword1 = GUILayout.PasswordField(registerPassword1, '*', 19);
GUILayout.Label("Password Again:");
registerPassword2 = GUILayout.PasswordField(registerPassword2, '*', 19);
GUILayout.Space(5);
if (GUILayout.Button("Submit", GUILayout.Width(85)))
{
StartCoroutine(RegisterEnumerator());
}
GUILayout.FlexibleSpace();
GUILayout.Label("Already have an account?");
if (GUILayout.Button("Login", GUILayout.Width(125)))
{
ResetValues();
currentWindow = CurrentWindow.Login;
}
}
IEnumerator RegisterEnumerator()
{
isWorking = true;
registrationCompleted = false;
errorMessage = "";
WWWForm form = new WWWForm();
form.AddField("email", registerEmail);
form.AddField("username", registerUsername);
form.AddField("password1", registerPassword1);
form.AddField("password2", registerPassword2);
using (UnityWebRequest www = UnityWebRequest.Post(rootURL + "register.php", form))
{
yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success)
{
errorMessage = www.error;
}
else
{
string responseText = www.downloadHandler.text;
if (responseText.StartsWith("Success"))
{
ResetValues();
registrationCompleted = true;
currentWindow = CurrentWindow.Login;
}
else
{
errorMessage = responseText;
}
}
}
isWorking = false;
}
IEnumerator LoginEnumerator()
{
isWorking = true;
registrationCompleted = false;
errorMessage = "";
WWWForm form = new WWWForm();
form.AddField("email", loginEmail);
form.AddField("password", loginPassword);
using (UnityWebRequest www = UnityWebRequest.Post(rootURL + "login.php", form))
{
yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success)
{
errorMessage = www.error;
}
else
{
string responseText = www.downloadHandler.text;
if (responseText.StartsWith("Success"))
{
string[] dataChunks = responseText.Split('|');
userName = dataChunks[1];
userEmail = dataChunks[2];
isLoggedIn = true;
ResetValues();
}
else
{
errorMessage = responseText;
}
}
}
isWorking = false;
}
void ResetValues()
{
errorMessage = "";
loginEmail = "";
loginPassword = "";
registerEmail = "";
registerPassword1 = "";
registerPassword2 = "";
registerUsername = "";
}
}
将 http://YOUR_SITE.COM/ 替换为您的值(这应该是您上传 PHP 文件的根路径)。另外,如果您的服务器安装了 SSL 证书,请确保使用 HTTPS。
- 创建一个新的游戏对象并为其命名 "LoginSystem"
- 将 附加到 SC_LoginSystem 到 LoginSystem 对象
按“播放”,然后单击“注册”以创建新帐户或提供登录凭据。
我们继续本教程,介绍如何创建 在线排行榜。