Hướng dẫn về Unity: Cách tạo một trò chơi giống như Space Invaders

nội dung

Space Invaders , được biết đến ở Nhật Bản với tên Supēsuinbēdā (スペースインベーダー) , là một trong những trò chơi cổ điển nổi tiếng nhất trên thế giới. Được phát hành vào năm 1978 bởi công ty trò chơi Nhật Bản Taito, nó nhanh chóng trở thành một hit lớn.

Trò chơi điện tử Invaders cổ điển.

Pháo bắn đạn laser đại diện cho người chơi. Người chơi có thể ẩn đằng sau bất kỳ trong bốn ngọn đuốc (トーチカ) , còn được gọi là hộp đựng thuốc .

Có ba loại kẻ xâm lược: cua , mực và bạch tuộc . Chúng xuất hiện thành một nhóm gồm nhiều hàng và di chuyển từ trên xuống dưới màn hình. Kẻ xâm lược cua đã trở thành một biểu tượng mang tính biểu tượng được liên kết phổ biến với các trò chơi điện tử và trò chơi nói chung.

Mục tiêu của trò chơi là loại bỏ những kẻ xâm lược trước khi chúng đến cuối màn hình trong khi né tránh và ẩn nấp sau những ngọn đuốc. Ngoài bầy đàn, thỉnh thoảng còn có một UFO xuất hiện. Tuy nhiên, bạn sẽ tập trung vào bầy đàn.

Trong hướng dẫn này, bạn sẽ sao chép các tính năng chơi trò chơi cốt lõi của Space Invaders bằng Unity. Trên đường đi, bạn sẽ học cách:

  • Sinh sản và di chuyển bầy đàn xâm lược.
  • Làm cho những kẻ xâm lược ở đầu đàn bắn đạn laze.
  • Di chuyển và bắn trả với tư cách là người chơi.
  • Thay đổi nhịp độ âm nhạc và tốc độ đàn dựa trên số lần tiêu diệt.

Thời gian để bắt đầu!

Lưu ý : Hướng dẫn này giả định rằng bạn đã có kinh nghiệm cơ bản với Unity và kiến ​​thức trung cấp về C#. Ngoài ra, hướng dẫn này giả định rằng bạn đang sử dụng C# 7 và Unity 2020.3.

Bắt đầu

Tải xuống tài liệu dự án bằng cách nhấp vào nút Tải xuống Tài liệu ở đầu hoặc cuối hướng dẫn này.

Giải nén tệp zip vào một vị trí thuận tiện. Sau khi giải nén, bạn sẽ thấy các thư mục dự án Starter và Final . Mở Starter trong Unity.

Dự án chứa một số thư mục để giúp bạn bắt đầu. Mở Assets/RW và bạn sẽ tìm thấy các thư mục sau:

  • Ảnh động : Chứa các hoạt ảnh được tạo sẵn và trình tạo hoạt ảnh cho các viên đạn và vụ nổ prefabs.
  • Prefabs : Có tất cả các prefabs mà dự án sử dụng.
  • Tài nguyên : Chứa phông chữ và kết cấu.
  • Cảnh : Chứa cảnh chính mà bạn sẽ làm việc.
  • Tập lệnh : Có tất cả các tập lệnh của dự án. Hầu hết trong số chúng là vỏ rỗng mà bạn sẽ lấp đầy.
  • Âm thanh : Có tất cả các hiệu ứng âm thanh và tệp nhạc.
  • Sprites : Chứa tất cả các pixel art cho dự án.

Điều hướng đến RW/Scenes và mở Main . Nhấp vào Phát và bạn sẽ thấy khẩu pháo trình phát màu đỏ ở giữa dưới cùng của màn hình và nghe thấy vòng lặp nhạc. Ngoài ra, bạn sẽ thấy Điểm số và Trực tiếp .

Bạn chưa thể tương tác với trò chơi, nhưng bạn sẽ thêm tính tương tác trong hướng dẫn này.

Điểm bắt đầu hiển thị pháo, điểm số và số mạng.

Dừng trò chơi và chọn Chỉnh sửa ▸ Cài đặt dự án ▸ Vật lý 2D . Hãy xem Ma trận va chạm lớp . Lưu ý rằng dự án này có hai lớp tùy chỉnh: Anh hùng và Kẻ thù .

Ma trận va chạm lớp Physics2D

Phát hiện va chạm Vật lý 2D cho GameObject trong lớp Kẻ thù chỉ hoạt động với GameObject trên lớp Anh hùng. GameObject lớp anh hùng hoạt động cho cả Kẻ thù và GameObject lớp anh hùng khác. Thông tin này sẽ rất quan trọng sau này.

Bây giờ, hãy xem GameObjects trong Hierarchy . Một số có các thành phần tùy chỉnh được đính kèm mà bạn sẽ làm việc trong hướng dẫn này.

Cửa sổ phân cấp của dự án

Game Controller có các thành phần Invader Swarm , Torchka Manager và Game Manager được đính kèm. Ngoài những thứ này, còn có một thành phần Nguồn âm thanh mà bạn sẽ sử dụng cho các hiệu ứng âm thanh.

Cửa sổ Thanh tra của Game Controller GameObject

Âm nhạc có Điều khiển nhạc và Nguồn âm thanh . Audio Source phát Beats nằm trong RW/Sounds . Đây là âm nhạc chính của trò chơi. Hiện tại, âm nhạc có nhịp độ cố định, nhưng sau này bạn sẽ làm cho nó động.

Music GameObject trong cửa sổ Thanh tra

CANNON có Cannon Control và Box Collider 2D để phát hiện va chạm. Lưu ý lớp của nó được đặt thành Hero . Nó cũng có hai phần tử con ngay lập tức: Sprite , là sprite liên quan của nó và Muzzle , một GameObject trống đại diện cho vị trí khởi tạo viên đạn trong khi bắn.

Trình kiểm tra thành phần CANNON

Máy ảnh chính là máy ảnh chính và duy nhất của trò chơi và có Trình nghe âm thanh . Nó chính tả với độ lệch vị trí -10 dọc theo trục Z.

Tất cả các GameObject khác có Z được đặt thành 0. Trên thực tế, đối với những GameObject khác, giả sử trục Z không tồn tại vì đây là trò chơi 2D và bạn sẽ chỉ định vị chúng trên trục X và Y.

INVADERS Spawn Start và TORCHKA Spawn Center là hai GameObject trợ giúp trống được cấp bậc cha mẹ cho Helpers . Vị trí của họ sẽ giúp bạn sinh ra bầy đàn xâm lược và đuốc sau này.

Canvas và Hệ thống sự kiện dành cho giao diện người dùng. Canvas có các con sau:

  • Văn bản điểm : Phần này hiển thị điểm.
  • Lives Text : Bạn sẽ sử dụng nó để hiển thị các trận đấu còn lại của người chơi.
  • Bảng kết thúc trò chơi : Bảng này hiển thị thông báo Trò chơi kết thúc khi một người chơi hết mạng.
  • All Clear : Bạn sẽ sử dụng bảng này để hiển thị thông báo All Clear khi người chơi loại bỏ tất cả những kẻ xâm lược.
  • Nút khởi động lại : Nút này khởi động lại trò chơi.

