ইউনিটি সম্পর্কে ধারণা এবং একটি গেম তৈরি

ইউনিটি দারুণ একটা গেম ইঞ্জিন। গেম বানানো কত সহজ হতে পারে, তা ইউনিটি নিয়ে কাজ না করলে বুঝা যেত না। ইউনিটি দিয়ে 2D অথবা 3D গেম তৈরি করা যায়। একই গেম এক সাথে সব প্লাটফর্মে রিলিজ করা যায়।

ইউনিটি নিয়ে কাজ করার জন্য প্রথমে ইউনিটি হাব ডাউনলোড করে নিতে হবে। ডাউনলোড শেষে ওপেন করলে প্রথমে সব কিছু ইন্সটল হতে কিছু সময় নিবে।

ইউনিটির সাথে আমাদের একটা কোড এডিটর ও লাগবে। তার জন্য আমরা চাইলে ভিজুয়াল স্টুডিও কোড ব্যবহার করতে পারি। ভালো যদি ভিজুয়াল স্টুডিও ব্যবহার করি। তা ইউনিটি হাব থেকেই ইন্সটল করা যাবে। তার জন্য ইউনিটি হাবের Install ট্যাবে গিয়ে ইন্সটল করে নেওয়া যাবে।

ইন্সটল শেষে আমরা একটা প্রজেক্ট তৈরি করব। Unity Hub ওপেন করে New তে ক্লিক করলে নতুন প্রজেক্ট তৈরি করার অপশন আসবে। আমরা একটা 2D গেম তৈরি করব। তাই সিলেক্ট করব 2D প্রজেক্টের একটা নাম দিলে প্রজেক্ট তৈরি হয়ে যাবে। প্রজেক্ট তৈরির পর ওপেন করলে নিচের মত করে দেখতে পাবোঃ

আমরা আরেকটা ফ্লাপি বার্ড তৈরি করব। দেখব কত সহজেই একটা গেম তৈরি করা যায়। অন্য যে কোন কিছুই তৈরি করতে পারেন। ফ্লাপি বার্ডের স্প্রাইট এখানে পাওয়া যাবে। স্প্রাইট হচ্ছে অনেক গুলো ইমেজের সমষ্টি। এই ইমেজকে স্লাইস করে নিতে হবে। তা ইউনিটির মাধ্যমেই করা যায়।

প্রথমে ইমেজটি প্রজেক্ট উইন্ডো তে এসেট ফোল্ডারে রাখব। এরপর ইমেজটি সিলেক্ট করলে ডানপাশে ইন্সপেক্টরে ইমেজটি নিয়ে যা যা করতে পারব, দেখাবে যা। আমরা প্রথমে স্প্রাইট এডিটর দিয়ে ইমেজটি স্লাইস করে নিব।

তার জন্য প্রথমে Sprite Mode সিঙ্গেল থেকে মাল্টিপল করে নিব। এরপর নিচের দিকে এপ্লাই বাটনে ক্লিক করব। এবং এরপর Sprite Editor বাটনে ক্লিক করব। তাহলে স্প্রাইট এডিটর হবে হবে। স্প্রাইট এডিটর থেকে স্লাইস অপশনে ক্লিক করব এবং Slice বাটনে ক্লিক করব। এবং শেষে স্প্রাইট এডিটরে Apply বাটনে ক্লিক করব। এবার আমরা স্প্রাইট এডিটর ক্লোজ করতে পারি।

এখন যদি প্রজেক্ট উইন্ডোতে যাই, দেখব ইমেজের পাশে ছোট্ট একটা এরও কী। ঐ এরও বাটনে ক্লিক করলে স্লাইসকৃত ইমেজ গুলো দেখব। আমরা দেখব স্প্রাইট এডিটর অনেক গুলো ইমেজ তৈরি করে দিয়েছে আমাদের। সেখান থেকে আমরা ব্যাকগ্রাউন্ড ইমেজ নিয়ে হারারাকিতে ছেড়ে দিব। তাহলে সিন ভিউতে এটা যুক্ত হবে। আমরা চাইলে রিসাইজ টুল ব্যবহার করে এটিকে ছোট বড় করতে পারব।

