# Unity

# Unity Camera

# orthographicSize & aspect

[https://docs.unity3d.com/ScriptReference/Camera-orthographicSize.html](https://docs.unity3d.com/ScriptReference/Camera-orthographicSize.html)  
[](https://docs.unity3d.com/ScriptReference/Camera-aspect.html)[https://docs.unity3d.com/ScriptReference/Camera-aspect.html](https://docs.unity3d.com/ScriptReference/Camera-aspect.html)

<span style="white-space: pre-wrap;">public float </span>**`<strong class="editor-theme-bold editor-theme-code">orthographicSize</strong>`**;  
<span style="white-space: pre-wrap;">public float </span>**`<strong class="editor-theme-bold editor-theme-code">aspect</strong>`**;

### Mô tả

#### Camera.orthographicSize

<span style="white-space: pre-wrap;">Là </span>****1/2****<span style="white-space: pre-wrap;"> kích thước của camera khi ở chế độ </span>****orthographic****.

<span style="white-space: pre-wrap;">Thuộc tính </span>`<span class="editor-theme-code">orthographicSize</span>`<span style="white-space: pre-wrap;"> xác định độ lớn vùng nhìn thấy được của một orthographic Camera. Để chỉnh sửa </span>`<span class="editor-theme-code">orthographicSize</span>`<span style="white-space: pre-wrap;"> bạn phải set Camera projection thành orthorgraphic.</span>

****Chiều cao****<span style="white-space: pre-wrap;"> của vùng nhìn là (</span>`<span class="editor-theme-code">orthographicSize</span>`<span style="white-space: pre-wrap;"> \* 2). Unity tính chiều rộng của vùng nhìn bằng cách sử dụng orthorgraphicSize và tỷ lệ của Camera.</span>

<span style="white-space: pre-wrap;">Unity bỏ qua orthographicSize nếu camera không phải orthorgraphic. Thay vào đó hãy sử dụng </span>****fieldOfView****.

#### Camera.aspect

Là tỷ lệ khung hình (chiều rộng/chiều cao).

<span style="white-space: pre-wrap;">Mặc định tỷ lệ này tự động được tính dựa theo tỷ lệ màn hình. Ngay cả khi camera không render full màn hình. Nếu bạn thay đổi aspect của camera, giá trị này sẽ giữ nguyên cho đến khi bạn gọi </span>`<span class="editor-theme-code">camera.ResetAspect()</span>`. Camera.aspect sẽ được đặt lại thành tỷ lệ khung hình của màn hình.

### <span style="white-space: pre-wrap;">Giữ </span>`<span class="editor-theme-code">orthographicSize</span>`<span style="white-space: pre-wrap;"> theo chiều rộng màn hình.</span>

```c#
private Camera mainCamera;
private Vector2 referenceResolution = new Vector2(1080, 1920);

private void ResizeCamera()
{
    float screenWidth = Screen.width;
    float screenHeight = Screen.height;

    float baseHorizontalSize = mainCamera.orthographicSize * referenceResolution.x / referenceResolution.y;
    float size = baseHorizontalSize * screenHeight / screenWidth;

    mainCamera.orthographicSize = size;
}
```

# Unity Addressable Asset System

[Unity Addressable Asset System | Package Manager UI website (unity3d.com)](https://docs.unity3d.com/Packages/com.unity.addressables@0.8/manual/index.html)

Addressable Asset System cung cấp một cách đơn giản để load assets bằng “địa chỉ”. Nó xử lý các chi phí quản lý bằng cách đơn giản hóa việc tạo và triển khai các gói nội dung.  
Addressable Asset System sử dụng tải bất đồng bộ để hỗ trợ tải ứng dụng từ bất kỳ đâu với mọi collection. Dù đang sử dụng tham chiếu trực tiếp, asset bundles, hoặc Resources folders. Addressable Assets cung cấp một cách đơn giản và linh hoạt.

# Summary

### Asset là gì???

Asset là nội dung được sử dụng để tạo ra game hoặc ứng dụng. Asset có thể là prefab, texture, material, audio clip, animation…

### Địa chỉ là gì???

Địa chỉ xác định vị trí nơi mà cái gì đó “cư trú”. Ví dụ, khi gọi điện thoại, số điện thoại sẽ được xem như một địa chỉ. Cho dù bạn ở nhà, chỗ làm, Hà Nội hay Sài Gòn thì mọi người đều có thể kết nối với bạn qua số điện thoại.

### Addressable Asset là gì???

<span style="white-space: pre-wrap;">Khi một asset được đánh dấu là </span>`<span class="editor-theme-code">addressable</span>`, asset đó được gọi là addressable asset (nghe lú vl) và asset đó có thể được được gọi từ bất kỳ đâu. Dù cho addressable asset được đặt ở local hay trên network, hệ sẽ định vị và trả về asset đó. Bạn có thể load một addressable bằng địa chỉ của nó hoặc load nhiều addressable sử dụng một nhãn (label) của nhóm mà bạn khai báo.

### Tại sao phải quan tâm???

Cách truyền thống gây ra nhiều khó khăn trong việc cấu trúc asset và load chúng một cách hiệu quả.  
Sử dụng addressable assets rút ngắn thời gian cấu trúc cho phép bạn có nhiều thời gian hơn để thiết kế, lập trình, và kiểm thử ứng dụng. Với Addressable Assets bạn định danh assets bằng addressable và tải ló :))))