Bây giờ bạn đã hoàn thành chuyến tham quan, đã đến lúc thêm những thứ hay ho. :] Trong phần tiếp theo, bạn sẽ làm việc với các điều khiển trình phát.

Triển khai Điều khiển Trình phát

Chọn tập lệnh CannonControl được đính kèm với CANNON . Mở nó trong trình chỉnh sửa mã của bạn. Dán đoạn mã sau vào bên trong lớp:

[ SerializeField ]
 riêng  float speed = 500f ;

 Cập nhật khoảng trống  riêng tư ()
{
    nếu như (Input.GetKey(KeyCode.D))
    {
        biến đổi.Dịch(tốc độ * Thời gian.deltaTime, 0 , 0 );
    }
    khác  nếu (Input.GetKey(KeyCode.A))
    {
        biến đổi.Dịch (-tốc độ * Thời gian.deltaTime, 0 , 0 );
    }
}

Đây là một sự cố mã:

  • Biến speedđiều khiển tốc độ của pháo.
  • Vào trong Update, bạn kiểm tra xem người chơi đang nhấn giữ phím D hay A. Nếu người chơi giữ phím D , khẩu pháo sẽ di chuyển sang phải theo speed * Time.deltaTimetừng khung hình. Nếu họ giữ phím A , khẩu pháo sẽ di chuyển sang trái cùng một lượng.

Lưu các tập tin. Quay lại Unity và chọn Play bên trong trình chỉnh sửa. Bây giờ bạn có thể di chuyển con tàu bằng cách sử dụng D và A .

Pháo bây giờ có thể di chuyển thông qua các phím A và D.

Tiếp theo, bạn sẽ thêm cơ chế bắn súng bằng cách sử dụng Bullet prefab bên trong RW/Prefabs .

Chọn Bullet và xem Thanh tra.

Nhà lắp ghép có thành phần Kinematic Rigidbody 2D . Đó là Động học vì bạn sẽ không dựa vào vật lý để di chuyển viên đạn mà thay vào đó dịch nó thông qua một tập lệnh.

Lớp của Rigidbody 2D được đặt thành Hero và  có thành phần Box Collider 2D để phát hiện va chạm. Ngoài ra còn có một thành phần Bullet chưa làm gì cả.

Mở tập lệnh Bullet bên trong trình chỉnh sửa mã của bạn. Thêm đoạn mã sau vào bên trong lớp:

[ SerializeField ]
 riêng  float speed = 200f ;

[ SerializeField ]
 phao riêng  lifeTime = 5f ;

 khoảng trống  bên trong Phá hủy bản thân ()
{
    gameObject.SetActive( sai );
    Phá hủy (gameObject);
}

 khoảng trống  riêng tư Tỉnh táo ()
{
    Gọi ( "Tự hủy" , lifeTime);
}

 Cập nhật khoảng trống  riêng tư ()
{
    biến đổi.Translate(tốc độ * Time.deltaTime * Vector2.up);
}

private  void  OnCollisionEnter2D ( Collision2D khác )
{
    Tự hủy ();
}

Trong đoạn mã trên, bạn:

  • Sử dụng Updateđể di chuyển viên đạn theo speed * Time.deltaTimemọi khung về phía trên cùng.
  • Dùng DestroySelfđể phá viên đạn GameObject. Trước khi gọi Destroy, bạn vô hiệu hóa dấu đầu dòng vì việc hủy cần một số khung để xử lý nhưng việc vô hiệu hóa gần như ngay lập tức.
  • Awakegọi DestroySelfđể tự động phá hủy viên đạn sau lifetimevài giây. DestroySelfcũng được gọi khi một viên đạn va chạm với GameObject khác.

Bạn sẽ cần hiệu ứng âm thanh trong khi chụp. Bên trong RW/Scripts , mở GameManager và thêm phần sau vào bên trong lớp:

 Phiên bản GameManager tĩnh bên trong ;

[ SerializeField ]
 riêng AudioSource sfx;

 khoảng trống  nội bộ PlaySfx ( AudioClip clip ) => sfx.PlayOneShot(clip);

 khoảng trống  riêng tư Tỉnh táo ()
{
    nếu (Trường hợp == null )
    {
        Ví dụ = cái này ;
    }
    khác  nếu (Trường hợp != this )
    {
        Phá hủy (gameObject);
    }
}

Đoạn mã trên biến GameManagerthành một singleton, điều này đảm bảo nó chỉ có một phiên bản duy nhất tại bất kỳ thời điểm nào. Nó cũng thêm một phương thức tiện ích, PlaySfxchấp nhận Đoạn âm thanh và phát nó bằng Nguồn âm thanh sfx .

Để sử dụng dấu đầu dòng, bạn cần khởi tạo nó. Mở lại CannonControl và thêm phần sau vào sau phần khai báo cho speed:

[ SerializeField ]
 mõm Transform riêng tư ;

[ SerializeField ]
 quay AudioClip riêng tư ;

[ SerializeField ]
 float riêng  coolDownTime = 0.5f ;

[ SerializeField ]
 riêng Bullet bulletPrefab;

 bộ đếm thời gian bắn phao riêng ;

Sau đó, sau mã chuyển động trước đó bên trong Update, hãy dán:

shootTimer += Time.deltaTime;
nếu như (shootTimer > coolDownTime && Input.GetKey(KeyCode.Space))
{
    bắnTimer = 0f ;

    Khởi tạo(bulletPrefab, mzzle.position, Quaternion.identity);
    GameManager.Instance.PlaySfx(bắn súng);
}

Mã này tăng shootTimertừng khung hình cho đến khi đạt đến coolDownTime. Nếu người chơi giữ phím Space , mã sẽ đặt lại shootTimervà khởi tạo bulletPrefabtại muzzle.position. Nó cũng phát shootinghiệu ứng âm thanh bằng cách sử dụng PlaySfxbên trong GameManager.

Lưu mọi thứ và quay lại Unity.

Quay trở lại nhà lắp ghép Bullet . Lưu ý các trường mới cho thành phần Bullet .

Cửa sổ Trình kiểm tra cho nhà lắp ghép Bullet.

Bây giờ, chọn Trình điều khiển trò chơi từ Hệ thống phân cấp. Đặt Sfx của Trình quản lý trò chơi thành Nguồn âm thanh được gắn vào Bộ điều khiển trò chơi .

Cửa sổ trình kiểm tra đang hiển thị thành phần Nguồn âm thanh của Bộ điều khiển trò chơi.

Chọn CANNON từ Hệ thống phân cấp. Trong Cannon Control , trước tiên hãy đặt Muzzle thành Muzzle Transform là con của CANNON . Sau đó đặt Bullet Prefab thành Bullet tìm thấy trong RW/Prefabs . Cuối cùng, đặt Shooting thành CannonBullet được tìm thấy trong RW/Sounds .

Thành phần Cannon Control trong cửa sổ Thanh tra