আমরা যে গেমটি তৈরি করব, তা শুধু Portrait মুডে খেলব। তাই প্রথমে গেমটির aspect ratio সেট করে নিব। এ জন্য গেম ট্যাবে গিয়ে 9:16 সিলেক্ট করে নিব।

যদি 9:16 aspect ratio না থাকে, তাহলে আমরা এড করে নিতে পারব। এ জন্য + এ ক্লিক করে Aspect Ratio সিলেক্ট করে আমাদের রেশিও দিয়ে ওকে দিব।

গেমটা কেমন দেখাবে, তা Play বাটনে ক্লিক করে দেখতে পাবো। সিন ভিউতে একটা আয়াতাকার গাইড লাইনের ভেতর যা থাকবে, তাই গেম ভিউতে দেখা যাবে। ঐ গাইড লাইন অনুযায়ী ব্যাকগ্রাউন্ডটা আমরা ছোট বড় করে নিব।

এবার আমাদের ফ্লাপি বার্ডটাকে আমরা গেমে যুক্ত করার জন্য প্রস্তুত। এসেট থেকে ফ্লাপি বার্ডটাকে হারাকিতে ছেড়ে দিব। তাহলে সিনে তা দেখাবে। মুভ টুল ব্যবহার করে এদিক সেদিক আমরা তাকে সরাতে পারব। গেম সিনের মাঝ বরাবর বাম পাশে রাখব এটিকে। প্লে করলে দেখব ফ্লাপি বার্ডটা নেই। কারণ তা ব্যাকগ্রাউন্ডের পেছএন পড়ে গিয়েছে। কোন গেম অবজেক্ট কোনটার উপর থাকবে, তা আমরা সেট করে দিতে পারব ইন্সপেক্টর থেক Order in layer থেকে।

ফ্লাপি বার্ড সিলেক্ট করে ইনস্পেক্টর থেকে Order in layer 1 করে দিব। এবার প্লে করলে আমরা ফ্লাপি বার্ড দেখতে পাবো।

ফ্লাপি বার্ড তো একটা পিজিক্স বডি তাই না? এর ভর আছে। উপড়ে ছেড়ে দিলে গ্রাভিটির জন্য তা নিচের দিকে পড়ে যাবে এমন অন্যান্য ফিজিক্স। আমাদের যদি এই ফিজিক্স গুলো নিজেরা লিখতে হত, তাহলে অনেক অনেক কোড লিখতে হতো। ভাগ্য ভালো গেম ইঞ্জিন গুলোতে এই ফিজিক্স গুলো লেখা থাকে। আমরা ব্যবহার করতে পারি সহজেই। ফ্লাপি বার্ড সিলেক্ট করে হায়ারাকি থেক add component এ ক্লিক করব। এবং এখান থেকে Rigidbody 2D এড করব আমাদের ফ্লাপি বার্ডে। এবার যদি গেম প্লে করি, তাহলে দেখব ফ্লাপি বার্ড ঠুস করে নিচে পড়ে যায়।

আমরা তো চাই না ফ্লাপি বার্ড নিচে পড়ে যাক, আমরা চাই তাকে যেন উড়াতে পারি। এই উড়ার কোডটা আমরা লিখতে হবে। ইউনিটিতে তা লেখা নেই। যদিও খুব সহজেই আমরা তা লিখতে পারি। তার জন্য প্রজেক্ট উইন্ডোতে ক্লিক করে Create > C# Script এ ক্লিক করব। এরপর একটা নাম দিব। যেমন FlyBird। যে কোন কোড এডিটরে এই স্ক্রিপ্টটা ওপেন করব। দেখব কিছু কোড অলরেডি লেখা আছে। এর মধ্যে একটা হচ্ছে Star মেথড। আরেকটা হচ্ছে Update মেথড। এই স্টার্ট মেথড কল হয় যখনি গেম শুরু হয়। আর আপডেট মেথড কল হয় প্রতিটা ফ্রেমে।

