tips – Jake Tee https://jakesto.com Game Dev Blog Sun, 08 Jun 2025 02:49:42 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.1 https://jakesto.com/wp-content/uploads/2022/07/cropped-pngwing.com_-32x32.png tips – Jake Tee https://jakesto.com 32 32 194548219 Black Myth Wukong và học được gì từng những án game thất bại https://jakesto.com/black-myth-wukong-va-hoc-duoc-gi-tung-nhung-an-game-that-bai/?utm_source=rss&utm_medium=rss&utm_campaign=black-myth-wukong-va-hoc-duoc-gi-tung-nhung-an-game-that-bai Sun, 25 May 2025 08:40:42 +0000 https://jakesto.com/?p=1044 Chắc hẳn mọi người đa phần sẽ được những câu chuyện về những dự án game đạt được triệu đô, những công ty đi từ 0 tới 1, những đội ngũ tài ba với tâm huyết, làm việc không ngừng nghỉ để gây dựng nên những thành tựu đáng tự hào. Những sản phẩm như Black Myth: Wukong, đã liên tục tạo động lực cho các anh em làm game, rằng cứ mơ lớn, cứ làm, ắt sẽ được.

Để rồi tự đó, xuất hiện những dự án lớn nhỏ đi theo, với hy vọng, tái tạo lại được thành công kì diệu của nó. Mình không nói là tất cả sẽ thất bại, nhưng liệu mọi người đã thử tự nghiên cứu xem, tại sao Wukong lại đạt được thành công như vậy (trừ việc tất nhiên là game phải tốt, câu truyện phải đủ hay và hấp dẫn)

Trở lại câu chuyện của cá nhân tôi, người đã trong ngành game, và đặc biệt là game PC được gần 8 năm, cũng không nhiều, nhưng cũng không ít, đủ để tôi có thể cảm nhận được những đắng cay và chút ngọt bùi của chặng đường.

Game PC ở Việt Nam là một mảng rất chua, và khó, do đặc tính của game PC là thời gian phát triển dài, và tệp user cũng khó tính hơn trên mobile. Ở Việt Nam, thị trường game mobile đã có được chỗ dựa vững chắc từ các đàn anh đi trước như là Ikame, Falcon, Wolffun, Amanotes.. với vô vàn sự hỗ trợ lớn nhỏ của các đối tác như Google, Unity, Facebook,.. thúc đẩy sự phát triển của ngành.

Còn với game PC, đa phần là anh em indie, tự tụ lại với nhau và làm, có thể là bán thời gian, hay là dành ra 1 năm để làm toàn thời gian, và sau đó tự phát hành lên các nền tảng như Steam. Hệ sinh thái hỗ trợ game PC ở Việt Nam trước 2024 gần như là 0: không có sự kiện, không có đối tác hỗ trợ chính thức, không có cộng đồng đủ lớn, không có tài nguyên, không có đầu tư.

Anh em làm mảng PC gần như là tự lực cánh sinh, và đều chung một đích đến đơn giản, một game PC made by Vietnam, một game PC có thể chạm đến tay những players toàn cầu.

Tôi cũng vậy, bắt đầu với PC game khá sớm từ nhỏ, và giữ đam mê cho đến khi chính thức theo đuổi một cách nghiêm túc chuyên nghiệp. Tôi bắt đầu với một dự án game bắn súng multiplayer. Nghe thì điên rồ thật, nhưng đúng là nó rất điên rồ :)) Dự án đầu tay, lại còn multiplayer, lại còn FPS. Thoạt nghe như dự án của các thanh niên mới vào nghề làm (do hay chơi CS, hay Call of Duty), nhưng với tôi, tôi coi nó là một sản phẩm nghiêm túc, một sản phẩm để khẳng định tên tuổi và khả năng kĩ thuật bản thân.

Khởi đầu của game có vẻ tốt, tôi được nhắc đến và khen ngợi trên báo chí, các cộng đồng nước ngoài, về cả sản phẩm lẫn sự đáng kinh ngạc khi studio chỉ vọn vẹn 3 người làm. Kết quả doanh thu 7 ngày đầu khá ok. Studio tiếp tục tái đầu tư để cho ra nhiều game mode mới, cải thiện trải nghiệm, fix bug, tối ưu, vân vân mây mây. Game càng ngày càng tốt, review trên steam tích cực.