Lưu và chơi . Bây giờ bạn có thể di chuyển khẩu pháo và bắn đạn laze bằng cách giữ phím Space .

Pháo bây giờ có thể bắn đạn laze.

Anh hùng của bạn đã sẵn sàng! Bây giờ là lúc để thêm nhân vật phản diện. Trong phần tiếp theo, bạn sẽ thêm đàn xâm lược.

Tạo kẻ xâm lược

Làm thế nào để tất cả các nhân vật phản diện bắt đầu cuộc sống của họ trong trò chơi? Sinh sản tất nhiên! Bạn sẽ làm điều đó tiếp theo.

Sinh ra những kẻ xâm lược

Điều hướng đến RW/Scripts để kiểm tra tập lệnh SimpleAnimator . Bạn sẽ sử dụng nó để tạo hoạt ảnh cho những kẻ xâm lược, nhưng bạn không cần phải lo lắng về hoạt động bên trong của nó đối với hướng dẫn này.

Khi bạn thêm SimpleAnimator vào GameObject, bạn cũng thêm SpriteRenderer  đó là thành phần bắt buộc để tập lệnh hoạt động.

SimpleAnimator cũng yêu cầu một loạt các họa tiết. Nó sẽ tiếp tục cập nhật sprite của SpriteRenderer theo chu kỳ bằng cách sử dụng các sprite bên trong mảng, về cơ bản là tạo hoạt ảnh cho nó.

Bây giờ, chọn Invader Swarm được gắn vào Bộ điều khiển trò chơi . Mở tập lệnh được liên kết bên trong trình chỉnh sửa mã của bạn. Thêm đoạn mã sau vào bên trong lớp:

[ System.Serializable ]
 cấu trúc riêng  InvaderType
{
     tên chuỗi công khai ;
    công khai Sprite[] sprites;
    điểm
     int công khai ;  public int rowCount; 
}

Đây là một sự cố mã:

  • Mã này xác định cấu trúc InvaderType .
  • Mảng spriteslưu trữ tất cả các họa tiết được liên kết với loại kẻ xâm lược mà SimpleAnimator sử dụng để tạo hoạt ảnh cho kẻ xâm lược.
  • rowCountlà số hàng mà loại kẻ xâm lược sẽ có trong bầy.
  • namelưu trữ tên loại cho kẻ xâm lược và pointslưu trữ phần đóng góp điểm nếu người chơi loại bỏ kẻ xâm lược thuộc loại này. Những thứ này sẽ có ích sau này.

Bây giờ thêm phần sau ngay bên dưới InvaderType:

[ Tiêu đề( "Sinh sản" ) ]
[ SerializeField ]
 InvaderType riêng tư [] InvaderTypes;

[ SerializeField ]
 private  int columnCount = 11 ;

[ SerializeField ]
 private  int ySpacing;

[ SerializeField ]
 private  int xSpacing;

[ SerializeField ]
 Chuyển đổi riêng spawnStartPoint;

 phao riêng minX;

Bạn sẽ sử dụng tất cả các trường này cho logic sinh sản:

  • invaderTypes: Đại diện cho tất cả các loại kẻ xâm lược đang sử dụng.
  • columnCount: Tổng số cột cho swarm.
  • ySpacing: Khoảng cách giữa mỗi kẻ xâm lược trong bầy dọc theo trục Y.
  • xSpacing: Khoảng cách giữa mỗi kẻ xâm lược trong bầy dọc theo trục X.
  • spawnStartPoint: Điểm sinh sản cho kẻ xâm lược đầu tiên.
  • minX: Lưu trữ giá trị vị trí X tối thiểu cho bầy đàn.

Tiếp theo, dán đoạn mã sau vào sau tất cả các khai báo biến:

 khoảng trống  riêng Bắt đầu ()
{
    minX = spawnStartPoint.position.x;

    bầy GameObject = new GameObject { name = "Swarm" };
    Vector2 currentPos = spawnStartPoint.position;

    int row Index = 0 ;
    foreach ( var kiểu kẻ xâm lược trong kiểu kẻ xâm lược)
    {
        var tên kẻ xâm lược = kẻ xâm lượcType.name.Trim();
        cho ( int tôi = 0 , len = xâm lượcType.rowCount; i < len; i++)
        {
            cho ( int j = 0 ; j < cộtCount; j++)
            {
                var kẻ xâm lược = new GameObject () { tên = tên kẻ xâm lược };
                kẻ xâm lược.AddComponent<SimpleAnimator>().sprites = kẻ xâm lượcType.sprites;
                kẻ xâm lược.transform.position = currentPos;
                kẻ xâm lược.transform.SetParent(swarm.transform);

                currentPos.x += xSpacing;
            }

            currentPos.x = minX;
            currentPos.y -= ySpacing;

            hàng Index++;
        }
    }
}

Đây là một sự cố mã:

  1. Mã này thiết lập minXbên trong Start. Sau đó, nó tạo một GameObject trống có tên Swarm .
  2. xSpacingvà ySpacingcập nhật currentPosdọc theo trục X và Y tương ứng.
  3. currentPos.xgia tăng sau mỗi lần lặp lại kẻ xâm lược trong hàng. Sau khi hoàn thành một hàng, currentPos.ygiảm dần.
  4. Lặp lại các thành viên của invaderTypes, đối với mỗi thành viên invaderType, bạn lặp lại theo hàng để tạo các GameObject kẻ xâm lược riêng lẻ tại currentPosvị trí đó.
  5. xSpacingvà ySpacingcập nhật currentPosdọc theo trục X và Y tương ứng.
  6. Mỗi GameObject kẻ xâm lược được tạo có tên được đặt thành invaderName. Sau đó, bạn thêm một SimpleAnimatorthành phần và gán mảng sprite của nó cho thành phần spritesđược liên kết với invaderType.
  7. Cuối cùng, kẻ xâm lược trở thành con của Swarmvà vị trí của nó được đặt thành currentPos.

Lưu mọi thứ và quay lại Unity.

Chọn Trình điều khiển trò chơi từ Hệ thống phân cấp. Trên Invader Swarm , hãy đặt:

  • Khoảng cách Y đến 25
  • Khoảng cách X đến 25
  • Spawn Start Point to INVADERS Spawn Start , là con của Helpers .

Sau đó, đặt kích thước Loại kẻ xâm lược thành 3 và đặt các trường thành viên như sau:

  • 0: Đặt Tên thành SQUID , Points thành 30 và Row Count thành 1 .
  • 1: Đặt Tên thành CRAB , Points thành 20 và Row Count thành 1 .
  • 2: Đặt Tên thành OCTOPUS , Points thành 10 và Row Count thành 2 .

Bây giờ, điều hướng đến RW/Sprites và nhìn vào bảng ma trận INVADERS . Đây không phải là Space Invaders ban đầu nhưng chúng sẽ phù hợp với hướng dẫn này.

Quay lại Invader Swarm và thiết lập nó như sau, sử dụng spritesheet:

Đối với mục SQUID, hãy đặt danh sách Sprites để chứa các sprite sau từ spritesheet theo thứ tự sau:

  • bug_invaders_0
  • bug_invaders_5
  • bug_invaders_9
  • bug_invaders_4

