نظام تسجيل الدخول الوحدة مع PHP وMySQL

في هذا البرنامج التعليمي، سأوضح كيفية إنشاء نظام تسجيل دخول في Unity باستخدام PHP وMySQL.

يتطلب هذا البرنامج التعليمي خادمًا مزودًا بـ cPanel بالإضافة إلى PHP وMySQLi (نسخة محسنة من MySQL).

لا تتردد في التحقق من استضافة VPS المميزة ذات الأسعار المعقولة أو بديل Shared Hosting الأرخص.

الخطوة 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.

الملف الأول هو data.php والذي سيتصل بقاعدة بيانات MySQL باستخدام ملحق PHP MySQLi.

قاعدة البيانات.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";
	}
?>
  • قم بتحميل جميع الملفات الثلاثة إلى مجلد 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). تأكد أيضًا من استخدام HTTPS إذا كان الخادم الخاص بك مثبتًا عليه شهادة SSL.

  • قم بإنشاء GameObject جديد وقم بتسميته "LoginSystem"
  • قم بإرفاق بـ SC_LoginSystem إلى كائن LoginSystem

اضغط على "تشغيل" ثم انقر فوق "تسجيل" لإنشاء حساب جديد أو تقديم بيانات الاعتماد لتسجيل الدخول.

لدينا استمرار لهذا البرنامج التعليمي حول كيفية إنشاء لوحة المتصدرين عبر الإنترنت.

المقالات المقترحة
الوحدة على الانترنت المتصدرين البرنامج التعليمي
اصنع لعبة سيارات متعددة اللاعبين باستخدام PUN 2
اصنع لعبة متعددة اللاعبين في Unity باستخدام PUN 2
مقدمة إلى الفوتون فيوجن 2 في الوحدة
دليل المبتدئين لشبكة الفوتون (الكلاسيكية).
بناء ألعاب شبكية متعددة اللاعبين في Unity
ضغط البيانات متعددة اللاعبين ومعالجة البتات