Group Details Private
administrators
Member List
-
HungBui
1. Phương án giao tiếp
Về cơ bản sự giao tiếp chỉ là app và unity send data cho nhau thông qua hệ thống giao tiếp.
2. Phương án kỹ thuật
Updating...
3. Model data giao tiếp
3.1 Model chung
{ "id": "string", "type": "string", "response": "boolean", "payload": { } }
Properties Type Mô tả id string Mã định danh duy nhất để xử lý trả về và call back type string Loại dữ liệu sẽ tác động ví dụ "coin", "scene"... response boolean Lần gửi data này có cần bên nhận trả lại kết quả hay không? payload object Data cụ thể hơn cho từng trường hợp 3.2 Ví dụ các trường hợp cụ thể
3.3.1 App request Unity mở một scene cụ thể và không cần trả về kết quả
{ "id": "123", "type": "open_unity", "response": false, "payload": { "action":"open", "destination": "map_lesson" } }
destination: "map_lesson" : là scene / layout muốn hiển thị. Giá trị này cần được thống nhất giữa app và unity
3.3.2 App request Unity lấy dữ liệu của coin và cần trả về kết quả
Request từ App sang Unity
{ "id": "4444", "type": "coin", "response": true, "payload": { "action": "get" } }
Response từ Unity trả về cho App, về bản chất là Unity gửi cho App bộ data có id và type cùng loại với Request ở trên
{ "id": "4444", "type": "coin", "response": false, "payload": { "success": true, "message": "Get coin success", "current_balance": 1000 } }
4. Model giao tiếp trong MS 2.0
Phần payload là phần động giữa các lần giao tiếp, cần phải thống nhất giữa App và Unity
Updating... -
HungBui
Mục tiêu
Thống nhất về cách sử dụng Debug
Dễ dàng quản lý debug cũng như tối ưu performance của ứng dụngTổ chức
Class DebugMonkey
Giải thích tăng hiệu năng
1. Vấn Đề Hiệu Năng Khi Debug
Trong Unity, việc sử dụng
Debug.Log
,Debug.LogWarning
, vàDebug.LogError
có thể gây ảnh hưởng đến hiệu suất của game, đặc biệt là trên mobile hoặc build final. Nguyên nhân chính:- Chuỗi string được tạo dù log có hiển thị hay không
Ví dụ khi debug theo cách truyền thống:
Debug.Log("Player position: " + player.transform.position.ToString());
Dù bạn có tắt debug khi build, nhưng chuỗi "Player position: ..." vẫn được tạo, gây tốn bộ nhớ và CPU không cần thiết.2. Giải Pháp DebugMonkey
Class DebugMonkey sử dụng biểu thức lambda (Func<string>) và điều kiện Conditional để tối ưu hiệu năng debug, ví dụ việc sử dụng DebugMonkey
DebugMonkey.Log(() => "Player position: " + player.transform.position);
Nếu điều kiện hiển thị Debug bị tắt , hàm Log() bị loại bỏ hoàn toàn khỏi build (tương đương với việc code không tồn tại)Cách dùng
Sử dụng DebugMonkey với các phương thức tương tự Debug của Unity, lưu ý là sử dụng lamda cho nội dung debug như ảnh trên. -
HungBui
Mục tiêu
Thống nhất về cùng kiểu guilding
Tiết kiệm thời gian phát triển guiding trong quá trình dev gameTổ chức
updating...
Cách dùng
Kéo prefabs guiding trong Base lên Hierarchy như hình
Reference vào đối tượng cần dùng
Call các method tương ứng
Các phương thức hỗ trợ
- Scale: Thay đổi kích thước của hướng dẫn.
- Tap: Mô phỏng thao tác chạm vào một vị trí.
- HideTap: Ẩn hiệu ứng chạm.
- Drag: Mô phỏng thao tác kéo từ một vị trí đến vị trí khác trong một khoảng thời gian.
Xin hãy đọc thêm ở summary của từng method
-
HungBui
Mục tiêu
Tránh việc coupling giữa game và hệ thống âm thanh bên ngoài
Thuận lợi cho việc implement SoundManager ở các project khác nhauTổ chức
updating...
Cách dùng
SoundListenner
Mỗi 1 game cần có 1 object chứa class SoundListenner trên Hierarchy, đối tượng này đã thiết kế sẵn method và phương thức lắng nghe các sự kiện phát âm thanh.
Sử dụng Observer qua kênh SoundChannel để phát âm thanh mong muốn
Cách gán SoundListenner lên Hierarchy
Class SoundListenner đã có sẵn trong project.
Kéo class SoundListenner vào 1 object tồn tại trên Hierarch như hình dưới đâySoundManager
Mỗi 1 game cần có 1 object chứa class SoundManager Fake trên Hierarchy để thực thi các method phát âm thanh
SoundManager Fake có ý nghĩa là sau này trong game sẽ không thực sự có vì sau này SoundManager sẽ dùng chung của cả project
Cách get prefabs SoundManager
SoundManager đã được tổ chức thành prefabs, chỉ cần kéo lên Hierarchy của game để sử dụng như hình dưới đây
-
HungBui
Mục đích
Nhằm tránh tình trạng không thống nhất và phân mảnh các tài nguyên dùng chung, sẽ có một số tài nguyên được quy định dùng chung tại tài liệu này
Đặc điểm
Thông thường các tài nguyên dùng chung sẽ nằm trong các mục được phân quyền cao, khi có vấn đề về việc thay đổi, bổ sung tài nguyên dùng chung sẽ phải làm theo quy trình tại đây (Xem mục Phân quyền và Quy trình đề xuất sửa đổi khi không được phân quyền )
Danh sách tài nguyên
1. Core
Sẽ bổ sung bài viết về hệ thống này sau
2. Base
1. Font
Hiện tại sử dụng 2 font là Nunito-Bold và Nunito-SemiBold, các game sử dụng chung font này, không tự tạo font mới3.ThirdPatty
1. Demigiant
Sử dụng cho Tween Tài liệu tại đây
2. Spine
Sử dụng cho animation Tài liệu tại đây
3. TextMesh Pro
Sử dụng TextMesh Pro Tài liệu tại đâyCập nhật ngày 13/3/2025
-
HungBui
Mã nguồn
1. Source
https://github.com/eduhub123/monkey_story_2
2. Flow
Xem tại đâyTổ chức chung
1. Core
Bộ phận chung của các project khác nhau (MS, MJ...)2. Base
Phần base của từng project, mỗi project khác nhau3. ThridPatty
Các library bên thứ ba4. Game MS
Nơi chứa các game của projectPhân quyền
1. Core, 2. Base, 3. ThridPatty
Chỉ Leader hoặc thành viên được leader ủy quyền mới được thay đổi nội dung của các thư mục này4. Game MS
Tất cả các thành viên code game sẽ được đặt code ở đây theo git flow tại đâyQuy trình đề xuất sửa đổi khi không được phân quyền
Bước 1. Thành viên trao đổi vấn đề với leader hoặc thành viên được leader ủy quyền để được thay đổi khu vực không có quyền thay đổi
Bước 2. Leader hoặc thành viên được ủy quyền review và thay đổi nếu có theo git flow tại đây
Bước 3. Thông báo đến thành viên yêu cầu thay đổi hoặc thông báo vào nhóm khi đã có kết quả (chấp nhận hay không chấp nhận đều thông báo)
-
HungBui
Xuất ảnh
Có 3 kiểu xuất ảnh, tùy vào nhu cầu, mng có thể lựa chọn 1 trong 3
Kiểu 1: Xuất ảnh theo từng Artboard
Phím tắt Ctrl + Alt + Shift + S
Đặc điểm: Chỉ xuất được những vùng bên trong Artboard đang chọnKhung artboard chưa chọn màu xám, khung artboard đang chọn hiện màu đen
Cách xuất ảnh:
Cách 1: Chọn Artboard bằng cách ấn chuột trái vào giữa hoặc trong khung của artboard đó, sau đó nhấn tổ hợp phím Ctrl + Alt + Shift + S để hiện cửa sổ xuất ảnhCách 2: Hoặc có thể chọn vào File -> Export -> Save for Web
Sau khi cửa sổ xuất ảnh hiện ra, điều chỉnh thông số như mong muốn và nhấn Save để xuất ảnh
Lưu ý tích vào nút Transparency nếu muốn xuất ảnh tách nền trắng
Kiểu 2: Xuất nhiều Artboard cùng lúc
Phím tắt Ctrl + Alt + E
Cách xuất ảnh:
Chọn vào File -> Export -> Export for ScreensHiện lên cửa sổ chọn các artboard mong muốn, sau khi chọn xong, click vào Export Artboard để xuất
Kiểu 3: Xuất 1 đối tượng riêng lẻ (Asset export)
Trên thanh công cụ phía bên phải giao diện Illustrator chọn icon Asset export
Nếu không có biểu tượng này thì vào Window -> chọn Asset Export
Cửa sổ Asset Export sẽ hiện ra
Kéo các đối tượng cần Export vào khung vuông
Tùy chỉnh thông số và ấn Export để xuất các đối tượng
Lưu ý: Các đối tượng đang trong group sẽ không kéo được vào khung vuông, nên sẽ phải ungroup ra rồi kéo vào, hoặc copy ra ngoài group
Group, Ungroup
Group các đối tượng:
Ví dụ: Với 3 tảng đá riêng lẻ, muốn group vào thì ta cần chọn cả 3, bằng cách:
- giữ phím Shift sau đó chuột trái vào lần lượt các tảng đá
- sau đó chuột phải, chọn Group
Ungroup các đối tượng:
- Chọn Group bằng chuột trái
- sau đó chuột phải, chọn Ungroup
Xuất đối tượng theo khung viền Artboard
Các bước thực hiện:
Bước 1: Xác định đối tượng cần xuất và vùng cần xuất
Click đúp vào đối tượng/group cho đến khi hiện khung object như ảnh dưới
Bước 2: Chọn vào biểu tượng Rectangle tool ( phím tắt M )
Bước 3: Giữ chuột trái, kéo 1 khung bao trọn toàn bộ object, sao cho cạnh của khung trùng với các cạnh của Artboard
Bước 4: Chọn cả 2 bằng cách giữ Shift và nhấn lần lượt vào khung và object
Bước 5: Click chuột phải, chọn Make Clipping Mask
Sau khi thao tác xong, ta có được 1 mảnh cần xuất của đối tượng
Bước 6: Ctrl C đối tượng, sau đó ấn vào tab đầu tiên của thanh Group để thoát khỏi group
Bước 7 : Sau đó, Ctrl V đối tượng vào vùng trống của file thiết kế, và xuất như bình thường với Asset Export. Sau khi xong, ta có thể xóa đối tượng đi
Loại bỏ thành phần không cần thiết trong object/group
Bước 1 : Bấm phím A, để con trỏ chuyển từ màu đen sang màu Trắng
Bước 2: click chuột trái vào thành phần cần bỏ, ví dụ như text
Bước 3: Nhấn delete và xuất như bình thường
- giữ phím Shift sau đó chuột trái vào lần lượt các tảng đá
-
tunadodev
Quy định chung
-
Luôn sử dụng ID test (config variant appTest) trong quá trình phát triển
-
Chỉ sử dụng ID thật khi đã pass test và build aab (trừ 1 số trường hợp debug cần check ad thật)
-
Không để bất kỳ content nào của app đè lên ads, cả loading (Chỉ chấp nhận các loại dialog, popup...có thể bật tắt)
-
Ads không được đè lên content app mà ko có scroll
-
Không đặt ads ở ngay cạnh trên/dưới thanh điều hướng, vị trí user dễ tương tác
-
Không đặt ads tại các màn không cung cấp nội dụng, chức năng của app, như các nội dung nhúng, webview
-
Ads không được hiển thị ở ngoài app
-
Không để ads xuất hiện bất ngờ khiến user dễ click nhầm vào ads , phải có loading giữ khoảng trống cho ads
-
Preload ads hợp lý để tỉ lệ showrate không quá thấp
-
Danh sách ID test
App Open ca-app-pub-3940256099942544/3419835294 Banner ca-app-pub-3940256099942544/6300978111 Interstitial ca-app-pub-3940256099942544/1033173712 Interstitial Video ca-app-pub-3940256099942544/8691691433 Rewarded ca-app-pub-3940256099942544/5224354917 Rewarded Interstitial ca-app-pub-3940256099942544/5354046379 Native Advanced ca-app-pub-3940256099942544/2247696110 Native Advanced Video ca-app-pub-3940256099942544/1044960115
Các loại ad
Ad Banner
- Không nên đặt ad banner ngay cạnh nội dung ứng dụng và các yếu tố tương tác
Banner ad guidance
Ad Interstitial
- Cần preload hợp lí đảm bảo khả năng show cao nhất có thể
- Set null ad interstitial sau khi đã được show và load lại nếu cần thiết
- Chỉ show interstitial khi có hành động chuyển màn từ tương tác của user
Interstitial ad guidance
Ad Native
- Luôn có loading trong khi chờ load ad native
- background ad phải khác background content app
AdMob native ads policy compliance checklist
Ad Reward
-
Cần có biểu tượng thông báo AD tại vị trí show ad reward
-
Ad reward có thời gian load lâu hơn so với các ad khác => cần preload hợp lí
-
Set null sau khi show reward và load lại nếu cần thiết
Overview of rewarded ad units
Policies for ads that offer rewards
Ad Open (ad resume)
- Luôn disable tại các màn splash, IAP, policy, readme...
- Disable khi open policy, more app, share app, feedback... từ menu, drawer, setting...
-
-
HungBui
1. Các bài toán đã thực hiện
Bài toán Thực trạng Tình trạng Kết quả Cải thiện Người thực hiện Base game Các game được phát triển một cách tự phát, không có quy trình cụ thể, khó khăn cho fixbug và phát triển Đã giải quyết được cơ bản về quy trình phát triển game với hệ thống FSM và observer design pattern Game đã có luồng rõ ràng, quá trình phát triển game được rút ngắn, thời gian fixbug nhanh, được đánh giá dễ sử dụng từ dev - Tự động tạo các class chính - Review base mục đích cải thiện, tối ưu và sử dụng thêm các design pattern hợp lý giúp tăng tính mạch lạc và dễ sử dụng của base Hùng Bùi Data game Các game khó có thể share giữa các khóa khác nhau do data có thể khác nhau Đã giải quyết bằng cách sử dụng chung bộ data model cho tất cả các game, bộ data đảm bảo cho việc dễ sử dụng và tổng quát Các game có thể chạy độc lập với data mock hoặc data test. Các game dễ dàng tách và đóng gói (cùng với base) Chưa có kế hoạch Hùng Bùi Navigation Để chuyển giữa các khóa học đang sử dụng bằng cách gọi thẳng tên scene và khó kiểm soát các yêu cầu khởi tạo của khóa học, phức tạp và khó khăn trong quá trình chuyển đổi giữa các khóa Đã chuyển chung cơ chế chuyển scene do 1 đối tượng quản lý, ở đây sẽ kiểm tra tất cả các điều kiện khởi tạo khóa học cần thiết Thời gian chuyển các khóa được tối ưu, phát triển khóa mới không lo lắng ảnh hưởng đến khóa cũ, tách biệt data của các khóa khác nhau, không cần thiết sẽ không khởi tạo Review lại luồng data học và data đồng bộ của khóa Abc và MStory để tách biệt ra với một số case đặc biệt Hùng Bùi Event Mỗi một event có hệ thống properties khác nhau, mỗi khi có một properties mới sẽ phải viết lại method cho event này Đã tạo 1 base event với việc chia các properties chung và thiết kế linh hoạt các properties khác nhau để có thể sử dụng chung method cho các event khác nhau Giảm thời gian phát triển cho chức năng push event Chưa có kế hoạch Tiến ND AI Speak Nhiều game sử dụng công nghệ AI Speak nhưng mỗi game sử dụng khác nhau dẫn đến không đồng nhất về luồng và gây khó khăn cho quá trình debug Đã tạo 1 module chung bao gồm đầy đủ từ xin quyền đến thực thi AI Speak với kịch bản online và offline cụ thể Dễ dàng trong việc sử dụng module với input và output rõ ràng, giảm thời gian phát triển chức năng liên quan đến AI Speak Chưa có kế hoạch Hiếu HS Tối ưu dung lượng build Các assets trong game đang được build cùng game. Khi phát triển thêm tính năng sẽ tăng build size Sử dụng Addressable nhằm tách các assets của game ra bên ngoài và download về khi cần Build size đã giảm và ổn định hơn. Khi thêm tính năng mới build size sẽ không tăng nhiều Chưa có kế hoạch Hải Ngô Support Service Các phần hỗ trợ trong game đang được phát triển riêng biệt, không có quy chuẩn cụ thể, khó khăn trong việc phát triển và fix bug Các phần hỗ trợ được quy chuẩn về dạng service, có Service manager để quản lý. Các service được implement qua Interface để dễ dàng nâng cấp, thay thế khi cần Đã Implement được các services sau: Addressables, Assetbundle, DataSync, Download, EventTracking, Localization, Popup, UserData Cần đưa các service vào toàn bộ hệ thống thay vì chỉ dùng một phần trong MJ5 Hải Ngô, Tùng Đỗ Thay đổi visual trong game theo event Khi thay đổi event cần submit lại app. Mỗi khi có event mới tốn thời gian trong việc chỉnh sửa lại app, không tận dụng được event đã làm từ trước Event được quy chuẩn về dạng Theme và hiển thị theo Config. Dễ dàng thêm Event mới. Các event được điều khiển bằng data và hiển thị khi cần thiết Đã hoàn thành theme cho chủ đề giáng sinh Đưa theme ra ngoài và download về khi cần. Bổ sung thêm các theme theo chủ đề khác Hải Ngô Tối ưu share và tải tài nguyên Game và tài nguyên có thể share cho nhau nhưng vẫn phải tải lại từ package khác nhau với mỗi khóa học Hệ thống share game, tải tài nguyên chỉ cần 1 lần, các lần sau không cần tải lại QA Testing cho khóa MJ5 Cho pack Event Season + MSpeak (có điều kiện từ data) Hải Ngô (12/12/24) 2. Các bài toán mong muốn thực hiện
Bài toán Thực trạng Mong muốn Data user Data của tất cả các khóa đang để chung model dù không dùng gây nặng cho user đặc biệt với các user học nhiều khóa, lượng bài học hoàn thành nhiều, hiệu năng giảm - Tách biệt data của các khóa và phần data tặng thưởng riêng, khi cần data nào sẽ load data đó.<br>- Khi bổ sung khóa mới dễ đồng bộ và fixbug, không ảnh hưởng hiệu năng UI Map Các map khá giống nhau về mặt UI và chức năng nhưng mỗi map vẫn trên 1 base code khác nhau Gen map tự động theo data setting hoặc kéo thả Tặng khóa học Khi tặng khóa học các điều kiện tặng ở client khá phức tạp, phụ thuộc nhiều bên như client và server Xây dựng hệ thống tặng khóa dễ thay đổi điều kiện và dễ setup Game framework Mỗi game phải order từ nhiều bên (nội dung > kịch bản > đồ họa > dev) gây mất thời gian phát triển và test thử Xây dựng framework để bộ phận kịch bản + nội dung tự tạo game mong muốn theo quy tắc nhất định Tối ưu quy trình dev game Các object game lặp lại qua nhiều game nhưng dev vẫn phải code lại hoặc copy Hệ thống các object chung, tái sử dụng, giảm thời gian dev game