- vừa được xem lúc

Coroutine trong Unity là gì? Có liên quan tới Threads hay không?

0 0 11

Người đăng: Phuong Le

Theo Viblo Asia

Phuongne, Th11 17, 2019

Sơ qua một chút về Coroutine và StartCoroutine(..)

Chính xác, đúng như các bạn nghĩ, Coroutine KHÔNG phải là Threads.

Okay, đa phần chúng ta đã biết về tác dụng “thần kỳ” của Coroutine như:

  • Thực thi câu lệnh một cách tuần tự qua các frames, chờ một hoạt động khác hoàn thành trước mới tiếp tục thực thi.
  • Chạy các câu lệnh một cách “song song”.
  • Thực thi câu lệnh sau một khoảng trễ (delay).

Dưới đây là ví dụ nhỏ tạo animation fade (mờ đi) bằng Coroutine, nếu bạn tạo theo cách dưới, hiệu ứng sẽ được apply ngay lập tức trong 1 frame và bạn sẽ không thấy được animation

void Fade()
{ for (float ft = 1f; ft >= 0; ft -= 0.1f) { Color c = renderer.material.color; c.a = ft; renderer.material.color = c; }
} //src: Unity3d documents

Coroutine có thể coi là một function có khả năng pause, tạm dừng việc thực thi và trả quyền thực thi về lại cho Unity, sau đó lại có thể thực thi tiếp ở nơi mà nó tạm dừng. Ở ví dụ dưới đây, yield return null sẽ tạm dừng frame đang thực thi, và tiếp tục chạy ở frame tiếp theo.

IEnumerator Fade()
{ for (float ft = 1f; ft >= 0; ft -= 0.1f) { Color c = renderer.material.color; c.a = ft; renderer.material.color = c; yield return null; }
} //src: Unity3D documents

“Sao tui thấy Invoke cũng gọi được hàm sau một khoảng thời gian đấy, có gì khác nhau giữa 2 cách làm không?”

Có chứ, nếu không rõ về sự khác nhau thì có thể tham khảo ở bài viết này: So sánh nhẹ Coroutines và Invoke

“Vậy StartCoroutine() là gì?”

StartCoroutine đơn giản là cách để gọi một Coroutine thực thi, ví dụ ở trường hợp animation Fade: StartCoroutine(Fade())

Coroutine và Threads

Đầu tiên, chúng ta phải xác định rõ ràng, Coroutine không phải là Threads và không xử lý bất đồng bộ. Nói qua về Multithreading, trong một máy tính đa bộ xử lý (multiprocessor hoặc multicore processor), một thread này có thể chạy code song song với thread chính và các thread khác, thường xảy ra các vấn đề shared resources.

Với coroutine, đây không phải là một threads khác, mà nó được thực thi NGAY TRÊN thread chính của game, vì vậy không cần phải lo về vấn đề bất đồng bộ, locking… Vậy Coroutine là gì?
“Theo mình”, coroutine là một khối lệnh có thể được chia nhỏ và thực thi trên nhiều frames cho đến khi gặp exit point “}” hoặc “yield break”

Q: Vì sao Coroutine hoạt động được như vậy?

Các bạn vào IEnumerator & IEnumerable tham khảo nhé.

Main thread và Coroutine

Như mình nói ở trên thì Coroutine thực thi ở thread chính, vậy nó thực thi lúc nào?

Coroutine trong Thread chính

Nó sẽ được gọi thực thi tiếp bằng hàm MoveNext() ở 3 thời điểm, sau bước Update, sau Rendering, và sau Physics

  • Sau Update nếu sử dụng yield null, yield WaitForSeconds, yield WWW, yield StartCoroutine
  • Sau Rendering nếu sử dụng yield WaitForEndOfFrame
  • Sau các xử lý vật lý (Physics) khi sử dụng yield WaitForFixedUpdate

“Ai gọi thực thi tiếp bằng MoveNext()?”

Khi StartCoroutine, Coroutine sẽ được đưa vào stack của MonoBehaviour, tất nhiên sẽ được System gọi thực thi thông qua hàm MoveNext().

Tham khảo thêm ở ĐÂY

Sử dụng yield hợp lý

Trong 1 frame, Coroutine có thể được gọi MoveNext() từ 1-2 lần.

private void Start() { StartCoroutine(CorouTesting()); } IEnumerator CorouTesting() { Debug.Log("Start Coroutine"); while (true) { yield return new WaitForEndOfFrame(); Debug.Log("After yield WaitForEndOfFrame"); yield return null; Debug.Log("After yield null"); } } int i = 0; private void Update() { Debug.Log("Frame: " + ++i); }
}

Log của ví dụ trên

Nếu sử dụng yield WaitForFixedUpdate cũng vậy, trong một frame FixedUpdate có thể gọi nhiều lần.

Một số loại yield hay sử dụng:

  • yield WaitForSeconds: tiếp tục thực thi sao một khoảng thời gian, sau Update của frame đó.
  • yield WaitForFixedUpdate: tiếp tục thực thi sau tất cả FixedUpdate đã được thực thi.
  • yield WWW: thực thi sau khi WWW downloads hoàn tất.
  • yield StartCoroutine(…): thực thi sau khi coroutine trong hàm này hoàn thành trước.
  • Tự tạo một loại YieldInstruction implement từ CustomYieldInstruction
  • yield WaitForSecondsRealtime (timeScale luôn = 1), yield WaitUntil, yield WaitWhile…

Claims

Bài viết từ năm 2019, chỉ có giá trị tham khảo bạn nhé 😉

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tạo setting game trên inspector.

. Chào các bạn,. Hôm nay chúng ta sẽ cùng tạo 1 setting/config cho game trên inspector nhé. Câu trả lời đó là khi chúng ta cần 1 cái gì đó để thao tác trong editor, trực quan nhất, không cần sửa code để cập nhật dữ liệu.... Và hẳn các bạn cũng từng làm việc với những value trên inspector rồi, ví dụ

0 0 22

- vừa được xem lúc

Hướng dẫn đưa nhân vật từ Mixamo vào demo.

. Chào các bạn. Bài này chúng ta chỉ tìm hiểu cách để lấy model, animation về, setting sao cho nó chạy được trong Unity để làm demo là ngon rồi nhé . Bước 1: Đăng nhập. Hãy tạo tài khoản nếu các bạn chưa có.

0 0 25

- vừa được xem lúc

Cơ bản về Rigidbody trong Unity3D

Phuong Le at 31-10-2019 - phuongne. Bài viết từ 2019 nên chỉ có giá trị tham khảo bạn nhé . . Rigidbody là gì.

0 0 18

- vừa được xem lúc

Một số folder đặc biệt trong Unity

Phuong Le 2019 - phuongne. Bài viết từ 2019 nên chỉ có giá trị tham khảo bạn nhé .

0 0 15

- vừa được xem lúc

So sánh nhẹ Coroutine và Invoke

Phuongne - 31-10-2019. . Roài, đây sẽ là một bài viết ngắn nên mình đi vào chi tiết luôn, khởi mở đầu giới thiệu dài dòng nhá anh em. Coroutine với Invoke là gì.

0 0 17

- vừa được xem lúc

IEnumerator và IEnumerable

Phuongne, Th11 04, 2019. .

0 0 13