Nhưng rồi sau 3 năm, tất cả chững lại rồi đi xuống. Số lượng người chơi giảm, tuy có các cộng đồng bền vững chơi đều, nhưng số lượng bản mới bán được chậm lại, team không có kế hoạch monetization thông qua bán skin hay bất cứ vật phẩm ingame nào. Dần rồi số tiền công ty cũng cạn, bản thân tôi bị kiệt quệ, do phải làm việc 7 ngày một tuần, 12 tiếng một ngày, trong 3 năm. Và rồi, tôi đưa ra một quyết định rời đi.. vào mùa xuân của năm đó.

Rồi đến 300475

Một dự án được khởi động và dẫn dắt bởi HikerGames, studio game lâu đời nhất Việt Nam. Tôi may mắn được bước vào dự án với vai trò là lead developer, phát triển gần như toàn bộ hệ thống AI, vũ khí, nhân vật,… Trong quá trình làm cùng đàn anh, tôi đã nhận rất nhiều lửa và động lực. Làm với các anh tôi mới nhận ra rằng, tuy Hikergames giờ đã làm game mobile, nhưng mọi người vẫn luôn đau đáu đam mê và giấc mơ tạo ra một tựa game PC để đời. Nhiệt huyết là thế, nhưng rồi dự án đã dừng chân lại sau 10 tháng phát triển, do chỉ đạt được 10% số vốn gọi cộng đồng..

Sau khi rời 300475, tôi bắt đầu với dự án mới, là Deverse World. Là dự án đầu tay do chính tôi lãnh đạo, nhưng cũng vì thế mà tôi mắc cực nhiều sai lầm. Nếu từ hai dự án trước, tôi đã rút ra nhiều bài học về phát triển và kĩ thuật, thì tới dự án này, tuy đã hạn chế hết mức phần đó, tôi lại mắc sai lầm về thị trường và chiến lược xây dựng cộng đồng. Tôi dành quá nhiều thời gian để xây dựng sản phẩm, mà quên rằng phải liên tục kiểm tra thị trường để thấy mức độ đón nhận và phù hợp. Và vì thế, khi sản phẩm ra, người thì không hiểu, người thì bối rối, để rồi bọn tôi phải ngồi lại, tiếp tục thay đổi, và lại tốn thêm nhiều thời gian..

Đến khi team cảm thấy sản phẩm đủ ổn, thì cũng là lúc, thị trường đã đi qua mùa đẹp nhất.

Và rồi bọn tôi phải đập đi hết, làm lại, với quyết tâm phải liên tục vừa làm vừa thử với cộng đồng, tập trung vào đúng cốt lõi của trò chơi. 8 tháng anh em liên tục cày và cày, với toàn bộ nhiệt huyết của tuổi trẻ và đam mê hoài bão. Chúng tôi cũng đã gặt hái được một chút thành công ở những tháng cuối năm 2024.

Nghe tới đây chắc mọi người sẽ nghĩ, chúng tôi đã làm được. Nhưng tiếc là, sự thay đổi đã đến quá trễ. Thời điểm chúng tôi đạt được cũng là lúc, công ty cũng cạn tiền. Tôi đã cố gắng tìm kiếm cơ hội đầu tư khắp nơi, nhưng nhìn nhận khách quan thì thị trường game toàn cầu đang đi qua giai đoạn mùa đông, và chủ quan thì những gì bọn tôi đạt được cũng còn quá nhỏ.

Và rồi chúng tôi lần nữa chia tay dự án và đội ngũ, vào mùa xuân 2025..

3 dự án, mỗi dự án, tôi đều học được gì đó, có dự án tôi chỉ là người làm, có dự án tôi dẫn dắt, nhưng nhìn chung, đều không đạt được thành công gì đáng kể. Tuy sau mỗi dự án, dù tôi không để những sai lầm trước xảy ra, nhưng vẫn còn vô vàn những biến số khác mà tôi cũng không thể lường được.

