nội dung
Hướng dẫn về Unity: Cách tạo một trò chơi giống như Space Invaders
40 phút
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.
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!
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.
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ù .
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.
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.
Â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.
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.
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 theospeed * Time.deltaTime
từ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 .
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à nó 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 theospeed * Time.deltaTime
mọi khung về phía trên cùng. - Dùng
DestroySelf
để phá viên đạn GameObject. Trước khi gọiDestroy
, 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. Awake
gọiDestroySelf
để tự động phá hủy viên đạn saulifetime
vài giây.DestroySelf
cũ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 GameManager
thà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, PlaySfx
chấ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 shootTimer
từ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 shootTimer
và khởi tạo bulletPrefab
tại muzzle.position
. Nó cũng phát shooting
hiệu ứng âm thanh bằng cách sử dụng PlaySfx
bê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 .
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 .
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 .
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 .
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 vì đó 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
sprites
lư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. rowCount
là số hàng mà loại kẻ xâm lược sẽ có trong bầy.name
lưu trữ tên loại cho kẻ xâm lược vàpoints
lư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ã:
- Mã này thiết lập
minX
bên trongStart
. Sau đó, nó tạo một GameObject trống có tên Swarm . xSpacing
vàySpacing
cập nhậtcurrentPos
dọc theo trục X và Y tương ứng.currentPos.x
gia 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.y
giảm dần.- Lặp lại các thành viên của
invaderTypes
, đối với mỗi thành viêninvaderType
, bạn lặp lại theo hàng để tạo các GameObject kẻ xâm lược riêng lẻ tạicurrentPos
vị trí đó. xSpacing
vàySpacing
cập nhậtcurrentPos
dọc theo trục X và Y tương ứng.- 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ộtSimpleAnimator
thành phần và gán mảng sprite của nó cho thành phầnsprites
được liên kết vớiinvaderType
. - Cuối cùng, kẻ xâm lược trở thành con của
Swarm
và vị trí của nó được đặt thànhcurrentPos
.
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ờ:
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.
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:
speedFactor
bâ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.invaders
lưu trữ các Biến đổi của tất cả các GameObject kẻ xâm lược đã tạo.rowCount
lưu trữ tổng số hàng của bầy đàn.isMovingRight
đại diện cho hướng di chuyển và được đặttrue
theo mặc định.maxX
là 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.xIncrement
là 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 maxX
dự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 ở spawnStartPoint
vị trí ‘s X.
Bạn đã khai báo invaders
mảng. Để điền nó, bạn sẽ cần thêm một dòng mã.
Dán dòng sau vào for
vò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ã:
MoveInvaders
chấp nhận hai giá trị float:x
vày
. Nó di chuyển từng Biến đổi theoinvaders
cùng một giá trị dọc theo trục X và Y tương ứng.ChangeDirection
chuyển đổiisMovingRight
và di chuyển đàn xuống theoySpacing
số lượng.- Bên trong
Update
, bạn tính toánxIncrement
và cập nhậtcurrentX
dự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ọiChangeDirection
. Nếu không, bạn di chuyển đàn bằng cách sử dụngMoveInvaders
.
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.
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.
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ừ invaders
mảng bên trong InvaderSwarm
.
Mở tập lệnh InvaderSwarm.cs và thêm dòng sau vào sau InvaderType
phầ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 InvaderSwarm
thà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);
}
}
GetInvader
trả về kẻ xâm lược Biến đổi tại row
và column
chỉ mục của kẻ xâm lược. Awake
biến nó InvaderSwarm
thà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ó InvaderSwarm
cò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.
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ữaminTime
vàmaxTime
.currentRow
vàcolumn
liên kết một người tạo đạn với một kẻ xâm lược. Đượccolumn
đặt một lần và sẽ không thay đổi. Tuy nhiên, như bạn sẽ thấy ở phần sau,currentRow
cá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ậpfollowTarget
bằng cách gọiGetInvader
từInvaderSwarm
thể hiện bằng cách sử dụngcurrentRow
vàcolumn
. Bạn cũng đặt giá trị ban đầu thànhcurrentTime
. - Bên trong
Update
, bạn cập nhật vị trí của bộ sinh đạn để phù hợp vớifollowTarget.position
. Ngoài ra, bạn tăng chotimer
đến khi nó đạt đếncurrentTime
. Khi điều này xảy ra, bạn tạo một dấu đầu dòngspawnPoint.position
trong khi phátshooting
hiệu ứng âm thanh, sau đó đặt lạitimer
và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 .
Để 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 bulletSpawner
cho từng cột của bầy đàn và thiết lập cột đó column
, currentRow
sau đó gọi Setup
phương thức của nó. Bạn cũng cấp cha mẹ bulletSpawner
cho 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.
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ì OnCollisionEnter2D
các cuộc gọi DestroySelf
bê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ổ);
}
CreateExplosion
tạo ra một vụ nổ với position
một vòng quay ngẫu nhiên dọc theo trục Z và phá hủy nó sau explosionTime
vài giây.
Để sử dụng CreateExplosion
, hãy thêm dòng sau vào cuối bên DestroySelf
trong Bullet
lớ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 .
Lưu cảnh và Phát . Bây giờ bạn có 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 UpdateLives
giảm lives
biế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 lives
về 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 lives
và 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:
ChangeSpriteAlpha
thay đổi độ mờ của sprite đại bác.- Khi một viên đạn bắn trúng khẩu đại bác,
GameManager.UpdateLives
tổng số mạng sẽ giảm xuống vàRespawn
quá trình điều tra bắt đầu. Respawn
đầu tiên vô hiệu hóacannonCollider
và 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ạistartPos
. 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 .
Đố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 .
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.
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();
StopPlaying
dừ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:
allClear
lư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.gameOver
tham khảo bảng Trò chơi kết thúc hiển thị khi người chơi hết mạng.UpdateScore
gia sốscore
đượcvalue
truyền cho nó và cập nhật nhãn giao diện người dùng để phản ánh các thay đổi.TriggerGameOver
hiển thị bảng Game Over nếufailure
đúng. Nếu không, nó sẽ hiển thị bảng All Clear . Nó cũng cho phéprestartButton
, tạm dừng trò chơi và dừng nhạc.Awake
xử lýonClick
sự 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ã:
pointsMap
là một Từ điển (ánh xạ từ chuỗi thành số nguyên). Nó ánh xạ loại kẻ xâm lượcname
vớipoints
giá trị của nó.IncreaseDeathCount
theo dõi và cập nhậtkillCount
khi 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,TriggerGameOver
nhậnfalse
và hiển thị bảng All Clear .GetPoints
trả 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:
OnCollisionEnter2D
quay 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ạiBullet
.- 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,
followTarget
Trình kết xuất Sprite của hiện tại sẽ tắt, sau đó cập nhật tệpcurrentRow
. - 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ệpfollowTarget
.
Ồ! Đó 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.
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 .
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.
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.
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
Start
vàsource.pitch
đượcTempo
đặt thành giá trị mặc định của chúng. IncreasePitch
tăng cao độ của âm thanh nguồn theo một lượng được xác định bởipitchChange
, lần lượt là tỷ lệ củamaxPitch
vàpitchChangeSteps
.maxPitch
cũ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:
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ờ IncreaseDeathCount
theo 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 IncreasePitch
và 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.pitchChangeSteps
những kẻ xâm lược, cả cường độ âm thanh và nhịp độ đều tăng. Biến Tempo
bên trong MusicControl
theo 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 xIncrement
xé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 .
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.
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 đặtminY
ở vị trí Y của pháo vàcurrentY
ở vị trí Y củaspawnStartPoint
. - Bất cứ khi nào được gọi, nó
ChangeDirection
sẽ giảm dầncurrentY
cho đến khi nó nhỏ hơnminY
, 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 .
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.
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!
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.