Tái sử dụng con đường
Bài học 7 trên 21 trong khóa học Trò chơi Unity: đường đua trên trời của Coddy.
Bảy đoạn tạo thành 140 đơn vị đường. Với tốc độ 10 đơn vị mỗi giây, đường sẽ hết sau 14 giây. Tạo một đoạn mới mỗi khi cần rồi xóa các đoạn cũ cũng được, nhưng có cách tiết kiệm hơn: chuyển đoạn đường đã chạy qua ra phía trước để dùng lại.
Một đoạn đường nằm hoàn toàn phía sau khi điểm giữa của nó vượt qua -chunkLength. Có bảy đoạn xếp thành một hàng, vậy nên di chuyển đoạn đó về phía trước bảy lần chiều dài sẽ đưa nó đến ngay sau đoạn cuối cùng:
if (chunk.position.z < -chunkLength)
{
chunk.position += Vector3.forward * chunkLength * chunks.Count;
}Việc dùng lại đối tượng thay vì xóa rồi tạo đối tượng mới gọi là pooling. Bảy đoạn đường tạo thành con đường bất tận.
Thử thách
DễTái sử dụng mỗi đoạn đường khi nó chạy qua phía sau nhân vật chạy.
- Trong
Road.Update, sau khi một đoạn di chuyển, hãy kiểm tra xemchunk.position.z < -chunkLengthhay không. - Nếu có, hãy di chuyển đoạn đó về phía trước một khoảng bằng
chunkLength * chunks.Count, như trên.
Nhấn Chơi và chờ 15 giây: đường chạy không bao giờ hết. Sau đó nhấn Kiểm tra.
Tự làm thử
using UnityEngine;
public class Runner : MonoBehaviour
{
public float laneWidth = 2.5f;
public float laneSpeed = 16f;
public float jumpHeight = 1.6f;
public float gravity = -40f;
public float slideTime = 0.7f;
public int lane;
private CharacterController controller;
private float fallSpeed;
private float slide;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow)) lane = Mathf.Max(-1, lane - 1);
if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow)) lane = Mathf.Min(1, lane + 1);
bool jump = Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Space);
if (jump && controller.isGrounded)
{
fallSpeed = Mathf.Sqrt(jumpHeight * -2f * gravity);
StopSlide();
}
if ((Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.DownArrow)) && controller.isGrounded)
{
slide = slideTime;
Resize(0.5f);
}
if (slide > 0f)
{
slide -= Time.deltaTime;
if (slide <= 0f) StopSlide();
}
if (controller.isGrounded && fallSpeed < 0f) fallSpeed = -2f;
fallSpeed += gravity * Time.deltaTime;
float targetX = lane * laneWidth;
float x = Mathf.MoveTowards(transform.position.x, targetX, laneSpeed * Time.deltaTime);
Vector3 move = new Vector3(x - transform.position.x, fallSpeed * Time.deltaTime, 0f);
controller.Move(move);
}
void StopSlide()
{
if (transform.localScale.y < 1f) Resize(1f);
slide = 0f;
}
void Resize(float height)
{
controller.enabled = false;
transform.position += Vector3.up * (height - transform.localScale.y);
transform.localScale = new Vector3(1f, height, 1f);
controller.enabled = true;
}
}
Tất cả bài học trong Trò chơi Unity: đường đua trên trời
Tự luyện tập: Playground Unity