আমরা জানি যে কোন ভিডিও হচ্ছে অনেক গুলো স্টিল ইমেজের সমন্বয়। প্রতিট স্টিল ইমেজ এক একটা ফ্রেম। 30fps মানে প্রতিটা সেকেন্ডে ৩০টা ফ্রেম প্লে হয়। গেমও ঠিক তেমনি।

আমরা যেমন Rigidbody 2D কম্পোনেন্ট এড করেছিলাম ফ্লাপি বার্ডে, ঠিক একই ভাবে এই FlyBird স্ক্রিপ্ট ও এড করতে হবে। ফ্লাপি বার্ড সিলেক্ট করে প্রজেক্ট উইন্ডো থেকে FlyBird টেনে এনে ইন্সপেক্টরে ছেড়ে দিলেও এড হয়ে যাবে।

যাই হোক, আমরা যখনি স্ক্রিনে টাস করব, ফ্লাপি বার্ড উপরের দিকে উঠবে। তার জন্য আমরা কোড লিখতে পারি এভাবেঃ

 if (Input.GetMouseButtonDown(0))
        {

            rb.velocity = Vector2.up * velocity;

        }

এই সিম্পল কোড লিখেই আমরা ফ্লাপি বার্ডকে ফ্লাই করাতে পারব। আর কিচ্ছু না!

সম্পূর্ণ কোডঃ

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FlyBird : MonoBehaviour
{

    float velocity = 3;
    Rigidbody2D rb;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {

            rb.velocity = Vector2.up * velocity;

        }
    }
}

এখানে velocity হচ্ছে প্রতি ট্যাপে কত দ্রুত উপড়ে উঠবে। এটা নিজের মত করে কম বেশি করে নিতে পারব।

এই কোড লেখার পর যদি সেভ করে আমরা প্লে করি, তাহলে দেখব ট্যাপ করলে বার্ড উপরের দিকে উঠে।

এবার আমরা পাইপ যুক্ত করার জন্য প্রস্তুত!

এসেট উইন্ডো থেকে একটি পাইপ হায়ারেকিটে ছেড়ে দিব। এরপর উপরের দিকে রাখব। রিসাইজ টুল ব্যবহার করে ইচ্ছে মত বড় ছোট করে নিতে পারব। এরপর হায়ারেকি থেকেই এই পাইপটাকেই আবার ব্যবহার করতে পারব। এর জন্য পাইপের উপর ক্লিক করে ডুপ্লিকেট ওঠাব Ctrl/Command + D প্রেস করলেও ডুপ্লিকেট হবে।

এবার এটিকে নিচের দিকে ড্র্যাগ করে রিপজিশন করে নিব। এবং ইন্সপেক্টর থেকে Flip Y অপশন সিলেক্ট করে দিব। তাহলে আমাদের পাইপ যুক্ত করা হয়ে যাবে।

এখন যদি আমরা গেম প্লে করি, তাহলে কিচ্ছুই হবে। না। পাইপ গুলো মুভ হবে না। মুভ করার জন্য আমাদের আরেকটা স্ক্রিপ্ট লিখতে হবে। প্রজেক্ট উইন্ডো তে ক্লিক করে Create > C# Script এ ক্লিক করে নতুন স্ক্রিপ্ট তৈরি করে নিব। যে কোন নাম দিতে পারি, যেমন PipeMove।

সিম্পল এক লাইন কোড লিখলেই পাইপ মুভ হবেঃ

transform.position += Vector3.left * speed * Time.deltaTime;

