المرجع الشامل في Unity
نسخة موسعة جدًا للمبتدئين: من الصفر حتى مشروع متكامل
مرجع تدريسي أكاديمي مع أمثلة عمليةفهرس المحتويات (متدرج من الأسهل إلى الأصعب)
📘 الفصل الأول: مدخل Unity + طريقة التفكير الصحيحة
لماذا هذا الفصل مهم جدًا للمبتدئ؟
أكثر سبب يجعل الطالب يتعب في Unity ليس صعوبة الأدوات، بل غياب الصورة الكبيرة. عندما تدخل Unity بدون منهج واضح، تشعر أن كل شيء متداخل: مشاهد، كائنات، أصوات، سكربتات، فيزياء. هذا الفصل يبني الخريطة الذهنية التي تمنع الضياع.
ثلاثة أسئلة قبل أي مشروع
- ما هدف اللعبة؟
- ما الحلقة الأساسية للعب (Core Loop)؟
- كيف يعرف اللاعب أنه نجح أو فشل؟
| العنصر | المعنى | مثال |
|---|---|---|
| Goal | الهدف | جمع 20 عملة |
| Challenge | التحدي | الوقت محدود + أعداء |
| Feedback | التغذية الراجعة | صوت/نص/اهتزاز/تأثير بصري |
قبل أن تفتح الكود: اكتب مستند تصميم صغير (1 صفحة) يحدد قواعد اللعبة. هذا يوفر ساعات من التخبط.
📘 الفصل الثاني: GameObject و Components و Transform بعمق
Why: لماذا Unity يعتمد على Components؟
لأن التركيب (Composition) أكثر مرونة من الوراثة الثقيلة. يمكنك تحويل نفس الكائن من عنصر ثابت إلى عنصر فيزيائي فقط بإضافة/إزالة Component.
Transform: أهم Component في Unity
لا يوجد GameObject بدون Transform. كل حركة ودوران وحجم تبدأ منه.
using UnityEngine;
public class TransformDeepDemo : MonoBehaviour
{
[SerializeField] private Transform target;
void Start()
{
// World position
transform.position = new Vector3(0f, 1f, 0f);
// Local position relative to parent
transform.localPosition = new Vector3(0f, 0.5f, 0f);
// Rotate smoothly toward target if available
if (target != null)
{
transform.LookAt(target);
}
}
}
localPosition يتأثر بالأب (Parent)، بينما position في العالم مباشرة. هذا يسبب كثير أخطاء للطلاب.
📘 الفصل الثالث: السكربتات ودورة الحياة (Lifecycle) والـ Time
Awake vs Start vs Update vs FixedUpdate
| الدالة | متى تعمل | أفضل استخدام |
|---|---|---|
| Awake | عند تحميل الكائن | تهيئة المراجع الداخلية |
| Start | قبل أول Frame | تهيئة تعتمد على كائنات أخرى |
| Update | كل Frame | قراءة الإدخال وتحديث UI خفيف |
| FixedUpdate | بمعدل ثابت | تحديث الفيزياء |
using UnityEngine;
public class TimeAndLoop : MonoBehaviour
{
private float _elapsed;
void Update()
{
// deltaTime prevents frame-rate dependency.
_elapsed += Time.deltaTime;
if (_elapsed >= 2f)
{
Debug.Log("2 seconds passed");
_elapsed = 0f;
}
}
}
📘 الفصل الرابع: الإدخال والحركة الأساسية (3D)
Why: لماذا نفصل الإدخال عن الحركة؟
القراءة في Update والاستجابة الفيزيائية في FixedUpdate تمنع اختلاف السلوك بين الأجهزة السريعة والبطيئة.
using UnityEngine;
public class BasicMovement3D : MonoBehaviour
{
[SerializeField] private float speed = 5f;
private Rigidbody _rb;
private Vector3 _input;
void Awake() { _rb = GetComponent<Rigidbody>(); }
void Update()
{
_input.x = Input.GetAxisRaw("Horizontal");
_input.z = Input.GetAxisRaw("Vertical");
_input = _input.normalized;
}
void FixedUpdate()
{
_rb.velocity = new Vector3(_input.x * speed, _rb.velocity.y, _input.z * speed);
}
}
📘 الفصل الخامس: الفيزياء التفصيلية 3D
Rigidbody: جسم فيزيائي يتحرك بالقوى والسرعة.Collider: شكل التصادم.IsTrigger: كشف عبور بدون تصادم مادي.
using UnityEngine;
public class JumpController3D : MonoBehaviour
{
[SerializeField] private float jumpForce = 7f;
[SerializeField] private Transform groundPoint;
[SerializeField] private LayerMask groundLayer;
private Rigidbody _rb;
private bool _jumpRequested;
void Awake() { _rb = GetComponent<Rigidbody>(); }
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) _jumpRequested = true;
}
void FixedUpdate()
{
if (_jumpRequested && Physics.CheckSphere(groundPoint.position, 0.2f, groundLayer))
{
_rb.velocity = new Vector3(_rb.velocity.x, 0f, _rb.velocity.z);
_rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
_jumpRequested = false;
}
}
📘 الفصل السادس: الفيزياء التفصيلية 2D
أهم فرق عملي عن 3D
كل شيء يكون بمكونات 2D. أي خلط بين 2D و3D يمنع عمل التصادمات.
using UnityEngine;
public class Collision2DGuide : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D c)
{
Debug.Log("2D Collision: " + c.gameObject.name);
}
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("2D Trigger: " + other.gameObject.name);
}
}
📘 الفصل السابع: Animation + Animator + State Machine
بناء Animator Controller صحيح
- States: Idle, Run, Jump, Fall.
- Parameters: Speed(float), IsGrounded(bool).
- Transitions بشروط واضحة.
using UnityEngine;
public class AnimatorBinder : MonoBehaviour
{
[SerializeField] private Animator animator;
[SerializeField] private Rigidbody2D rb;
void Update()
{
animator.SetFloat("Speed", Mathf.Abs(rb.velocity.x));
animator.SetBool("IsGrounded", Mathf.Abs(rb.velocity.y) < 0.01f);
}
}
📘 الفصل الثامن: UI و Canvas و TextMeshPro
UI ليس مجرد نص على الشاشة
واجهة المستخدم هي عقد المعلومات بين اللعبة واللاعب: نقاط، صحة، وقت، رسائل الفوز والخسارة.
using TMPro;
using UnityEngine;
public class HUDController : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI scoreText;
private int _score;
public void AddScore(int value)
{
_score += value;
scoreText.text = "Score: " + _score;
}
}
📘 الفصل التاسع: GameManager وإدارة الحالة والمشاهد
Why: لماذا نحتاج GameManager؟
GameManager يدير الحالة العامة ويمنع تكرار منطق اللعبة عبر ملفات متفرقة.
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManagerFlow : MonoBehaviour
{
public static GameManagerFlow Instance;
public int Lives = 3;
void Awake()
{
if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); }
else Destroy(gameObject);
}
public void LoseLife()
{
Lives--;
if (Lives <= 0) SceneManager.LoadScene("GameOver");
}
}
📘 الفصل العاشر: Prefabs و Coroutines و Spawn Systems
لماذا Prefab أساس الإنتاجية؟
Prefab يقلل التكرار، ويجعل تعديل نموذج واحد ينعكس على كل النسخ الجديدة منه.
using System.Collections;
using UnityEngine;
public class WaveSpawner : MonoBehaviour
{
[SerializeField] private GameObject enemyPrefab;
void Start()
{
StartCoroutine(SpawnRoutine());
}
private IEnumerator SpawnRoutine()
{
while (true)
{
for (int i = 0; i < 3; i++)
{
Instantiate(enemyPrefab, transform.position + Random.insideUnitSphere * 2f, Quaternion.identity);
yield return new WaitForSeconds(0.4f);
}
yield return new WaitForSeconds(4f);
}
}
}
📘 الفصل الحادي عشر: Audio System (SFX/Music/Mixer)
تصميم صوتي بسيط لكنه احترافي
| الطبقة | المحتوى | ملاحظة |
|---|---|---|
| Music | خلفية مستمرة | Loop + مستوى منخفض |
| SFX | قفز/ضرب/جمع | PlayOneShot |
| UI | ضغط أزرار | يرتبط بالقوائم |
الموازنة بين الموسيقى والمؤثرات أهم من جودة الملف الصوتي نفسه.
📘 الفصل الثاني عشر: ScriptableObject + Event Bus
فصل البيانات عن المنطق
ScriptableObject يمنحك قوة تخزين البيانات خارج MonoBehaviour، مما يسهل إعادة استخدامها في عدة Scenes دون تكرار.
using UnityEngine;
[CreateAssetMenu(menuName = "Configs/Enemy")]
public class EnemyConfig : ScriptableObject
{
public int health;
public float moveSpeed;
}
📘 الفصل الثالث عشر: Save/Load Architecture
ابدأ بسيطًا ثم توسع
PlayerPrefs بسيط لكنه يناسب النماذج الصغيرة. للمشاريع الأكبر، يمكن الانتقال إلى JSON + File I/O.
using UnityEngine;
public static class SaveLoadSimple
{
public static void SaveBest(int best)
{
PlayerPrefs.SetInt("BEST_SCORE", best);
PlayerPrefs.Save();
}
public static int LoadBest()
{
return PlayerPrefs.GetInt("BEST_SCORE", 0);
}
}
📘 الفصل الرابع عشر: تنظيم المشروع بأسلوب Clean Architecture مبسط
هيكل مجلدات عملي مقترح
// Assets/Scripts/Domain - قواعد العمل الأساسية
// Assets/Scripts/Application - Use Cases وLogic متوسط
// Assets/Scripts/Presentation - UI Controllers
// Assets/Scripts/Infrastructure - حفظ/تحميل/Audio/Services
// Assets/Scripts/Common - Utilities/Extensions/Constants
أي كود UI يستدعي كود Domain مباشرة بشكل عشوائي هو إشارة أن الهيكلة تحتاج تحسين.
📘 الفصل الخامس عشر: مشروع تخرج متكامل + Rubric + خطة تدريب
متطلبات المشروع النهائي (Coin Rush Pro)
- لاعب يتحرك ويقفز ويتأثر بالفيزياء.
- أعداء أو عقبات مع نظام Spawn.
- نقاط + وقت + شاشات فوز/خسارة.
- Audio كامل (Music/SFX).
- حفظ أفضل نتيجة.
- تنظيم ملفات بمبدأ فصل المسؤوليات.
Rubric تقييم (100)
| المعيار | الدرجة | التفصيل |
|---|---|---|
| وظائف اللعبة | 30 | كل المزايا المطلوبة تعمل بثبات |
| جودة الكود | 20 | أسماء واضحة، تنظيم، تجنب التكرار |
| صحة استخدام Unity | 20 | تطبيق صحيح لـ Physics/Animator/UI |
| تجربة المستخدم | 15 | وضوح الواجهة والصوت والتغذية الراجعة |
| الاختبار والاستقرار | 15 | معالجة حالات الحواف وعدم الانهيار |
لكي يصبح الطالب جاهزًا لسوق العمل: اطلب منه تقديم شرح معماري مختصر (5 دقائق) يبرر قراراته البرمجية.
📘 الفصل السادس عشر: قالب الدرس العملي (شرح + تمرين + حل نموذجي)
كيف نستخدم هذا القالب في كل محاضرة؟
لجعل التعلم عمليًا ومنظمًا، كل درس يمر بثلاث مراحل ثابتة: شرح المفهوم، تنفيذ تمرين، ثم مراجعة حل نموذجي. بهذه الطريقة الطالب لا يحفظ فقط، بل يبني مهارة حل المشكلات.
| المرحلة | المدة المقترحة | الهدف |
|---|---|---|
| شرح Why/How | 20 دقيقة | فهم الفكرة وسياقها |
| تطبيق مباشر | 25 دقيقة | تحويل الفهم إلى كود |
| مراجعة الحل | 15 دقيقة | تثبيت المفهوم وتصحيح الأخطاء |
مثال تمرين من الفيزياء 2D
المطلوب: حركة يمين/يسار + قفز مرة واحدة عند ملامسة الأرض + طباعة تحذير إذا اللاعب حاول القفز وهو في الهواء.
using UnityEngine;
public class LessonTemplate_Solution : MonoBehaviour
{
[SerializeField] private float speed = 6f;
[SerializeField] private float jumpForce = 10f;
[SerializeField] private Transform groundCheck;
[SerializeField] private LayerMask groundLayer;
private Rigidbody2D _rb;
void Awake() { _rb = GetComponent<Rigidbody2D>(); }
void Update()
{
float x = Input.GetAxisRaw("Horizontal");
_rb.velocity = new Vector2(x * speed, _rb.velocity.y);
bool grounded = Physics2D.OverlapCircle(groundCheck.position, 0.15f, groundLayer);
if (Input.GetKeyDown(KeyCode.Space))
{
if (grounded)
{
_rb.velocity = new Vector2(_rb.velocity.x, 0f);
_rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
else
{
Debug.Log("Cannot jump: player is not grounded.");
}
}
}
}
ثبّت هذا القالب في كل درس، وستلاحظ تحسنًا سريعًا في أداء الطلاب.
📘 الفصل السابع عشر: خطة تدريس 8 أسابيع
خطة تنفيذ الكورس داخل فصل تدريبي
| الأسبوع | الوحدات | الهدف | ناتج مطلوب |
|---|---|---|---|
| 1 | 1-2 | فهم البيئة وComponents | مشهد ابتدائي منظم |
| 2 | 3-4 | Lifecycle + حركة 3D | لاعب متحرك |
| 3 | 5 | فيزياء 3D عميقة | قفز/Collision/Trigger |
| 4 | 6-7 | 2D Physics + Animator | مشهد Platformer صغير |
| 5 | 8-9 | UI + إدارة الحالة | HUD + GameOver |
| 6 | 10-11 | Spawn + Audio | موجات أعداء + SFX/Music |
| 7 | 12-13 | Data + Save/Load | حفظ تقدم اللاعب |
| 8 | 14-15 | Architecture + Project | عرض مشروع نهائي |
نموذج توزيع درجات
- 30% واجبات أسبوعية.
- 20% تقييم عملي منتصف الكورس.
- 50% مشروع نهائي.
📘 الفصل الثامن عشر: Debugging Playbook
خطة تشخيص الأعطال بدون تخمين
أي مشكلة في Unity يمكن التعامل معها إذا اتبعت منهجًا ثابتًا بدل العشوائية.
| الخطوة | ماذا تفعل؟ | أداة Unity |
|---|---|---|
| 1 | عرّف السلوك المتوقع | ملاحظة واضحة |
| 2 | حدّد السلوك الفعلي | Game View + Console |
| 3 | تابع القيم أثناء التشغيل | Inspector Runtime |
| 4 | أضف Logs دقيقة | Debug.Log |
| 5 | اختبر فرضية واحدة | تعديل صغير + إعادة اختبار |
using UnityEngine;
public class DebugChecklist : MonoBehaviour
{
[SerializeField] private Rigidbody2D rb;
void Update()
{
// Structured debugging line helps identify timing/value issues fast.
Debug.Log("[DebugChecklist] frame=" + Time.frameCount + " pos=" + transform.position + " vel=" + rb.velocity);
}
}
لا تغيّر عدة أشياء معًا أثناء التصحيح. غيّر عنصرًا واحدًا فقط في كل تجربة.