Thực hiện bài tập tương tự, nhưng lần này là CRAB bằng cách sử dụng các họa tiết sau:

  • bug_invaders_13
  • bug_invaders_18

Cuối cùng, chỉ định các họa tiết cho OCTOPUS bằng cách sử dụng:

  • bug_invaders_7
  • bug_invaders_2

Đây là một tài liệu tham khảo trực quan về những thứ sẽ trông như thế nào bây giờ:

Thiết lập cho trường Loại kẻ xâm lược của thành phần Bầy đàn xâm lược của Bộ điều khiển trò chơi.

Lưu và chơi . Chú ý bầy đàn sinh sản và những kẻ xâm lược hoạt hình ở một nơi.

Trò chơi bây giờ đã sinh ra những kẻ xâm lược.

Tuyệt vời! Nhưng họ không di chuyển. Bạn sẽ khắc phục điều đó trong phần tiếp theo.

Di chuyển quân xâm lược

Quay lại tập lệnh InvaderSwarm.cs và thêm phần sau vào sau các khai báo biến hiện có:

[ Không gian ]
[ Tiêu đề( "Chuyển động" ) ]
[ SerializeField ]
 riêng  float speedFactor = 10f ;

những kẻ xâm lược Transform[,]
 riêng tư ; private  int rowCount;
bool riêng  isMovingRight = true ;
phao riêng maxX;
riêng nổi hiện tạiX;
float riêng xIncrement;
   

Tất cả các biến này sẽ giúp di chuyển đàn:

  • speedFactorbây giờ đại diện cho tốc độ mà những kẻ xâm lược di chuyển dọc theo trục X. Sau đó, tốc độ sẽ liên quan đến nhịp độ âm nhạc nên tốc độ thực tế là sản phẩm của cả hai.
  • invaderslưu trữ các Biến đổi của tất cả các GameObject kẻ xâm lược đã tạo.
  • rowCountlưu trữ tổng số hàng của bầy đàn.
  • isMovingRightđại diện cho hướng di chuyển và được đặt truetheo mặc định.
  • maxXlà vị trí X tối đa cho phong trào bầy đàn.
  • currentXđại diện cho vị trí X tổng thể của bầy đàn.
  • xIncrementlà giá trị trên mỗi khung hình di chuyển kẻ xâm lược dọc theo trục X.

Bây giờ, trong Start, hãy thêm đoạn mã sau vào ngay trên int rowIndex = 0;:

foreach ( var kiểu kẻ xâm lược trong kiểu kẻ xâm lược)
{
    rowCount += kẻ xâm lượcType.rowCount;
}
maxX = minX + 2f * xSpacing * cộtCount;
hiện tạiX = minX;
kẻ xâm lược = new Transform[rowCount, columnCount];

Mã này tính toán tổng số hàng và lưu trữ nó bên trong tệp rowCount. Sau đó, bạn tính toán maxXdựa trên tổng số cột và khoảng cách giữa mỗi kẻ xâm lược. Ban đầu, currentXđược đặt ở spawnStartPointvị trí ‘s X.

Bạn đã khai báo invadersmảng. Để điền nó, bạn sẽ cần thêm một dòng mã.

Dán dòng sau vào forvòng lặp trong cùng, ngay phía trên currentPos.x += xSpacing;:

kẻ xâm lược[rowIndex, j] = kẻ xâm lược.transform;

Dòng này chăm sóc dân số invaders.

Cuối cùng, ngay sau đó Start, dán:

 Cập nhật khoảng trống  riêng tư ()
{
    xIncrement = speedFactor * Time.deltaTime;
    nếu (isMovingRight)
    {
        currentX += xIncrement;
        nếu (currentX < maxX)
        {
            MoveInvaders(xIncrement, 0 );
        }
        khác 
        {
            Chuyển hướng();
        }
    }
    khác
    {
        hiện tạiX -= xIncrement;
        nếu (currentX > minX)
        {
            MoveInvaders(-xIncrement, 0 );
        }
        khác 
        {
            Chuyển hướng();
        }
    }
}

private  void  MoveInvaders ( float x, float y )
{
    cho ( int i = 0 ; i < rowCount; i++)
    {
        cho ( int j = 0 ; j < cộtCount; j++)
        {
            kẻ xâm lược[i, j].Translate(x, y, 0 );
        }
    }
}

private  void  ChangeDirection ()
{
    isMovingRight = !isMovingRight;
    MoveInvaders( 0 , -ySpacing);
}

Đây là một sự cố mã:

  • MoveInvaderschấp nhận hai giá trị float: xvà y. Nó di chuyển từng Biến đổi theo invaderscùng một giá trị dọc theo trục X và Y tương ứng.
  • ChangeDirectionchuyển đổi isMovingRightvà di chuyển đàn xuống theo ySpacingsố lượng.
  • Bên trong Update, bạn tính toán xIncrementvà cập nhật currentXdựa trên hướng của mọi khung hình.
  • Bạn dùng currentXđể kiểm tra xem vị trí swarm X có đang tiến đến ngưỡng hay không. Nếu có, bạn gọi ChangeDirection. Nếu không, bạn di chuyển đàn bằng cách sử dụng MoveInvaders.

Lưu tất cả mọi thứ. Quay trở lại Unity và nhấp vào Play . Bạn sẽ thấy lũ xâm lược đang di chuyển. Khi ở Chế độ chơi, hãy thử các giá trị khác nhau cho Hệ số tốc độ của Bầy đàn xâm lược và xem nó ảnh hưởng đến tốc độ của bầy đàn như thế nào.

Những kẻ xâm lược hiện đang di chuyển với tốc độ ngày càng nhanh qua rồi xuống màn hình.

Quân xâm lược đang di chuyển, nhưng chúng chưa bắn đạn. Bạn sẽ làm việc đó trong phần tiếp theo.

Khiến kẻ xâm lược bắn tia laze

Bạn sẽ sử dụng một biến thể của nhà lắp ghép Bullet cho quân xâm lược. Điều hướng đến RW/Prefabs và tìm EnemyBullet . Nó giống như Bullet , ngoại trừ các điểm sprite theo hướng Y ngược lại và lớp của nó được đặt thành Enemy .

Chọn EnemyBullet . Lưu ý Tốc độ của Bullet được đặt thành -200 . Điều này đảm bảo viên đạn di chuyển ngược hướng với viên đạn đại bác nhưng cùng độ lớn.

Cửa sổ Thanh tra cho nhà tiền chế EnemyBullet

Trong trò chơi, chỉ những kẻ xâm lược ở phía trước của bầy bắn đạn laze. Để đạt được điều này, bạn sẽ sử dụng bản cài sẵn BulletSpawner nằm trong RW/Prefabs .

Bạn sẽ khởi tạo nhiều trong số chúng bằng số lượng cột của kẻ xâm lược. Bạn cũng sẽ khiến những kẻ sinh ra đạn đi theo Kẻ xâm lược Biến hình ở phía trước bầy đàn.

Điều này sẽ đảm bảo rằng khi bắn, những viên đạn sẽ có vẻ như đến từ những kẻ xâm lược hàng đầu.