### Addressable Asset System giải quyết vấn đề gì???

- ****Thời gian lặp lại****: Tham chiếu đến nội dung bằng địa chỉ của nó là siêu hiệu quả. Với một địa chỉ được tham chiếu hệ thống chỉ việc truy xuất nó. Tối ưu hóa content mà không cần thay đổi code.
- ****Quản lý sự phụ thuộc****: Hệ thống không chỉ trả về nội dung theo địa chỉ mà còn trả về mọi sự phụ thuộc của nội dung đó. Hệ thống sẽ thông báo cho bạn khi nào nội dung sẵn sàng. Mọi meshes, shaders, animations… sẽ được tải trước khi nội dung được trả về.
- ****Quản lý bộ nhớ****: địa chỉ không chỉ load asset mà còn unload chúng. Tham chiếu tự động được tính toàn và một profiler mạnh mẽ sẽ cho bạn biết những vấn đề tiềm ẩn với bộ nhớ.
- ****Đóng gói nội dung****: Bởi vì hệ thống lập bản đồ và hiểu các chuỗi phụ thuộc phức tạp, nó cho phép đóng gói hiệu quả các gói ngay cả khi asset được thay đổi hoặc đổi tên. Asset có thể được chuẩn bị một cách dễ dàng cho cả triển khai cục bộ và từ xa để hỗ trợ nội dung có thể tải về (DLC) và giảm kích thước ứng dụng.

### Với những game có sẵn thì sao???

Addressable Asset cung cấp một lộ trình nâng cấp cho dù bạn đang sử dụng tham chiếu trực tiếp, Resources folder hoặc Asset Bundles.

# Overview