এখানে স্পিড হচ্ছে কত স্পিডে পাইপ মুভ হবে। সম্পূর্ন কোডঃ

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PipeMove : MonoBehaviour
{
    public float speed = 2;

    void Update()
    {
        transform.position += Vector3.left * speed * Time.deltaTime;
    }
}

এই PipeMove স্ক্রিপ্ট দুইটা পাইপে যুক্ত করে দেওয়ার পর যদি আমরা গেম করি তাহলে দেখব পাইপ আস্তে আস্তে বামে থেকে ডান দিকে যাচ্ছে।

আমরা দেখলাম দুইটা পাইপেই একই স্ক্রপিট যুক্ত করতে হয়েছে। এটাকে সহয করার জন্য আমরা একটা গেম অবজেক্ট তৈরি করে নিতে পারি। এরপর ঐ গেম অবজেক্ট এর ভেতর যদি এই পাইপ দুইটা সেট করে দেই, তাহলে একবার শুধু ঐ গেম অবজেক্টে স্ক্রিপ্ট যুক্ত করলেই হবে। তার জন্য হায়ারেকিতে ক্লিক করে CreateEmpty তে ক্লিক করব। তাহলে একটা শূন্য গেম অবজেক্ট তৈরি হয়ে যাবে। এর একটা নাম দিতে পারি, যেমন Pipes। এরপর পাইপ একটা একটা করে ঐ গেম অবজেক্টের ভেতর ড্র্যাগ করে ছেড়ে দিব। তাহলে এখন যদি শুধু ঐ গেম অবজেক্ট মুভ করি, তাহলে দেখব একই সাথে দুইটা পাইপই মুভ হয়।

এবার পাইপ দুইটা থেকে আমরা স্ক্রিপ্টটি রিমুভ করে শুধু ঐ গেম অবজেক্টে যুক্ত করব। তাহলেও দেখব পাইপ মুভ হচ্ছে। স্ক্রিপ্ট রিমুভ করার জন্য পাইপ সিলেক্ট করে ইন্সপেক্টর থেকে স্ক্রিপ্ট এর পাশের ছোট্ট গিয়ার আইকনে ক্লিক করলে রিমুভ করার অপশন পাবো।

এখন যদি আমরা গেমটি খেলার চেষ্টা করি, তাহলে দেখব ফ্লাপি পাইপের সাথে কোলাইড করে না। তার জন্য একই সাথে পাইপ দুইটাতে এবং ফ্লাপিতে Box Collider 2D যুক্ত করতে হবে। Box Collider 2D যুক্ত করার পর যদি আমরা গেম প্লে করি, তাহলে দেখব এবার ফ্লাপি পাইপের সাথে কোলাইড করে। কিন্তু নতুন পাইপ আসে না। আমরা চাইবো পাইপ একের পর এক যেন আসতে থাকে।

আমরা আরেকটা ইম্পটি গেম অবজেক্ট তৈরি করে নিব। নাম দিতে পারি PipesSpawner। এর কাজ হচ্ছে একের পর এক পাইপ যেন আসতে থাকে, তার ব্যবস্থা করা। এর পজিশন দিব গেম সিনের বাহিরে, ডান দিকে। এই গেম অবজেক্ট যেখানে রাখব, সেখানেই নতুন পাইপ তৈরি হবে। তাই আমরা চেষ্টা করব গেম সিনের বাহিরের যেন পাইপ তৈরি হয়। আর অটোমেটিক পাইপ তৈরি হওয়ার জন্য একটা স্ক্রিপ্ট লাগবে। নাম দিতে পারি PipesSpawnerController।

এর জন্য কোড লিখতে পারি নিচের মত করেঃ

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PipesSpawnerController : MonoBehaviour
{


    public float maxTime = 2;
    public GameObject pipes;
    private float timer;
    public float height = 1;

    void Update()
    {

        if (timer > maxTime)
        {
            GameObject newPipe = Instantiate(pipes);
            newPipe.transform.position = transform.position + new Vector3(0, Random.Range(-height, height), 0);
            Destroy(newPipe, 15);
            timer = 0;
        }

        timer += Time.deltaTime;

    }
}