Trước khi bạn làm điều đó, bạn cần một cách để có được một kẻ xâm lược Chuyển đổi tại một hàng và cột cụ thể từ invadersmảng bên trong InvaderSwarm.

Mở tập lệnh InvaderSwarm.cs và thêm dòng sau vào sau InvaderTypephần khai báo cấu trúc:

 Phiên bản InvaderSwarm tĩnh bên trong ;

Điều này giúp biến InvaderSwarmthành một Singleton.

Sau đó dán đoạn sau vào ngay trên Start:

Biến đổi nội bộ GetInvader ( hàng int , cột int )
{
    nếu (hàng < 0 || cột < 0
        || hàng >= kẻ xâm lược.GetLength( 0 ) || cột >= kẻ xâm lược.GetLength( 1 ))
    {
        trả về  giá trị rỗng ;
    }

    trả lại kẻ xâm lược [hàng, cột];
}

 khoảng trống  riêng tư Tỉnh táo ()
{
    nếu (Trường hợp == null )
    {
        Ví dụ = cái này ;
    }
    khác  nếu (Trường hợp != this )
    {
        Phá hủy (gameObject);
    }
}

GetInvadertrả về kẻ xâm lược Biến đổi tại rowvà columnchỉ mục của kẻ xâm lược. Awakebiến nó InvaderSwarmthành Singleton bằng cách đảm bảo rằng khi trò chơi bắt đầu, chỉ một phiên bản của nó InvaderSwarmcòn sống.

Bây giờ, hãy chọn nhà lắp ghép BulletSpawner và xem Thanh tra. Lưu ý rằng nó có Bullet Spawner gắn liền với nó.

Ngoài ra còn có Kinematic Rigidbody 2D , Box Collider 2D và lớp được đặt thành Enemy . Bạn sẽ không thêm máy va chạm vào những kẻ xâm lược, mà sử dụng máy va chạm này để phát hiện các cú đánh từ đạn đại bác.

Cửa sổ Thanh tra cho BulletSpawner.

Trong trình chỉnh sửa mã của bạn, hãy mở tập lệnh BulletSpawner.cs được đính kèm với BulletSpawner và thêm phần sau vào bên trong lớp:

nội bộ  int currentRow;
cột int nội bộ  ;

[ SerializeField ]
 quay AudioClip riêng tư ;

[ SerializeField ]
 riêng GameObject bulletPrefab;

[ SerializeField ]
 Điểm sinh sản biến đổi riêng tư ;

[ SerializeField ]
 minTime float riêng ;

[ SerializeField ]
 thời gian maxTime riêng nổi  ;

 hẹn giờ nổi riêng ;
thời gian trôi nổi riêng tư  ;
chuyển đổi riêng tư theoTarget;

 Thiết lập khoảng trống  nội bộ ()
{
    currentTime = Random.Range(minTime, maxTime);
    followTarget = InvaderSwarm.Instance.GetInvader(currentRow, column);
}

 Cập nhật khoảng trống  riêng tư ()
{
    biến đổi.vị trí = theoTarget.vị trí;

    hẹn giờ += Time.deltaTime;
    nếu như (hẹn giờ <thời gian hiện tại)
    {
        trả lại ;
    }

    Khởi tạo(bulletPrefab, spawnPoint.position, Quaternion.identity);
    GameManager.Instance.PlaySfx(bắn súng);
    hẹn giờ = 0f ;
    currentTime = Random.Range(minTime, maxTime);
}

Đây là một sự cố mã:

  • currentTimeđại diện cho thời gian chờ cho đến khi bắn viên đạn tiếp theo. Nó được đặt thành một giá trị ngẫu nhiên giữa minTimevà maxTime.
  • currentRowvà columnliên kết một người tạo đạn với một kẻ xâm lược. Được columnđặt một lần và sẽ không thay đổi. Tuy nhiên, như bạn sẽ thấy ở phần sau, currentRowcác bản cập nhật nếu đạn của người chơi bắn trúng người sinh sản này.
  • Bên trong Setup(), bạn thiết lập followTargetbằng cách gọi GetInvadertừ InvaderSwarmthể hiện bằng cách sử dụng currentRowvà column. Bạn cũng đặt giá trị ban đầu thành currentTime.
  • Bên trong Update, bạn cập nhật vị trí của bộ sinh đạn để phù hợp với followTarget.position. Ngoài ra, bạn tăng cho timerđến khi nó đạt đến currentTime. Khi điều này xảy ra, bạn tạo một dấu đầu dòng spawnPoint.positiontrong khi phát shootinghiệu ứng âm thanh, sau đó đặt lại timervà currentTime.

Lưu tất cả mọi thứ. Quay trở lại Unity và mở BulletSpawner ở Prefab Mode . Đảm bảo các giá trị sau được đặt cho Bullet Spawner :

  • Bắn vào InvaderBullet đặt tại RW/Sounds .
  • Bullet Prefab to EnemyBullet đặt tại RW/Prefabs .
  • Điểm sinh sản đến Biến đổi SpawnPoint là con duy nhất của BulletSpawner .
  • Thời gian tối thiểu thành 1 và Thời gian tối đa thành 10 .

Thanh tra đang hiển thị tập lệnh Bullet Spawner.

Để sử dụng BulletSpawner , bạn cần quay lại tập lệnh InvaderSwarm.cs .

Đầu tiên, dán dòng sau vào cuối tất cả các khai báo biến:

[ SerializeField ]
 riêng BulletSpawner bulletSpawnerPrefab;

Sau đó, bên trong Start, thêm các dòng sau vào cuối:

cho ( int i = 0 ; i < cộtCount; i++)
{
    var bulletSpawner = Instantiate(bulletSpawnerPrefab);
    bulletSpawner.transform.SetParent(swarm.transform);
    đạnSpawner.column = i;
    bulletSpawner.currentRow = rowCount - 1 ;
    bulletSpawner.Setup();
}

Trong đoạn mã này, bạn tạo một bộ sinh đạn và thiết lập nó. Bạn khởi tạo bulletSpawnercho từng cột của bầy đàn và thiết lập cột đó columncurrentRowsau đó gọi Setupphương thức của nó. Bạn cũng cấp cha mẹ bulletSpawnercho Swarm để ngăn chặn sự lộn xộn trong Hệ thống phân cấp.

Lưu mọi thứ và quay lại Unity. Chọn Game Controller từ Hierarchy và đặt Bullet Spawner Prefab cho Invader Swarm thành BulletSpawner , nằm trong RW/Prefabs .

Lưu và chơi . Bây giờ bạn có những kẻ xâm lược bắn đạn vào người chơi.

Bầy hiện đang bắn đạn laze vào khẩu pháo.

Lưu ý rằng cả hai viên đạn đều biến mất khi viên đạn xâm lược và viên đạn đại bác va chạm. Viên đạn của kẻ xâm lược biến mất khi nó chạm vào khẩu đại bác và viên đạn của khẩu súng thần công biến mất khi nó chạm vào người tạo ra viên đạn. Chúng biến mất vì OnCollisionEnter2Dcác cuộc gọi DestroySelfbên trong Bullet.