Thế mới thấy rằng, không phải cứ có sản phẩm tốt, được cộng đồng ủng hộ thì thành công được.

Vậy tôi học được gì?
Dưới đây là một số bài học cho cá nhân tôi, có thể đúng hoặc sai, nhưng hy vọng sẽ giúp được mọi người chút gì đó, để tránh thất bại nhiều như tôi.

1. MVP, MVP, MVP. Tôi nhấn mạnh ý này 3 lần vì thực sự đây là một thứ cực kì quan trọng để bạn đánh giá xem concept game mình có được đón nhận không, trước khi dành tiếp 1-2 năm phát triển. Cố gắng làm MVP trong 6 tháng, chấp nhận thiết kế chống cháy, code không logic,.. để ra được sản phẩm nhanh nhất

2. Đánh giá khả năng team và sản phẩm. Để phát triển ra 1 game multiplayer không quá khó, nhưng để vận hành và duy trì nó sau đó là cả một vấn đề. Một team nhỏ 5-10 người hiển nhiên sẽ khó có đủ tài nguyên và nguồn lực cho việc đó. Nếu team bạn ít hơn nữa, bạn nên tập trung vào những thể loại indie, platformer ngắn, hoặc coop đơn giản.

3. Game là vui. Đôi khi tôi hay quá nghiêm túc trong các ý tưởng làm game, tức là phải làm ra những tựa game phải hoành tráng, điện ảnh, đồ sộ về hệ thống gameplay, cân bằng chiến đấu,.. Nhưng thực ra, luôn có những ý tưởng rất đơn giản và vui nhộn, đem lại sự giải trí cho người chơi, mà tôi lại bỏ qua. Suy cho cùng, người chơi tìm đến game là để giải trí, và cười sau một ngày làm việc học tập.

4. Nghiên cứu và lên kế hoạch cụ thể trước khi bắt đầu. Một kế hoạch bao gồm thời điểm ra MVP, khi nào bắt đầu ra video đầu tiên, khi nào setup Steam page, khi nào lên store, khi nào kết nối với đối tác và người chơi. Tất cả tuy chỉ là tương đối nhưng nó sẽ chỉ đường và giúp bạn tập trung trong quá trình làm.

5. Tuy là vui, nhưng cuối cùng vẫn là kinh doanh. Suy cho cùng, thì để game tới giai đoạn cuối, bạn cũng cần có tiền, và bạn cũng cần tiền sau khi ra để tiếp tục làm game mới hoặc phát triển thêm. Tiền có thể là tiền nghĩa đen hoặc là công sức bạn đổi lấy tiền. Dù sao đi nữa cũng cần tính toán trước các kế hoạch tài chính cho bản thân, hay cho đội và công ty.

6. Rõ ràng về quyền lợi. Nếu bạn là solo dev, thì mục này không quan trọng lắm. Nhưng nếu bạn có nhóm, hay là công ty, bạn nên rõ ràng từ đầu về quyền lợi của các thành viên tham gia. Quyền lợi nên được tính toán dựa trên đóng góp và cam kết của cá nhân với dự án, thay vì đơn giản là “Team tôi 4 người, nên tôi chia mỗi người 25% lợi nhuận/công ty”. Nghe thì có vẻ sẽ không có nghiêm trọng nhưng một khi game bạn có được thành công, những sự đơn giản này sẽ dễ biến thành vấn đề không hề nhỏ đâu.

Chắc còn nhiều nữa mà chắc đây là vài ý chính tôi có thể ghi ra.

Vậy, sắp tới tôi làm gì? Tôi đã thất bại liên tục vậy, liệu tôi có làm tiếp? Chắc tôi sẽ có câu trả lời sau vài thời gian nghỉ ngơi.