maxTime হচ্ছে কতক্ষণ পর পর নতুন পাইপ তৈরি হবে। আমরা এখানে ২ সেট করেছি।

GameObject newPipe = Instantiate(pipes); নতুন করে পাইপের কপি তৈরি করা হয়েছে। এরপর পাইপটার পজিশন সেট করা হয়েছে। কোন গেম অবজেক্টের পজিশনের জন্য ৩টা ভ্যালু লাগে। X,Y এবং Z। এখানে X এবং Z এর ভ্যালু শূন্য। মানে যেখানে আমরা PipesSpawner রাখব, সেখানেই থাকব। শুধু মাত্র Y ভ্যালু র‍্যান্ডমলি পরিবর্তন করেছি যেন পাইপ গুলো একটু উপড়ে নিচে এলোমেলো হয়ে থাকে। এর ভ্যালু শূন্য দিয়ে দেখতে পারেন।

Destroy(newPipe, 15); দিয়ে একটা নির্দিষ্ট সময় পর পাইপ ডিস্ট্রয় করেছি। না হলে যত গুলো পাইপ তৈরি হবে, সেগুলো সারাক্ষণ বাম দিকে যেতেই থাকবে আর গেম স্লো করে দিবে।

এখন এই PipesSpawnerController টা PipesSpawner এ যুক্ত করতে হবে। যুক্ত করার পর যদি আমরা দেখি, তাহলে দেখব PipesSpawner এর ইন্সপেক্টরে Pipes নামে একটা ফিল্ড দেখব। যার ভ্যালু দেখাচ্ছে None।

আমাদের কন্ট্রোলার তো জানে না কোনটা পাইপ অবজেক্ট। কোনটাকে কিছুক্ষণ পর পর নতুন করে তৈরি করতে হবে। এ জন্য বাম পাশের হায়ারেকি থেকে Pipes নামক গেম অবজেক্ট(যার ভেতর পাইপ দুইটা রয়েছে) তা ড্র্যাগ করে এনে এর ভেতর ছেড়ে দিতে হবে। এখন যদি আমরা গেম প্লে করি, তাহলে দেখব কিছুক্ষণ পর পর নতুন পাইপ আসতেছে। আমরা সুন্দর মত গেম খেলতে পারছি।

গেম খেলতে পারছি ঠিকি কিন্তু কোন কিছুর সাথে লাগলে ফ্লাপি বার্ডের কিচ্ছু হচ্ছে না। যখনি ফ্লাপি কোন কিছুর সাথে ধাক্কা খাবে, আমরা গেম ফ্রিজ করব। তার জন্য FlyBird স্ক্রিপ্টে নিচের মেথডটি যুক্ত করবঃ

 private void OnCollisionEnter2D(Collision2D collision)
    {
        Time.timeScale = 0;

    }

এখন যদি ফ্লাপি পাইপের সাথে লেগে যায়, তাহলে গেম বন্ধ হয়ে যায়। সম্পূর্ণ কোড এমন হবেঃ

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FlyBird : MonoBehaviour
{

    float velocity = 3;
    Rigidbody2D rb;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {

            rb.velocity = Vector2.up * velocity;

        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        Time.timeScale = 0;

    }
}

কি সহজেই একটা গেম তৈরি হয়ে গেলো। আমরা খেলতেও পারছি! এবার কিভাবে স্কোর দেখানো যায়, তা চেষ্টা করতে পারেন। স্বাগতম গেম ডেভেলপমেন্টে 🙂

পররের পর্বঃ

2 thoughts on “ইউনিটি সম্পর্কে ধারণা এবং একটি গেম তৈরি”

Leave a Reply