Tuy nhiên, có một thứ còn thiếu, đó là các vụ nổ. :] Bạn sẽ thêm chúng vào tiếp theo.

Thêm vụ nổ

Điều hướng đến RW/Nhà lắp ghép . Chú ý nhà lắp ghép Explosion . Đó là một GameObject đơn giản với hoạt ảnh nhân vật được tạo sẵn mà bạn sẽ sử dụng cho hình ảnh vụ nổ.

Bây giờ, hãy mở lại GameManager.cs . Thêm phần sau sau khi khai báo sfx:

[ SerializeField ]
 GameObject riêng tư bùng nổPrefab;

[ SerializeField ]
 riêng nổi  floatTime = 1f ;

[ SerializeField ]
 AudioClip riêng tư ExplosionClip;

 khoảng trống  bên trong CreateExplosion ( Vị trí Vector2 )
{
    PlaySfx(clip vụ nổ);

    var nổ = Khởi tạo(vụ nổPrefab, vị trí,
        Quaternion.Euler( 0f , 0f , Random.Range( -180f , 180f )));
    Phá hủy (vụ nổ, thời gian nổ);
}

CreateExplosiontạo ra một vụ nổ với positionmột vòng quay ngẫu nhiên dọc theo trục Z và phá hủy nó sau explosionTimevài giây.

Để sử dụng CreateExplosion, hãy thêm dòng sau vào cuối bên DestroySelftrong Bulletlớp:

GameManager.Instance.CreateExplosion(transform.position);

Lưu tất cả. Quay lại Unity và chọn Trình điều khiển trò chơi từ Hệ thống phân cấp. Đối với bộ Trình quản lý trò chơi :

  • Explosion Prefab to Explosion nằm trong RW/Prefabs .
  • Explosion Clip to Explosion nằm trong RW/Sounds .

Thành phần Trình quản lý trò chơi trong cửa sổ Trình kiểm tra

Lưu cảnh và Phát . Bây giờ bạn có vụ nổ. :]

Bắn đạn bây giờ mang lại vụ nổ

Hiện tại, những viên đạn không ảnh hưởng đến quân xâm lược hoặc pháo. Trong các phần sau, bạn sẽ thêm điểm số và cuộc sống.

Thêm Điểm và Cuộc sống

Bạn có nhận thấy những nhãn UI siêu cổ điển đó trong chế độ xem trò chơi không? Ngay bây giờ họ chỉ là deadweight. Đã đến lúc bắt họ làm việc để có những mục tiêu và hậu quả mang lại ý nghĩa cho trò chơi này.

Thực hiện cuộc sống của người chơi

Mở GameManager.cs và thêm đoạn mã sau vào sau phần khai báo biến:

[ SerializeField ]
 private  int maxLives = 3 ;

[ SerializeField ]
 riêng Văn bản đời sốngLabel;

 cuộc sống riêng tư ;

nội bộ  void  UpdateLives ()
{
    cuộc sống = Mathf.Clamp(cuộc sống - 1 , 0 , maxLives);
    livesLabel.text = $"Lives: {lives} " ;
}

Gọi UpdateLivesgiảm livesbiến xuống một và cập nhật nhãn giao diện người dùng để phản ánh thay đổi. Hiện tại, không có gì xảy ra khi livesvề 0 nhưng bạn sẽ thay đổi điều đó sau.

Thêm phần sau vào cuối Awake:

cuộc sống = maxLives;
livesLabel.text = $"Lives: {lives} " ;

Mã này đặt giá trị mặc định cho livesvà cũng cập nhật nhãn giao diện người dùng.

Bây giờ, hãy mở CannonControl và dán các dòng sau vào sau phần khai báo biến:

[ SerializeField ]
 riêng  float respawnTime = 2f ;

[ SerializeField ]
 sprite SpriteRenderer riêng tư ;

[ SerializeField ]
 riêng Collider2D CannonCollider;

riêng Vector2 startPos;

private  void  Start () => startPos = transform.position;

Sau đó, thêm các dòng sau vào sau Update:

private  void  OnCollisionEnter2D ( Collision2D khác )
{
    GameManager.Instance.UpdateLives();
    StopAllCoroutines();
    StartCoroutine(Respawn());
}

System.Collections. Hồi sinh IEnumerator ()
{
    đã bật = sai ;
    CannonCollider.enabled = false ;
    ChangeSpriteAlpha( 0.0f );

    lợi nhuận  trả về  WaitForSeconds mới  ( 0,25f * respawnTime ) ;

    biến đổi. vị trí = startPos;
    đã bật = đúng ;
    ChangeSpriteAlpha( 0,25f );

    năng suất  trả về  WaitForSeconds mới  ( 0,75f * respawnTime ) ;

    ChangeSpriteAlpha( 1.0f );
    CannonCollider.enabled = true ;
}

private  void  ChangeSpriteAlpha ( giá trị float  )
{
    var color = sprite.color;
    color.a = giá trị ;
    sprite.color = màu;
}

Đây là những gì đang xảy ra:

  • ChangeSpriteAlphathay đổi độ mờ của sprite đại bác.
  • Khi một viên đạn bắn trúng khẩu đại bác, GameManager.UpdateLivestổng số mạng sẽ giảm xuống và Respawnquá trình điều tra bắt đầu.
  • Respawnđầu tiên vô hiệu hóa cannonCollidervà làm cho khẩu súng thần công trở nên vô hình. Sau một lúc, nó làm cho viên đạn pháo hơi trong suốt và đặt vị trí của khẩu pháo trở lại startPos. Cuối cùng, nó khôi phục độ mờ đục của sprite và kích hoạt lại máy va chạm.

Lưu mọi thứ và quay lại Unity. Chọn Bộ điều khiển trò chơi và đặt Nhãn trực tiếp của Trình quản lý trò chơi thành Văn bản trực tiếp , là phần tử con của Canvas .

Người kiểm tra cho người quản lý trò chơi

Đối với Điều khiển Cannon trên CANNON , đặt Sprite thành Sprite Renderer trên Sprite , một GameObject con của CANNON . Đặt Máy va chạm thành Máy va chạm hộp 2D trên CANNON .

Thanh tra cho thành phần Điều khiển Pháo

Bây giờ, lưu và chơi . Bạn sẽ thấy trình tự hồi sinh cũng như cập nhật mạng sống bất cứ khi nào một viên đạn bắn trúng khẩu pháo.

Pháo bây giờ mất mạng.

Những viên đạn dường như không ảnh hưởng đến những kẻ xâm lược. Bạn sẽ làm việc đó trong phần tiếp theo.

Thực hiện Điểm và Trò chơi kết thúc

Trước khi bạn làm bất cứ điều gì khác, hãy mở tập lệnh MusicControl.cs . Bạn muốn dừng nhạc khi trò chơi kết thúc, vì vậy hãy dán đoạn mã sau vào bên trong lớp:

[ SerializeField ]
 nguồn AudioSource riêng tư ;

nội  void  StopPlaying () => source.Stop();

