Khi tiếp nhận và xử lý các sự kiện thu được, đôi lúc cần 1 khoảng thời gian chờ giữa việc nhận được sự kiện và xử lý sự kiện. Khi cần 1 hiệu ứng zoom camera thật đẹp và mượt mà, sử dụng kỹ thuật điều chỉnh size và nghỉ liên tục thành 1 vòng lặp. Độ chênh lệch kích thước camera và thời gian nghỉ là vừa đủ cho người dùng có trải nghiệm tốt nhất.
Ngoài ra còn khá nhiều những trường hợp cụ thể khác trong game mà cần delay lại trước khi thực hiện hành động. Tất cả những trường hợp đó, Unity đã hỗ trợ hiện thực lại bằng các Coroutine. Vậy Coroutine là gì và sử dụng nó trong Unity ra sao ?
Coroutine là gì
Khi thực thi 1 hàm, hàm đó sẽ được xử lý hoàn toàn trước khi trả về 1 giá trị. Điều đó có nghĩa là dù hàm có phức tạp đến mấy cũng sẽ được xử lý trong duy nhất 1 vòng lặp của chương trình. Do đó, các hàm dạng này không thể được sử dụng để xử lý các hiệu ứng, animation hoặc các sự kiện diễn ra trong nhiều thời gian.
Coroutine là 1 thành phần của chương trình máy tính giúp tạo ra các tiến trình con độc lập, bằng cách cho phép tại 1 vị trí có thể có nhiều entry point hoạt động trong cùng thời điểm. Trong Unity, Coroutine được sử dụng để bắt đầu 1 tiến trình độc lập với hàm Update
và được gọi 1 lần duy nhất. Unity sẽ tự động quản lý tiến trình này cho đến khi nó kết thúc và được giải phóng.
Từ khoá yield
Từ khoá yield
được ứng dụng nhiều trong các ngôn ngữ lập trình. yield
là 1 tín hiệu để báo hiệu cho trình biên dịch biết đoạn code hay hàm chứa nó chính là 1 khối lặp, mặc dù không sử dụng các cú pháp thông thường đã biết. yield
sẽ kết hợp với return
, cho phép trả về các giá trị của khối lặp đó, đồng thời có thể quay trở lại khối lặp trong những lần lặp tiếp theo.
yield return
sẽ không kết thúc phương thức chứa nó mà vẫn tiếp tục chạy cho đến khi thực thi xong lệnh cuối cùng của khối lặp.
Muốn kết thúc phương thức, sử dụng yield break
. Phương thức chứa yield
có kiểu trả về là IEnumerator
, được sử dụng nhằm tạo ra 1 Coroutine.
WaitForSeconds
WaitForSeconds
là 1 phương thức của Unity có chức năng trì hoãn 1 Coroutine với 1 khoảng thời gian tính bằng giây. WaitForSeconds
được sử dụng duy nhất với từ khoá yield
.
Sử dụng Coroutine trong Unity
Dùng phương thức StartCoroutine
để bắt đầu 1 coroutine trong Unity. Nguyên mẫu của hàm như sau:
public Coroutine StartCoroutine(IEnumerator routine);
Tham số nhận vào là 1 IEnumerator
, giá trị trả về của 1 hàm IEnumerator
. Trong Unity, có thể có nhiều Coroutine hoạt động đồng thời trong cùng 1 thời gian. Ngoài ra, cũng có thể truyền trực tiếp tên hàm IEnumerator
vào hàm dưới dạng chuỗi.
Ví dụ đơn giản dưới đây sẽ giúp hiểu được mục đích của việc sử dụng Coroutine và ứng dụng trong Unity:
void Start() { Debug.Log("Starting " + Time.time); StartCoroutine(PrintfAfter(2.0f)); } IEnumerator PrintfAfter(float seconds) { yield return new WaitForSeconds(seconds); Debug.Log("Done " + Time.time); }
Hàm PrintfAfter
có kiểu trả về là IEnumerator
.
Dòng số 9, cặp từ khoá yield return, kết hợp với WaitForSeconds
sẽ dừng hàm và bỏ qua dòng lệnh số 10 cho đến khi khoảng thời gian đã trôi qua hết.
Khi đó dòng lệnh số 10 mới được thực thi và hàm sẽ thật sự kết thúc và được giải phóng.
Dưới đây là 1 số ví dụ:
Disable
đối tượng khi không còn sử dụng nữa. Đối tượng sẽ được đưa ra khỏi game và sẵn sàng được kích hoạt lại mà không cần khởi tạo mới:
void Update () { if (m_state == State.DEATH) { StartCoroutine(InactiveAfter(1f)); } } IEnumerator InactiveAfter(float seconds) { yield return new WaitForSeconds(seconds); GetComponent<Renderer>().enabled = false; GetComponent<Collider2D>().enabled = false; GetComponent<Rigidbody2D>().isKinematic = true; }
- Giải phóng đối tượng sau một khoảng thời gian:
void Update () { if (!GetComponent<Health>().m_isAlive) StartCoroutine(DestroyAfter(0.5f)); } IEnumerator DestroyAfter(float seconds) { yield return new WaitForSeconds(seconds); Score.m_score += 500; DoScoreEffect(); Destroy(gameObject); }
Đoạn code sử dụng hiệu ứng và 1 số thao tác khác trước khi giải phóng đối tượng nên không thể sử dụng hàm Destroy
với tham số thời gian delay. Coroutine là cách hiện thực đơn giản nhất trong trường hợp này.