Cảm ơn bạn đã đọc tới thời điểm này. Chúc các bạn sớm thành công với dự án game của mình.

]]>
1044
Tại sao gần đây mình không có bài gì mới https://jakesto.com/tai-sao-gan-day-minh-khong-co-bai-gi-moi/?utm_source=rss&utm_medium=rss&utm_campaign=tai-sao-gan-day-minh-khong-co-bai-gi-moi Sun, 19 Nov 2023 02:53:12 +0000 https://jakesto.com/?p=1000 Xin chào mọi người, mọi người có thể thấy là bài cuối mình viết là từ tháng 3. Trong thời gian qua mình khá bận với việc chưa có ý tưởng để viết bài 😂 Nên nếu mọi người muốn mình viết gì về tính năng hay tips thì cứ comment nhé.

Mình cũng muốn share cho mọi người khóa học tiếng việt Unreal Engine rất chất lượng của một bạn trong nhóm.

https://www.udemy.com/user/brandon-vox/

]]>
1000
101 Tips – Stack Trace https://jakesto.com/101-tips-stack-trace/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-stack-trace Sun, 19 Mar 2023 14:57:30 +0000 https://jakesto.com/?p=980 Khi debug lỗi, hẳn các bạn sẽ không lạ việc tìm kiếm xem hàm đó hoặc sự kiện đó được gọi ở đâu. Trong c++, cách thường làm đó là thêm break point vào dòng code cần xem. Thế còn trong Blueprint thì làm như thế nào?
Câu trả lời là Stack Trace.

Giả sử ta có 1 hàm tên là PrintHelloWorld, chỉ đơn giản là Print String ra màn hình dòng “Hello World” như sau:

Để biết được hàm PrintHelloWorld này được gọi từ object nào, chỉ việc thêm Stack Trace vào nối hàm:

Sau khi hàm PrintHelloWorld được gọi, ta sẽ biết được nguồn gốc của việc gọi đó:

LogBlueprintUserMessages: Script call stack:
Function /Game/Blueprints/BP_MyCharacter.BP_MyCharacter_C:InpActEvt_T_K2Node_InputKeyEvent_0
Function /Game/Blueprints/BP_MyCharacter.BP_MyCharacter_C:ExecuteUbergraph_BP_MyCharacter
Function /Game/Blueprints/BP_MyCharacter.BP_MyCharacter_C:PrintHelloWorld
Function /Game/Blueprints/BP_MyCharacter.BP_MyCharacter_C:ExecuteUbergraph_BP_MyCharacter
LogBlueprintUserMessages: [BP_MyCharacter_C_0] Hello World!

Như ở ví dụ trên, PrintHelloWorld được gọi trong BP_MyCharacter, ở sự kiện ấn nút T.

]]>
980
101 Tips – Mở level kèm tham số https://jakesto.com/101-tips-mo-level-kem-tham-so/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-mo-level-kem-tham-so Sun, 18 Sep 2022 12:55:28 +0000 https://jakesto.com/?p=945 Có nhiều mục đích khi mở level kèm tham số. Ví dụ bạn cần kiểm tra xem level trước đó của người chơi là gì, hoặc chỉ đơn giản là muốn truyền một tham số để khi vừa qua level mới có thể sử dụng ngay.
Có nhiều cách để có thể truyền tham số khi mở một level mới, ví dụ như lưu vào GameInstance, rồi sau khi level đã load xong, ta lấy ra sử dụng. Nhưng thứ thế ta lại phải tạo một hay nhiều biến mới không cần thiết.

Một cách đơn giản đó là ta truyền tham số kèm với khi mở một level mới bằng hàm OpenLevel phổ biến

Nếu bạn không thấy mục Absolute và Options ở dưới, chỉ việc click vào mũi tên để xổ ra.

Vùng Options cho phép ta truyền vào một hay nhiều tham số, được ngăn cách nhau bởi dấu “?”:

?PreviousLevel=MyLevel1?MyScore=20

Ở ví dụ trên, ta sẽ truyền qua Level mới giá trị PreviousLevel (level trước đó) là MyLevel1, MyScore là 20.

Tiếp đến, để sử dụng những tham số vừa truyền, ta vào class GameMode. Nếu bạn chưa biết GameMode là gì, có thể tham khảo lại bài viết này: https://jakesto.com/index.php/2020/03/01/unreal-engine-4-framework-gamemode/