StopPlayingdừng nguồn âm thanh khi được gọi.

Bây giờ, hãy mở tập lệnh GameManager.cs và thêm phần sau vào sau phần khai báo biến:

[ SerializeField ]
 nhạc MusicControl riêng tư ;

[ SerializeField ]
 Nhãn điểm văn bản riêng tư ;

[ SerializeField ]
 GameObject gameOver riêng tư ;

[ SerializeField ]
 GameObject riêng tư allClear;

[ SerializeField ]
 nút khởi động lại Nút riêng tư ;

 điểm int riêng ;

nội bộ  void  UpdateScore ( giá trị int  )
{
    điểm += giá trị ;
    scoreLabel.text = $"Điểm: {score} " ;
}

 khoảng trống  bên trong TriggerGameOver ( bool fail = true )
{
    gameOver.SetActive(thất bại);
    allClear.SetActive(!failure);
    restartButton.gameObject.SetActive( true );

    Thời gian.timeScale = 0f ;
    nhạc.StopPlaying();
}

Sau đó, dán các dòng sau vào cuối UpdateLives:

nếu (sống > 0 )
{
    trả lại ;
}

Kích hoạtGameOver();

Cuối cùng, thêm phần sau vào cuối Awake:

điểm = 0 ;
scoreLabel.text = $"Điểm: {score} " ;
gameOver.gameObject.SetActive( false );
allClear.gameObject.SetActive( false );

restartButton.onClick.AddListener(() =>
{
    SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    Thời gian.timeScale = 1f ;
});
restartButton.gameObject.SetActive( false );

Đây là những gì mã này làm:

  • allClearlưu trữ một tham chiếu đến bảng Xóa tất cả , hiển thị khi người chơi loại bỏ tất cả những kẻ xâm lược. gameOvertham khảo bảng Trò chơi kết thúc hiển thị khi người chơi hết mạng.
  • UpdateScoregia số scoređược valuetruyền cho nó và cập nhật nhãn giao diện người dùng để phản ánh các thay đổi.
  • TriggerGameOverhiển thị bảng Game Over nếu failuređúng. Nếu không, nó sẽ hiển thị bảng All Clear . Nó cũng cho phép restartButton, tạm dừng trò chơi và dừng nhạc.
  • Awakexử lý onClicksự kiện cho nút khởi động lại. Nó tải lại cảnh khi nhấp vào.

Mở InvaderSwarm.cs và thêm phần sau vào bên trong lớp sau phần khai báo biến:

riêng  int killCount;
riêng System.Collections.Generic.Dictionary< string , int > pointMap;

 khoảng trống  nội bộ TăngDeathCount ()
{
    killCount++;
    if (killCount >= những kẻ xâm lược. Chiều dài)
    {
        GameManager.Instance.TriggerGameOver( false );
        trả lại ;
    }
}

nội bộ  int  GetPoints ( string AlienName )
{
    nếu (pointMap.ContainsKey(tên người ngoài hành tinh))
    {
        trả lại điểmBản đồ [tên người ngoài hành tinh];
    }
    trả về  0 ;
}

Sau đó dán dòng sau ngay phía trên int rowIndex = 0;bên trong Start:

pointMap = new System.Collections.Generic.Dictionary< string , int >();

Bên dưới dòng ngay bên dưới var invaderName = invaderType.name.Trim();thêm vào như sau:

pointMap[InvaderName] = InvaderType.points;

Đây là một sự cố mã:

  • pointsMaplà một Từ điển (ánh xạ từ chuỗi thành số nguyên). Nó ánh xạ loại kẻ xâm lược namevới pointsgiá trị của nó.
  • IncreaseDeathCounttheo dõi và cập nhật killCountkhi người chơi loại bỏ kẻ xâm lược. Khi người chơi loại bỏ tất cả những kẻ xâm lược, TriggerGameOvernhận falsevà hiển thị bảng All Clear .
  • GetPointstrả về các điểm được liên kết với loại kẻ xâm lược bằng cách chuyển tên của nó làm khóa.

Cuối cùng, mở BulletSpawner.cs để xử lý phát hiện va chạm đối với những kẻ xâm lược. Dán đoạn sau ngay sau Update:

private  void  OnCollisionEnter2D ( Collision2D khác )
{
    nếu (!other.collider.GetComponent<Bullet>())
    {
        trả lại ;
    }

    GameManager.Instance.
        UpdateScore(InvaderSwarm.Instance.GetPoints(followTarget.gameObject.name));

    InvaderSwarm.Instance.IncreaseDeathCount();

    followTarget.GetComponentInChildren<SpriteRenderer>().enabled = false ;
    currentRow = currentRow - 1 ;
    nếu (currentRow < 0 )
    {
        gameObject.SetActive( false );
    }
    khác 
    {
        Cài đặt();
    }
}

Đây là những gì mã này làm:

  • OnCollisionEnter2Dquay lại mà không làm bất cứ điều gì nếu đối tượng bắn trúng viên đạn không phải là loại Bullet.
  • Nếu viên đạn đại bác bắn trúng người sinh sản, điểm số và số lần tiêu diệt sẽ cập nhật. Ngoài ra, followTargetTrình kết xuất Sprite của hiện tại sẽ tắt, sau đó cập nhật tệp currentRow.
  • Nếu không còn bất kỳ hàng nào, GameObject sẽ bị tắt. Nếu không, bạn gọi Setupđể cập nhật tệp followTarget.

Ồ! Đó là rất nhiều việc. Lưu mọi thứ và quay lại Unity để hoàn thành bước này.

Chọn Nhạc và đặt Nguồn điều khiển nhạc thành thành phần Nguồn âm thanh trên cùng một GameObject.

Trình kiểm tra thành phần Điều khiển nhạc

Sau đó, chọn Bộ điều khiển trò chơi . Đối với Trình quản lý trò chơi , hãy đặt:

  • Music to Music Kiểm soát âm nhạc .
  • Điểm Nhãn để Điểm Văn bản .
  • Game Over đến Game Over Panel .
  • Tất cả rõ ràng đến tất cả rõ ràng .
  • Nút khởi động lại để khởi động lại nút .

Trình kiểm tra hiển thị thành phần Trình quản lý trò chơi

Lưu và chơi . Bây giờ bạn có thể giết những kẻ xâm lược! Bật Gizmos trong Chế độ xem trò chơi và chọn Swarm để xem cách cập nhật những người sinh đạn.

Các viên đạn laze bây giờ đánh và loại bỏ những kẻ xâm lược.

Giết tất cả những kẻ xâm lược để xem All Clear , hoặc để mạng sống cạn kiệt để xem Game Over . Sau đó, bạn có thể sử dụng nút Khởi động lại để tải lại cảnh.

Bảng Game Over
Bảng điều khiển All Clear

Những kẻ xâm lược hơi chậm và có cùng tốc độ trong suốt. Trong phần tiếp theo, bạn sẽ cập nhật tốc độ của chúng theo nhịp điệu của âm nhạc.

Thêm âm thanh động đơn giản