[Addressable Assets Overview | Package Manager UI website (unity3d.com)](https://docs.unity3d.com/Packages/com.unity.addressables@0.8/manual/AddressableAssetsOverview.html)

Addressable Assets bao gồm 3 gói:

- Addressable Assets (chính)
- Resource Manager
- Scriptalbe Build Pipeline

Resource Manager và Scriptable Build Pipeline sẽ tự động được cài đặt cùng Addressable Assets

### Khái niệm

- ****Address****<span style="white-space: pre-wrap;"> – Xác định một asset để dễ dàng truy xuất trong run-time.</span>
- ****AddressableAssetData directory****<span style="white-space: pre-wrap;"> – Lưu trữ metadata của addressable Asset trong thư mục Assets của dự án.</span>
- ****Asset Group****<span style="white-space: pre-wrap;"> – Một tập hợp addressable Assets sẵn sàng cho xử lý build-time.</span>
- ****Asset Group Schema****<span style="white-space: pre-wrap;"> – Khai báo một tập dữ liệu có thể gán cho một nhóm và sử dụng trong build.</span>
- ****AssetReference****<span style="white-space: pre-wrap;"> – Một đối tượng hoạt động như một tham chiếu trực tiếp, nhưng với khởi tạo hoãn lại (deferred initialization) (Ví dụ như lazy loading). AssetReference lưu trữ GUID dưới dạng địa chỉ mà bạn có thể load theo yêu cầu.</span>
- ****Asynchronous Loading****<span style="white-space: pre-wrap;"> – cho phép vị trí của Asset và các phụ thuộc (local, remote, generated) thay đổi trong suốt quá trình phát triển mà bạn không cần thay đổi code. Tải bất đồng bộ (async loading) là nền tảng của Addressable Asset System.</span>
- ****Build Script**** – chạy các Asset Group Processors để đóng gói Asset và cung cấp các ánh xạ giữa các địa chỉ (Address) và vị trí của tài nguyên (Resource Location) cho Resource Manager.
- ****Labal****<span style="white-space: pre-wrap;"> – cung cấp thêm một định danh cho addressable Asset để định danh các Asset tương tự nhau trong run-time. VD </span>`<span class="editor-theme-code">Addressables.DownloadDependenciesAsync("spaceHazards");</span>`

# Getting started

[Getting started with Addressable Assets | Package Manager UI website (unity3d.com)](https://docs.unity3d.com/Packages/com.unity.addressables@0.8/manual/AddressableAssetsGettingStarted.html)

### Yêu cầu

- Unity 2018.3 hoặc mới hơn.

### Đánh dấu asset là addressable

<span style="white-space: pre-wrap;">Có 2 cách để đánh dấu đối tượng là addressable asset. Khi package Addressable Assets được cài đặt bạn có thể đánh dấu một asset là addressable trong </span>****Inspector****<span style="white-space: pre-wrap;"> hoặc kéo thả vào cửa sổ </span>****Addressables****.

<span style="white-space: pre-wrap;">Trong cửa sổ </span>****Inspector****<span style="white-space: pre-wrap;"> của đối tượng. Chọn Address và nhập tên để định danh Asset.</span>![](https://docs.thanhdv.com/wp-content/uploads/2024/02/image.png)

<span style="white-space: pre-wrap;">Để mở </span>****Addressables****<span style="white-space: pre-wrap;"> chọn </span>****Window &gt; Asset Management &gt; Addressable Assets****.  
Kéo đối tượng từ folder Asset trong cửa sổ Project vào một nhóm trong tab Asset của cửa sổ Addressables.

![](https://docs.thanhdv.com/wp-content/uploads/2024/02/image-3.png)

<span style="white-space: pre-wrap;">Địa chỉ mặc định của asset là đường dẫn đến asset trong dự án. Ví dụ </span>**Assets/images/myImage.png**<span style="white-space: pre-wrap;">. Bạn có thể sử dụng </span>****Addressables****<span style="white-space: pre-wrap;"> để thay đổi địa chỉ thành bất kỳ tên unique nào.</span>

Để thay đổi địa chỉ, double click vào address của asset và nhập địa chỉ mới.

<span style="white-space: pre-wrap;">Trong lần đầu sử dụng Addressable Asset, hệ thống lưu lại một số dữ liệu asset edit-time và run-time cho project trong </span>`<span class="editor-theme-code">Assets/AddressableAssetsData</span>`<span style="white-space: pre-wrap;"> (nên được thêm vào version control).</span>

### Build Game

Addressables cần build nội dung của bạn vào file mà game có thể chạy trước khi bạn build game. Bước này không được thực hiện tự động. Bạn cần build nội dung thông qua UI hoặc API.

- UI: Mở Addressables. Chọn Build &gt; Build Player Content
- <span style="white-space: pre-wrap;">API: </span>`<span class="editor-theme-code">AddressableAssetSettings.BuildPlayerContent()</span>`

### Load hoặc Instantiate bằng địa chỉ

Bạn có thể Load hoặc Instantiate một asset trong run-time. Load một asset sẽ load toàn bộ các ràng buộc vào bộ nhớ (bao gồm cả dữ liệu Asset Bundle nếu có). Nó cho phép bạn sử dụng Asset khi cần. Instantiate tải asset và ngay lập tức thêm nó vào scene.

Truy cập một asset trong script sử dụng địa chỉ dạng string:  
Addressables.LoadAssetAsync&lt;GameObject&gt;(“AssetAddress”);  
hoặc  
Addressables.InstantiateAsync(“AssetAddress”);

**`<strong class="editor-theme-bold editor-theme-code">LoadAssetAsync</strong>`**<span style="white-space: pre-wrap;"> and </span>**`<strong class="editor-theme-bold editor-theme-code">InstantiateAsync</strong>`**<span style="white-space: pre-wrap;"> là xử lý bất đồng bộ. Bạn có thể gọi một callback để làm việc với asset ngay khi n được tải xong. Xem </span>[AsyncOperationHandle](https://docs.unity3d.com/Packages/com.unity.addressables@0.8/manual/AddressableAssetsAsyncOperationHandle)<span style="white-space: pre-wrap;"> để biết thêm về hoàn thành chờ.</span>

![](https://docs.thanhdv.com/wp-content/uploads/2024/02/image-4.png)

#### Sub-Assets và Component

Sub-Assets và Component là các trường hợp đặc biệt đáng để xem xét cho load asset.

- Component – bạn không thể load game object thông qua các component của nó. Bạn phải load/instantiate GameObject và sau đó lấy component bạn cần.
- <span style="white-space: pre-wrap;">Sub-Assets – Load sub-asset được hỗ trợ nhưng thông qua cú pháp đặc biệt. Ví dụ sub-asset là sprite trong sprite sheet hoặc animation clip trong một FBX. Cú pháp sẽ là: </span>`<span class="editor-theme-code">Addressables.LoadAssetAsync<IList<Sprite>>("MySpriteSheetAddress");</span>`

### Sử dụng AssetReference

****AssetReference**** cung cấp cơ chết để truy cập asset mà không cần đến địa chỉ dạng string.

Để truy cập Addressable Asset sử dụng AssetReference:

1. Chọn 1 asset.
2. Trong Inspector, thêm script bạn cần.
3. Trong script thêm`<span class="editor-theme-code"> public AssetReference assetReference;</span>`
4. Quay lại Inspector. Thêm asset vào script trên.

![](https://docs.thanhdv.com/wp-content/uploads/2024/02/image-8.png)

![](https://docs.thanhdv.com/wp-content/uploads/2024/02/image-6.png)

### Load Addressable Asset bằng object reference

Để load AssetReference bằng object reference:  
`<span class="editor-theme-code">AssetRefMember.LoadAssetAsync<GameObject>();</span>`  
Hoặc  
`<span class="editor-theme-code">AssetRefMember.InstantiateAsync(pos, rot);</span>`

**`<strong class="editor-theme-bold editor-theme-code">LoadAssetAsync</strong>`**<span style="white-space: pre-wrap;"> and </span>**`<strong class="editor-theme-bold editor-theme-code">InstantiateAsync</strong>`**<span style="white-space: pre-wrap;"> là xử lý bất đồng bộ. Bạn có thể gọi một callback để làm việc với asset ngay khi n được tải xong. Xem </span>[AsyncOperationHandle](https://docs.unity3d.com/Packages/com.unity.addressables@0.8/manual/AddressableAssetsAsyncOperationHandle)<span style="white-space: pre-wrap;"> để biết thêm về hoàn thành chờ.</span>

### Dữ liệu cục bộ trong StreamingAssets

<span style="white-space: pre-wrap;">Addressables cần một số file trong run-time để biết load cái gì và load như thế nào. File này được sinh ra khi build Addressable data và lưu trong folder </span>****StreamingAssets****<span style="white-space: pre-wrap;">. Đây mà một folder đặc biệt vì tất cả file trong thư mục này đều được thêm vào build. File không được thêm vào folder này ngay lập tức trong khi build. Thay vào đó chúng được lưu trong </span>****Library****. Khi build game file đươc chuyển qua để build xong đó bị xóa đi. Điều này được thực hiện để người dùng có thể build đa nền tảng. Nhưng yên tâm nó chỉ bao gồm những dữ liệu liên quan đến build đó.

<span style="white-space: pre-wrap;">Ngoài dữ liệu Addressables cụ thể, bất kỳ nhóm nào build dữ liệu để sử dụng local cũng sẽ sử dụng vị trí tổ chức sắp xếp cụ thể cho nền tảng của thư viện đó. Để đảm bảo điều này hoạt động, đường dẫn build game nên được đặt thành biến bắt đầu bằng </span>**`<strong class="editor-theme-bold editor-theme-code">[UnityEngine.AddressableAssets.Addressables.BuildPath]</strong>`**<span style="white-space: pre-wrap;"> và đường dẫn load nên bắt đầu bằng </span>**`<strong class="editor-theme-bold editor-theme-code">{UnityEngine.AddressableAssets.Addressables.RuntimePath}</strong>`**.****

### Tải xuống trước

Gọi phương thức`<span class="editor-theme-code"> Addressables.DownloadDependenciesAsync()</span>`<span style="white-space: pre-wrap;"> để load các phụ thuộc cho địa chỉ (address) hoặc nhãn (label). Tiêu biểu là asset bundle.</span>

<span style="white-space: pre-wrap;">Cấu trúc </span>`<span class="editor-theme-code">AsyncOperationHandle </span>`<span style="white-space: pre-wrap;">được trả về bao gồm cả thuộc tính </span>`<span class="editor-theme-code">PercentComplete</span>`<span style="white-space: pre-wrap;"> – có thể được sử dụng để hiển thị quá trình tải xuống. Bạn có thể sử dụng </span>`<span class="editor-theme-code">PercentComplete</span>`<span style="white-space: pre-wrap;"> để hiển thị thanh trạng thái và chờ đến khi nội dung được tải xong.</span>

<span style="white-space: pre-wrap;">Nếu bạn muốn hỏi người dùng có bằng lòng tải xuống hay không. Bạn có thể sử dụng </span>`<span class="editor-theme-code">Addressables.GetDownloadSize()</span>`. Nó sẽ cho bạn biết dung lượng dữ liệu cần tải xuống. Dung lượng này bao gồm tất cả các gói đã được tải về trước đó (kể cả khi gói đó vẫn được lưu trong cache).

Mặc dù việc tải xuống trước có thể có lợi. Nhưng trong nhiều trường hợp bạn có thể chọn không tải trước. Ví dụ:

- Ứng dụng bao gồm rất nhiều nội dung online, và người dùng thường chỉ tương tác với một phần nội dung đó.
- Bạn có một ứng dụng phải kết nối mạng để hoạt động. Ví dụ như game online. Nếu tất cả dữ liệu của ứng dụng nằm trong một gói nhỏ, bạn có thể chọn chờ và tải xuống khi cần.

<span style="white-space: pre-wrap;">Bạn cũng có thể chọn sử dụng một phần của chức năng này. Thay vì sử dụng </span>`<span class="editor-theme-code">PercentComplete</span>`<span style="white-space: pre-wrap;"> và chờ đến khi tải xong. Bạn có thể tải xuống sau đó tiếp tục ứng dụng. Bạn nên tạo màn hình chờ khi dữ liệu thực sự được tải xuống. Nếu không ứng dụng sẽ vẫn phải chờ cho đến khi tải xuống hoàn tất.</span>

### Build đa nền tảng

Khi build nội dung cho Addressable, Asset Bundles được tạo bao gồm Addressable Assets. Asset Bundles phụ thuộc vào nền tảng nên bạn sẽ cần build lại cho mỗi nền tảng mà bạn nhắm tới.

Mặc định, khi Addressable được build dữ liệu cho nền tảng sẽ được lưu vào các thư mục con của đường dẫn Addressable. Đường dẫn runtime sẽ tính đến các folder nền tảng này và trỏ đến dữ liệu được chỉ định.

****Chú ý****<span style="white-space: pre-wrap;">: Khi trong Play Mode trên Editor. Nếu sử dụng script </span>****Addressable Packed Play Mode****, Addressable sẽ tải dữ liệu cho nền tảng mục tiêu bạn đang chọn. Có nghĩa là nếu dữ liệu không tương thích với nền tảng mục tiêu trên editor thì rất có thể vẫn đề này cũng xảy ra trên thiết bị.

# MonoBehaviour và ScriptableObject

<table id="bkmrk-ti%C3%AAu-ch%C3%ADmonobehaviou"><colgroup><col></col><col></col><col></col></colgroup><tbody><tr style="height:10px;"><th>Tiêu chí

</th><th>****MonoBehaviour****</th><th>****ScriptableObject****</th></tr><tr><td>****Bản chất****

</td><td><span style="white-space:pre-wrap;">Component </span>****gắn lên GameObject****<span style="white-space:pre-wrap;"> trong Scene/Prefab</span>

</td><td>****Asset dữ liệu****<span style="white-space:pre-wrap;"> độc lập (không gắn GameObject)</span>

</td></tr><tr><td>****Vòng đời****

</td><td><span style="white-space:pre-wrap;">Theo GameObject: </span>`<span class="editor-theme-code">Awake</span>`<span style="white-space:pre-wrap;"> → </span>`<span class="editor-theme-code">OnEnable</span>`<span style="white-space:pre-wrap;"> → </span>`<span class="editor-theme-code">Start</span>`<span style="white-space:pre-wrap;"> → </span>`<span class="editor-theme-code">Update</span>`<span style="white-space:pre-wrap;">… → </span>`<span class="editor-theme-code">OnDisable</span>`/`<span class="editor-theme-code">OnDestroy</span>`

</td><td><span style="white-space:pre-wrap;">Theo Asset: tồn tại như file </span>`<span class="editor-theme-code">.asset</span>`; không có loop mặc định

</td></tr><tr><td>****Khởi tạo****

</td><td><span style="white-space:pre-wrap;">Tạo qua </span>`<span class="editor-theme-code">AddComponent<T>()</span>`<span style="white-space:pre-wrap;"> hoặc trên Prefab/Scene</span>

</td><td><span style="white-space:pre-wrap;">Tạo file bằng </span>****Create &gt; ScriptableObject****<span style="white-space:pre-wrap;"> hoặc </span>`<span class="editor-theme-code">CreateInstance<T>()</span>`

</td></tr><tr><td>****Chứa gì****

</td><td>****Logic/Hành vi****<span style="white-space:pre-wrap;"> + tham chiếu Component/Transform trong Scene</span>

</td><td>****Dữ liệu****; có thể chứa logic nhẹ (không phụ thuộc Scene)

</td></tr><tr><td>****Update loop****

</td><td>****Có****<span style="white-space:pre-wrap;"> (</span>`<span class="editor-theme-code">Update</span>`<span style="white-space:pre-wrap;">, </span>`<span class="editor-theme-code">FixedUpdate</span>`<span style="white-space:pre-wrap;">, </span>`<span class="editor-theme-code">LateUpdate</span>`…)

</td><td>****Không****

</td></tr><tr><td>****Serialization****

</td><td><span style="white-space:pre-wrap;">Serialize theo </span>****Scene/Prefab****

</td><td><span style="white-space:pre-wrap;">Serialize thành </span>****asset****<span style="white-space:pre-wrap;">; dễ </span>****chia sẻ giữa nhiều scene****

</td></tr><tr><td>****Tham chiếu Scene****

</td><td>Truy cập trực tiếp GameObject/Component

</td><td>****Không nên****<span style="white-space:pre-wrap;"> giữ tham chiếu trên scene (dễ null/leak); giữ </span>****data thuần****

</td></tr><tr><td>****Dùng lại/chia sẻ****

</td><td>Instance gắn với từng GameObject

</td><td>****Một asset dùng cho nhiều đối tượng/scene****<span style="white-space:pre-wrap;"> (data-driven)</span>

</td></tr><tr><td>****Bộ nhớ/GC****

</td><td>Tạo/hủy theo vòng đời object trong Scene

</td><td><span style="white-space:pre-wrap;">Ít cấp phát runtime; phù hợp </span>****giảm trùng lặp dữ liệu****

</td></tr><tr><td>****Use-case chính****

</td><td>Controller, behaviour, input, AI, UI view, spawn…

</td><td>Config, stat, item database, lookup table, event channel, state container

</td></tr><tr><td>****Làm việc trong Editor****

</td><td>Thường test trong Play Mode

</td><td><span style="white-space:pre-wrap;">Dễ chỉnh sửa/so sánh như </span>****asset****

</td></tr><tr><td>****Phụ thuộc****

</td><td>Phụ thuộc Scene/Prefab hierarchy

</td><td>****Độc lập****<span style="white-space:pre-wrap;"> với Scene; tốt cho </span>****DI/data pipeline****

</td></tr><tr><td>****Hạn chế****

</td><td>Khó chia sẻ state giữa nhiều scene nếu không singleton/DI

</td><td><span style="white-space:pre-wrap;">Không có lifecycle update; </span>****không****<span style="white-space:pre-wrap;"> tham chiếu scene trực tiếp</span>

</td></tr><tr><td>****Dùng khi****

</td><td>Cần logic chạy mỗi frame, tương tác thế giới

</td><td><span style="white-space:pre-wrap;">Cần </span>****dữ liệu chung/cấu hình****<span style="white-space:pre-wrap;"> tái sử dụng, tách data khỏi logic.</span>

</td></tr></tbody></table>

# Awake và Start

<table id="bkmrk-ti%C3%AAu-ch%C3%ADawake%28%29start"><colgroup><col style="width:130px;"></col><col></col><col></col></colgroup><tbody><tr><th>Tiêu chí

</th><th>****Awake()****</th><th>****Start()****</th></tr><tr><td>****Thời điểm gọi****

</td><td><span style="white-space:pre-wrap;">Ngay khi </span>****script được nạp/khởi tạo****<span style="white-space:pre-wrap;"> (khi scene load hoặc </span>`<span class="editor-theme-code">Instantiate</span>`<span style="white-space:pre-wrap;"> prefab)</span>

</td><td>****Khung hình đầu tiên****<span style="white-space:pre-wrap;"> khi component </span>****được enable****<span style="white-space:pre-wrap;"> sau </span>`<span class="editor-theme-code">Awake</span>`/`<span class="editor-theme-code">OnEnable</span>`

</td></tr><tr><td>****Yêu cầu enable****

</td><td><span style="white-space:pre-wrap;">Gọi </span>****dù component bị Disable****

</td><td><span style="white-space:pre-wrap;">Chỉ gọi khi </span>****component Enable****

</td></tr><tr><td>****Mục đích chính****

</td><td><span style="white-space:pre-wrap;">Khởi tạo </span>****nội bộ****<span style="white-space:pre-wrap;">: tạo dữ liệu, tìm &amp; cache reference trong </span>****cùng GameObject****

</td><td><span style="white-space:pre-wrap;">Khởi tạo </span>****phụ thuộc ngoại****<span style="white-space:pre-wrap;">: cần đảm bảo </span>****các đối tượng khác đã Awake xong****

</td></tr><tr><td>****Thứ tự giữa các object****

</td><td>****Không đảm bảo****<span style="white-space:pre-wrap;"> thứ tự Awake giữa các object khác nhau</span>

</td><td>****Không đảm bảo****<span style="white-space:pre-wrap;"> thứ tự Start giữa các object khác nhau</span>

</td></tr><tr><td>****Gọi lại khi Instantiate****

</td><td><span style="white-space:pre-wrap;">Có (mỗi lần </span>`<span class="editor-theme-code">Instantiate</span>`)

</td><td>Có (khi instance được enable và tới frame đầu)

</td></tr><tr><td>****Best practice****

</td><td>Cache component (`<span class="editor-theme-code">GetComponent</span>`), set giá trị mặc định, đăng ký dịch vụ/DI

</td><td>Kết nối hệ thống khác, subscribe event ngoài, logic cần đảm bảo đối tượng khác đã sẵn sàng

</td></tr><tr><td>****Lưu ý****

</td><td>Gọi API phụ thuộc đối tượng khác chưa sẵn sàng

</td><td><span style="white-space:pre-wrap;">Công việc nặng mỗi frame; tránh dùng nếu chỉ cần ở </span>

`<span class="editor-theme-code">Awake</span>`

</td></tr></tbody></table>

# MonoBehaviour Life Circle

<div drawio-diagram="102"><img src="https://knowledge.thanhdv.com/uploads/images/drawio/2025-10/drawing-1-1760560775.png" alt="drawing-1-1760560775.png"/></div>

# FixedUpdate, Update và LateUpdate

<table id="bkmrk-ti%C3%AAu-ch%C3%ADfixedupdate%28"><colgroup><col style="width:120px;"></col><col></col><col></col><col></col></colgroup><tbody><tr><th>Tiêu chí

</th><th>****FixedUpdate()****</th><th>****Update()****</th><th>****LateUpdate()****</th></tr><tr><td>****Thời điểm gọi****

</td><td><span style="white-space:pre-wrap;">Theo </span>****nhịp cố định****<span style="white-space:pre-wrap;"> của physics (mặc định 0.02s)</span>

</td><td>****Mỗi khung hình****<span style="white-space:pre-wrap;"> (phụ thuộc FPS)</span>

</td><td>****Sau mọi** `<strong class="editor-theme-bold editor-theme-code">Update()</strong>`**<span style="white-space:pre-wrap;"> trong cùng frame</span>

</td></tr><tr><td>****Tần suất****

</td><td><span style="white-space:pre-wrap;">Có thể chạy </span>****0, 1, hoặc nhiều lần****<span style="white-space:pre-wrap;"> trong một frame để “đuổi kịp” thời gian vật lý</span>

</td><td>1 lần/frame

</td><td><span style="white-space:pre-wrap;">1 lần/frame, </span>****sau**** `<span class="editor-theme-code">Update()</span>`

</td></tr><tr><td>****delta time dùng****

</td><td>`<span class="editor-theme-code">Time.fixedDeltaTime</span>`

</td><td>`<span class="editor-theme-code">Time.deltaTime</span>`

</td><td>`<span class="editor-theme-code">Time.deltaTime</span>`

</td></tr><tr><td>****Gắn với****

</td><td>****Vật lý****<span style="white-space:pre-wrap;"> (PhysX): </span>`<span class="editor-theme-code">Rigidbody</span>`, lực, va chạm

</td><td>****Logic frame****: input, AI nhẹ, UI, timer

</td><td>****Hậu xử lý****<span style="white-space:pre-wrap;"> sau Update: camera follow, căn chỉnh vị trí/rotation</span>

</td></tr><tr><td>****timeScale = 0****

</td><td>****Dừng****<span style="white-space:pre-wrap;"> (physics dừng)</span>

</td><td><span style="white-space:pre-wrap;">Dừng (trừ khi dùng </span>**unscaled time**)

</td><td><span style="white-space:pre-wrap;">Dừng (trừ khi dùng </span>**unscaled time**)

</td></tr><tr><td>****Nên dùng cho****

</td><td>Vật lý, tính toán ổn định theo thời gian

</td><td><span style="white-space:pre-wrap;">Đọc </span>****input****, cập nhật gameplay, hoạt ảnh thủ công, UI

</td><td><span style="white-space:pre-wrap;">Cập nhật </span>****camera****<span style="white-space:pre-wrap;"> theo đối tượng đã cập nhật xong; sắp xếp thứ tự/đồng bộ transform</span>

</td></tr><tr><td>****Tránh****

</td><td><span style="white-space:pre-wrap;">Đọc input (không theo frame), thao tác </span>`<span class="editor-theme-code">Transform</span>`<span style="white-space:pre-wrap;"> trực tiếp gây xé với Update</span>

</td><td>Gọi API physics bước lớn/không ổn định theo FPS

</td><td><span style="white-space:pre-wrap;">Logic làm thay đổi dữ liệu mà </span>`<span class="editor-theme-code">Update()</span>`<span style="white-space:pre-wrap;"> còn phụ thuộc</span>

</td></tr><tr><td>****Ghi chú****

</td><td><span style="white-space:pre-wrap;">Nếu FPS thấp, </span>`<span class="editor-theme-code">FixedUpdate</span>`<span style="white-space:pre-wrap;"> có thể chạy </span>****nhiều lần/frame****; giữ logic vật lý ở đây để kết quả ổn định

</td><td>Logic phụ thuộc hiển thị/frame-accurate nên đặt ở đây

</td><td><span style="white-space:pre-wrap;">Dùng để </span>****“đi sau cùng”****: camera mượt, ràng buộc cuối cùng sau Update

</td></tr></tbody></table>

# Collision Detection

### Khái niệm

- <span style="white-space:pre-wrap;">Cách Unity/PhysX (3D) hoặc Box2D (2D) xác định </span>****hai collider có chạm nhau****<span style="white-space:pre-wrap;"> trong bước mô phỏng.</span>
- <span style="white-space:pre-wrap;">Mục tiêu: </span>****tránh “xuyên vật”****<span style="white-space:pre-wrap;"> (tunneling) khi vật thể </span>****di chuyển nhanh****<span style="white-space:pre-wrap;"> hoặc collider </span>****mỏng****.

### Rigidbody 3D

<table id="bkmrk-ch%E1%BA%BF-%C4%91%E1%BB%99m%C3%B4-t%E1%BA%A3d%C3%B9ng-khid"><colgroup><col style="width:119px;"></col><col></col><col></col></colgroup><tbody><tr><th>Chế độ

</th><th>****Mô tả****

</th><th>****Dùng khi****

</th></tr><tr><td>****Discrete****

</td><td><span style="white-space:pre-wrap;">Mặc định. Kiểm tra tại </span>****các mẫu thời gian rời rạc****<span style="white-space:pre-wrap;"> (mỗi bước physics). Nhanh nhất nhưng có thể xuyên nếu quá nhanh/mỏng.</span>

</td><td>Hầu hết vật thể di chuyển chậm/trung bình.

</td></tr><tr><td>****Continuous****

</td><td><span style="white-space:pre-wrap;">Kiểm tra </span>****swept****<span style="white-space:pre-wrap;"> giữa hai vị trí (last→new) để giảm xuyên qua </span>****static colliders****.

</td><td>Vật thể di chuyển nhanh, va tường mỏng.

</td></tr><tr><td>****Continuous Dynamic****

</td><td><span style="white-space:pre-wrap;">Nâng cấp của Continuous cho </span>****Rigidbody động nhanh****<span style="white-space:pre-wrap;"> va vào </span>****đối tượng continuous****<span style="white-space:pre-wrap;"> khác. </span>

Tốn chi phí hơn.

</td><td>Đạn/vật thể rất nhanh, va chạm động–động.

</td></tr><tr><td>****Continuous Speculative****

</td><td>Dự đoán va chạm (**speculative**) ở bước kế tiếp. Ổn định, chi phí vừa, hiệu quả với vật nhỏ/nhanh.

</td><td>Vật thể nhỏ, tốc độ cao, cần chi phí hợp lý.

</td></tr></tbody></table>

<p class="callout warning"><span style="white-space:pre-wrap;">Continuous/Continuous Dynamic </span>****tốn hiệu năng****<span style="white-space:pre-wrap;"> hơn Discrete; chỉ bật cho vật thể thật sự cần.</span></p>

### Rigidbody 2D

<table id="bkmrk-ch%E1%BA%BF-%C4%91%E1%BB%99m%C3%B4-t%E1%BA%A3d%C3%B9ng-khid-1"><colgroup><col style="width:102px;"></col><col></col><col></col></colgroup><tbody><tr><th>Chế độ

</th><th>****Mô tả****

</th><th>****Dùng khi****

</th></tr><tr><td>****Discrete****

</td><td>Mặc định, rẻ. Có thể xuyên khi rất nhanh.

</td><td>Vật thể chậm/trung bình.

</td></tr><tr><td>****Continuous****

</td><td>Giảm xuyên qua bằng kiểm tra swept 2D.

</td><td>Vật thể nhanh hoặc collider mỏng.

</td></tr></tbody></table>

### Trigger vs Collision

<table id="bkmrk-lo%E1%BA%A1id%C3%B9ng-chocallback"><colgroup><col></col><col style="width:335px;"></col><col></col></colgroup><tbody><tr><th>Loại

</th><th>Dùng cho

</th><th>Callback

</th></tr><tr><td>****Collision (va chạm)****

</td><td><span style="white-space:pre-wrap;">Vật thể </span>****chặn nhau****<span style="white-space:pre-wrap;"> (phản lực, ma sát…)</span>

</td><td>`<span class="editor-theme-code">OnCollisionEnter/Stay/Exit</span>`

</td></tr><tr><td>****Trigger****

</td><td>****Không chặn****, chỉ để bắt sự kiện

</td><td>`<span class="editor-theme-code">OnTriggerEnter/Stay/Exit</span>`

</td></tr></tbody></table>

### Best Practice

- ****Vật nhanh/nhỏ****<span style="white-space:pre-wrap;">: dùng </span>****Continuous/Continuous Dynamic****<span style="white-space:pre-wrap;"> (3D) hoặc </span>****Continuous****<span style="white-space:pre-wrap;"> (2D).</span>
- ****Giữ collider đơn giản****<span style="white-space:pre-wrap;"> (hộp/cầu/capsule) để giảm chi phí và ổn định tiếp xúc.</span>
- ****Di chuyển Rigidbody bằng physics****<span style="white-space:pre-wrap;"> (</span>`<span class="editor-theme-code">AddForce</span>`<span style="white-space:pre-wrap;">, </span>`<span class="editor-theme-code">MovePosition</span>`<span style="white-space:pre-wrap;">) — tránh </span>`<span class="editor-theme-code">transform.Translate</span>`<span style="white-space:pre-wrap;"> để không bỏ qua mô phỏng.</span>
- ****Interpolate****<span style="white-space:pre-wrap;"> (Rigidbody Interpolate) chỉ mượt hình ảnh, </span>****không****<span style="white-space:pre-wrap;"> thay đổi va chạm.</span>
- <span style="white-space:pre-wrap;">Kiểm soát va chạm bằng </span>****Layer Collision Matrix****; tắt những lớp không cần để tiết kiệm.
- <span style="white-space:pre-wrap;">Nếu vẫn bị “xuyên”: tăng </span>****Fixed Timestep****<span style="white-space:pre-wrap;"> (mô phỏng dày hơn), giảm tốc độ đỉnh, hoặc </span>****tăng độ dày****<span style="white-space:pre-wrap;"> collider.</span>