Chuột phải vào Event Graph, và tìm cụm từ Options String, đó chính là đoạn Options mà bạn truyền vào ở trên. Tiếp đó ta chỉ cần Parse đoạn string đó với key tương ứng:

Như vậy đã xong, với cách này, bạn đã có thể thoải mái đem giá trị từ level này sang level khác mà không cần lo việc tạo quá nhiều biến.

]]>
945
101 Tips – Lightning channel https://jakesto.com/101-tips-lightning-channel/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-lightning-channel Sat, 28 May 2022 13:54:06 +0000 https://jakesto.com/?p=895 Có bao giờ bạn muốn đèn chỉ cast ánh sáng lên một số vật thể nhất định trong scene? Hay là chỉ đơn giản là muốn hạn chế ánh sáng cast lên quá nhiều vật thể để tối ưu hiệu năng? Trong Unreal Engine có một tính năng khá hay đó là Lighting Channel.

UE cung cấp cho người dùng 3 channel để sử dụng, và mặc định luôn là Channel 0.

Để thay đổi Lightning Channel, tìm kiếm giá trị Lightning Channel trong vùng Details của ánh sáng, bỏ check Channel 0 và đánh dấu vào Channel 1:

Làm tương tự với các vật thể mà bạn muốn ánh sáng được cast lên. Kết quả ta sẽ có như sau:

Như vậy toàn bộ scene đã không còn được nhận ánh sáng từ DirectionalLight, trừ khối hộp bên trái đã chuyển Lightning Channel sang 1.

]]>
895
Tổng hợp các bài viết ngẫu nhiên https://jakesto.com/tong-hop-bai-viet-random/?utm_source=rss&utm_medium=rss&utm_campaign=tong-hop-bai-viet-random Tue, 03 May 2022 15:18:32 +0000 https://jakesto.com/?p=884 Quy trình

Cách fornite kiểm soát quy trình công việc với UnrealGameSync

Địa ngục render

Cách tối ưu hóa dành cho thiết kế mô đun

Nghệ thuật tối ưu

Sách cầm tay cho người kinh doanh game

Hiệu năng cần thiết cho Valorant

Phát triển, lập trình

Netcode không hiệu quả ra sao

Server 128-tick của Valorant

Sử dụng ChunkDownloader

Stream assets trong C++

Phân tích module network của Unreal Engine (tiếng Trung)

Xây dựng thế giới ở No Man’s Sky sử dụng toán học

Series làm game MMORPG

Khám phá sự bí ẩn của Soft Object Reference

Object Reference là gì

Plugin hỗ trợ giao tiếp với dedicated server thông quan rcon

Mô phỏng trực quan components

Chức năng tạo liên tục thế giới trong No Man’s Sky

Âm thanh

Tại sao tiếng súng trong Call of Duty : Modern Warfare nghe đã vậy

Làm thế nào để tạo tiếng súng hay cho games

Thiết kế, diễn hoạt hình

Plugin convert mixamo sang mannequin cho blender

Shader và gameplay của Valorant

Làm sao để Unreal trông thật và điện ảnh hơn

]]>
884
101 Tips – Format text https://jakesto.com/101-tips-format-text/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-format-text Tue, 29 Mar 2022 14:00:14 +0000 https://jakesto.com/?p=875 Đây là một tip khá hay để có thể format đoạn chữ. Cách phổ biến mọi người hay dùng thường là sử dụng Append String:

Cách này có một hạn chế lớn đó là khi cấu trúc câu trở nên phức tạp thì việc thêm pin vô sẽ rất rườm rà. Thay vào đó ta có thể sử dụng Format Text:

Với cách này, ta có thể thêm pin vào bằng cách sử dụng cú pháp {char} với char có thể là bất cứ kí tự chữ số nào miễn là không trùng nhau.

Ngoài ra, sử dụng Format Text, các đầu nối pin sẽ không phải convert sang dạng String như khi dùng Append String, ta chỉ việc đổi Text thành String sau cùng.

]]>
875
101 Tips – Macro https://jakesto.com/101-tips-macro/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-macro Wed, 23 Mar 2022 12:59:45 +0000 https://jakesto.com/?p=864 Nếu các bạn đã từng thấy một node Blueprint như:

kèm với biểu tượng bánh răng ở góc thì đó chính là một Macro. Công dụng của node trên đó là kiểm tra quyền network của dòng logic đi qua.

Vậy Macro là gì, Macro có thể hiểu đơn giản là một node cho phép người dùng kiểm soát dòng di chuyển logic một cách gọn hơn. Nếu như Function hay Custom Event chỉ có một chiều di chuyển thì Macro có thể có một hoặc nhiều chiều.

Nếu chung ta đúp chuột vào node Switch Has Authority, nó sẽ trông như sau:

Về lí thuyết ta có thể kéo giá trị trả lại từ Has Authority và nối vào Branch để kiểm tra quyền network nhưng nếu phải lặp lại nhiều lần như vậy thì đống dây nối của ta sẽ bị dư thừa nhiều hơn.

Để tạo một Macro, click dấu + trong vùng Macro ở MyBlueprint

Trong ví dụ này mình sẽ làm một Macro kiểm tra xem đầu vào có phải số chẵn hay không.

Trong vùng InputsDetails, lần lượt thêm tham số đầu vào FloatExec. Định dạng Exec chính là một dạng đặc biệt cho phép dòng logic đi qua (hay còn thấy ở mỗi đầu node Blueprint).

Trong vùng Outputs, lần lượt thêm tham số đầu ra Exec cho số chẵn và số lẻ.

Logic thì chỉ đơn giản là kiểm tra số dư khi chia 2, nếu dư thì ta cho dòng logic đi vào nối Even Number và lẻ thì vào Odd Number.

Sau đó chỉ việc kéo ra sử dụng và kết quả khi truyền số 11 vào:

]]>
864
Hướng dẫn làm chức năng quan sát đồ vật trong game kinh dị https://jakesto.com/huong-dan-lam-chuc-nang-quan-sat-do-vat-trong-game-kinh-di/?utm_source=rss&utm_medium=rss&utm_campaign=huong-dan-lam-chuc-nang-quan-sat-do-vat-trong-game-kinh-di Mon, 13 Sep 2021 11:09:43 +0000 https://jakesto.com/?p=831 Do hướng dẫn khá dài và mình cũng lười đánh nên mình làm luôn video :))

Phần 1
Phần 2
Phần 3

Link project :

https://github.com/Long1302/UE4-TutorialProject

]]>
831
101 Tips – 2 – Widget instance editable variables và expose on spawn https://jakesto.com/101-tips-2-widget-instance-editable-variables-va-expose-on-spawn/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-2-widget-instance-editable-variables-va-expose-on-spawn Sat, 26 Sep 2020 09:42:59 +0000 https://jakesto.com/?p=724 Khi tạo một widget và khởi tạo các giá trị, cách thông thường ta hay thấy đó là như sau:

Giả sử ta có 1 widget tên là WBP_Health, và ta muốn khởi tạo giá trị máu ban đầu cho widget

Cách dễ thấy nhất là sau khi tạo widget, ta set thẳng biến InitialHealth được tạo trong WBP_Health.

Cách này sẽ hiệu quả trong nhiều trường hợp, nhưng nếu ví dụ, bạn muốn sau khi set máu ban đầu, bạn sẽ set hiển thị máu lên widget ngay sau đó, khi đó bạn sẽ phải gọi thêm một hàm set máu hiển thị. Có thể là

Với một số bạn quan tâm tới việc gọn gàng, cũng như hạn chế việc nối dây rườm rà, có thể sử dụng Expose on spawn + Instance Editable để khiến mọi thứ gọn hơn. Cụ thể như sau:

Nhớ Save và Compile.

Trong WBP_Health, ta thao tác update ở Event Construct

Lúc này quay lại chỗ Create Widget, ta chỉ cần Refresh Nodes và mọi thứ sẽ thành như sau

Không còn nối dây rườm rà và lo lắng rằng khi UpdateHealth được gọi liệu biến InitialHealth có được set chưa 😀 (dừ 99.69% nó đã được set rồi)

]]>
724