Truy cập MusicControl.cs . Mở nó bên trong trình chỉnh sửa mã của bạn. Thêm dòng sau vào đầu lớp:

 phao chỉ đọc  riêng tư defaultTempo = 1.33f ;

Dòng này biểu thị nhịp mặc định của nhạc mỗi giây. Bạn có thể tính toán giá trị này bằng cách xem xét bản nhạc có bốn nhịp và dài ba giây.

Bây giờ, dán như sau ở trên StopPlaying:

[ SerializeField ]
 internal  int pitchChangeSteps = 5 ;

[ SerializeField ]
 float riêng  maxPitch = 5.25f ;

riêng  float pitchChange;

 nhịp độ float bên trong { get ; bộ riêng  ; }

Sau đó, thêm các dòng sau vào sau định nghĩa cho StopPlaying:

 void  nội bộ TăngPitch ()
{
    nếu như (source.pitch == maxPitch)
    {
        trở lại ;
    }

    source.pitch = Mathf.Clamp(source.pitch + pitchChange, 1 , maxPitch);
    Nhịp độ = Mathf.Pow( 2 , thay đổi độ cao) * Nhịp độ;
}

 khoảng trống  riêng Bắt đầu ()
{
    nguồn.pitch = 1f ;
    Nhịp độ = defaultTempo;
    pitchChange = maxPitch / pitchChangeSteps;
}

Đây là cách mã hoạt động:

  • Inside Startvà source.pitchđược Tempođặt thành giá trị mặc định của chúng.
  • IncreasePitchtăng cao độ của âm thanh nguồn theo một lượng được xác định bởi pitchChange, lần lượt là tỷ lệ của maxPitchvà pitchChangeStepsmaxPitchcũng đặt ra giới hạn trên cho sân cỏ.
  • Sau khi thay đổi cao độ, bạn có thể tính toán nhịp độ dựa trên công thức sau:

pitchchange = -log(2)(tempo1/tempo2) trong đó tempo1 biểu thị nhịp độ trước khi thay đổi và tempo2 biểu thị nhịp độ sau khi thay đổi.

Bây giờ hãy mở tập lệnh InvaderSwarm.cs và thêm phần sau vào cuối phần khai báo biến:

[ SerializeField ]
 MusicControl riêng MusicControl;

riêng  int tempKillCount;

Trong IncreaseDeathCount, dán các dòng sau vào cuối:

tempKillCount++;
nếu (tempKillCount < kẻ xâm lược. Độ dài / musicControl.pitchChangeSteps)
{
    trả lại ;
}

musicControl.IncreasePitch();
tempKillCount = 0 ;

Bây giờ IncreaseDeathCounttheo dõi biến tempKillCountđể kiểm tra xem nó có vượt quá invaders.Length / musicControl.pitchChangeSteps. Nếu có, nó sẽ gọi IncreasePitchvà tempKillCountđặt lại.

Điều này có nghĩa là khi người chơi loại bỏ hầu hết invaders.Length / musicControl.pitchChangeStepsnhững kẻ xâm lược, cả cường độ âm thanh và nhịp độ đều tăng. Biến Tempobên trong MusicControltheo dõi nhịp độ được cập nhật.

Cuối cùng, bên trong Update, thay thế xIncrement = speedFactor * Time.deltaTime;bằng:

xIncrement = speedFactor * musicControl.Tempo * Time.deltaTime;

Dòng này đảm bảo xem xIncrementxét nhịp độ âm nhạc và những kẻ xâm lược di chuyển nhanh hơn khi âm nhạc nhanh hơn khi người chơi loại bỏ ngày càng nhiều kẻ xâm lược.

Lưu tất cả mọi thứ. Quay lại Unity và chọn Game Controller . Đặt Invader Swarm ‘s Music Control thành Music .

Lưu và chơi .

Thanh tra hiển thị thành phần Invader Swarm

Hãy thử bắn hạ những kẻ xâm lược. Bạn sẽ nhận thấy chúng bắt đầu di chuyển nhanh hơn.

Những kẻ xâm lược bị bắn, và đàn di chuyển với tốc độ ngày càng tăng.

Vẫn còn một vấn đề nhỏ: Nếu bạn bỏ lỡ bất kỳ kẻ xâm lược nào, chúng sẽ tiếp tục di chuyển khi đến cuối màn hình. Sẽ tốt hơn nếu kích hoạt Trò chơi kết thúc nếu đàn chạm đến đáy.

Để thực hiện việc này, hãy mở InvaderSwarm.cs và thêm phần sau vào cuối phần khai báo biến:

[ SerializeField ]
 riêng Chuyển đổi CannonPosition;

 phao riêng minY;
phao riêng  hiện tạiY;

Sau đó, dán các dòng sau vào đầu Start:

currentY = spawnStartPoint.position.y;
minY = CannonPosition.position.y;

Sau đó thêm phần sau vào cuối ChangeDirection:

hiện tạiY -= ySpacing;
nếu (hiện tạiY < minY)
{
    GameManager.Instance.TriggerGameOver();
}

Đây là những gì mã này làm:

  • Bên trong Start, bạn đặt minYở vị trí Y của pháo và currentYở vị trí Y của spawnStartPoint.
  • Bất cứ khi nào được gọi, nó ChangeDirectionsẽ giảm dần currentYcho đến khi nó nhỏ hơn minY, lúc đó trò chơi kết thúc và hiển thị Game Over .

Lưu tất cả mọi thứ. Quay lại Unity và chọn Game Controller . Đặt Cannon Vị trí của Invader Swarm thành Transform của CANNON .

Cửa sổ Trình kiểm tra hiển thị thành phần Invader Swarm

Lưu và chơi . Bây giờ, bạn sẽ thấy bảng Trò chơi kết thúc được kích hoạt nếu đàn đi xuống dưới vị trí của khẩu đại bác.

Bảng Trò chơi kết thúc hiển thị sau khi quân xâm lược đến bên dưới vị trí của khẩu đại bác.

Và bạn đã hoàn tất!

Đi đâu từ đây?

Bạn có thể sử dụng nút Tải xuống Tài liệu ở đầu và cuối hướng dẫn này để tải xuống cả dự án khởi đầu và dự án cuối cùng.

Bạn có thể nhận thấy rằng bạn đã không thêm bất kỳ ngọn đuốc nào. Hãy thử thêm chúng như một thử thách.

Tất cả mọi thứ bạn cần đã có sẵn. Bạn có thể cần kiểm tra mã bên trong TorchkasManager và tập lệnh Torchka . Nếu bạn gặp khó khăn, hãy xem Dự án cuối cùng để biết giải pháp. Chúc may mắn!

Toàn bộ trò chơi, với Torchkas!

Cảm ơn đã dành thời gian để đọc bài viết này. Tôi hy vọng bạn đã vui vẻ và học được điều gì đó mới. Xin vui lòng tham gia diễn đàn dưới đây cho bất kỳ câu hỏi hoặc ý kiến.

Đặc biệt cảm ơn người dùng opengameart jlunesc vì một số tài sản CC-BY được sử dụng trong dự án.

About admin

Leave a Reply

Your email address will not be published. Required fields are marked *

Translate »