unreal engine – Jake Tee https://jakesto.com Game Dev Blog Sun, 19 Nov 2023 02:53:14 +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 unreal engine – Jake Tee https://jakesto.com 32 32 194548219 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 – 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
101 Tips – Event collision khi overlap particle https://jakesto.com/101-tips-event-collision-khi-overlap-particle/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-event-collision-khi-overlap-particle Sun, 13 Feb 2022 03:43:37 +0000 https://jakesto.com/?p=852 Nếu mọi người đã quen với Event Begin Overlap hay Event Component Begin Overlap thì Event Particle Collide của particle cũng tương tự như thế, nó sẽ gọi khi 1 actor overlap vào particle.

Một ví dụ cho việc sử dụng On Particle Collide đó là lửa của molotov trong CS:GO

Trong ví dụ lần này mình sẽ sử dụng particle lửa trong Starter Content của Unreal Engine.

Để thuận tiện cho sử dụng, ta nên duplicate P_Fire thành P_FireCollision.

Mở P_FireCollision lên, và thêm module Actor Collision vào cái emitter.

  • Damping factor: particle sẽ nhả emitter chậm lại bao nhiêu khi bị collide. Hiện tại mình để giá trị cố định là 1 cho đơn giản.
  • Max Collisions: số lượng collision tối đa, mình để là 1 để tránh trigger quá nhiều event
  • Collision Types: ObjectType là particle sẽ tương tác, mình set thành Pawn để tương tác với nhân vật điều khiển.

Ngoài ra để cho test, mình cũng tắt Collide Only if Visible đi và tăng Max Collision Distance lên 100m.

Như vậy đã xong phần setup của Particle, kế đến ta cần một actor để xử lí event overlap. Đơn giản tạo một actor mới và đặt tên là BP_FireActor. Actor sẽ có một component đó là ParticleSystem, được set Template thành P_FireCollision ta tạo trên.

Ở mục Events của ParticleSystem, click chọn On Particle Collide.

Mình setup cho nó sẽ in ra màn hình Burning để test nhé. Sau đó compile và thả actor vào level.

Kết quả:

Lưu ý: particle sẽ trigger collide liên tục do emitter được chạy liên tục, để tránh xử lí event quá nhiều các bạn có thể thêm delay hoặc timer nhé.

]]>
852
101 Tips – Delay cho AI Task https://jakesto.com/101-ai-delay-task/?utm_source=rss&utm_medium=rss&utm_campaign=101-ai-delay-task Sun, 05 Dec 2021 01:11:01 +0000 https://jakesto.com/?p=843 Mọi người có lẽ đều quen biết node Delay để dừng flow logic trong blueprint, tuy nhiên khi sử dụng trong BlueprintTask cho hành vi AI thì dường như nó không hoạt động. Thể làm thế nào để delay một hay nhiều chuỗi logic trong Task ?

Cùng coi ví dụ một Task setup dưới đây. Trước hết cần 2 event sau:
Event Execute AI

Event Tick AI

Nếu bạn không biết tìm Event trên ở đâu thì các bạn tìm đến Override ở vùng Functions

Sau đó tiếp tục tạo 2 biến float lần lượt:

  • CurrentDelay: sẽ lưu thời gian delay hiện tại, thay đổi theo tick
  • Delay: thời gian delay mặc định tối đa. Khi sửa ta sẽ sửa giá trị này

Đối với Delay, tick chọn Instance Editable để có thể sửa trực tiếp trên Task khi đặt ở BehaviorTree.

Khi Event Receive Execute AI được gọi, ta set giá trị ban đầu cho biến CurrentDelay:

Kế đến, ở Event Receive Tick AI, ta chỉ việc giảm giá trị CurrentDelay theo từng tick cho tới khi giá trị bé hơn hoặc bằng 0:

Như vậy là đã xong Delay cho Task. Khi Task được gọi xong nhớ lưu ý Finish Execute Success để Task không kẹt nhé.

]]>
843
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 – Khắc phục tình trạng mặt phẳng dưới đen https://jakesto.com/101-tips-khac-phuc-tinh-trang-mat-phang-duoi-den/?utm_source=rss&utm_medium=rss&utm_campaign=101-tips-khac-phuc-tinh-trang-mat-phang-duoi-den Thu, 19 Nov 2020 17:04:37 +0000 https://jakesto.com/?p=758 Hôm nay dựng scene bị vướng phải mỗi lỗi khá là khó chịu, khi sử dụng dynamic skylight và dynamic directional light, đó là mặt phía dưới của bất kì object nào đều đen thui

Mặc dù đã chỉnh cường độ ánh sáng các kiểu, tăng indirect light intensity nhưng đều không hiệu quả (có lẽ indirect light chỉ dành cho baked lightning).

Loay hoay một hồi tìm hiểu thì mới phát hiện ra rằng, ở skylight có một cái biến được dấu khá kĩ tên là Lower Hemisphere Is Solid Color được bật mặc định.

Theo chú thích của UE thì khi bật lên, những mặt phẳng ngược ánh sáng mặt trời sẽ được set sang màu sắc được định bởi biến Lower Hemisphere Color (được mặc định là thuần đen).

Như vậy để giải quyết vấn đề, cách nhanh nhất là ta có thể tắt biến Lower Hemisphere Is Solid Color đi là xong. Khi này ánh sáng sẽ được tính toán đúng như ánh sáng môi trường

Hoặc các bạn có thể set Lower Hemisphere Color sang một khác sáng hơn, ví dụ như là màu trắng gốc:

Như vậy là xong, loay hoay cả buổi mới ngộ ra cái quỷ này =)) Chúc anh em không bị như mình.

]]>
758
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
Tối ưu hóa thời gian load và bộ nhớ RAM https://jakesto.com/toi-uu-hoa-thoi-gian-load-va-bo-nho-ram/?utm_source=rss&utm_medium=rss&utm_campaign=toi-uu-hoa-thoi-gian-load-va-bo-nho-ram Sun, 20 Sep 2020 15:28:51 +0000 https://jakesto.com/?p=702 Chắc hẳn mọi người đã quen với reference thông thường, hay còn gọi là hard-reference. Hard-reference khá là phổ biến ở UE bởi tính tiện dụng cũng như là khả năng load reference từ bộ nhớ đệm lên một cách nhanh chóng.

Tuy nhiên, nhược điểm to lớn nhất là của hard reference chính là việc mọi thứ đều sẽ được đưa vào hết bộ nhớ tạm thời (RAM), để có thể tiện access nhanh hơn. Dẫn đến việc đó là nếu một object A, chỏ tới Object B, Object B dùng Object C, thì tất cả đều sẽ được tải lên hết và lưu vào RAM.

Cách nhanh nhất để coi xem một actor đang được chỏ tới ở đâu, đó là chuột phải object đó phải chọn Reference Viewer hoặc tổ hợp phím Alt+Shift+R

Ảnh 1. Reference viewer trong option menu của một actor

Và thông thường sẽ thấy như sau, actor chính sẽ nằm ở giữa:

Ảnh 2. Reference của BP_MyCharacter

Để cho dễ hiểu, khi BP_MyCharacter được sử dụng, thì tất cả những thằng xung quanh cũng sẽ được tải lên cùng.

Để giải quyết việc này, ta sẽ sử dụng Soft Pointer ReferenceSoft Pointer Class Reference.

Nếu project của bạn nhẹ và không phải lo lắng về memory thì có lẽ việc sử dụng Soft Pointer Reference không cần thiết.

Nhưng ví dụ bạn sử dụng nhiều hard reference, mỗi reference đều nặng thì bạn nên xem xét chuyển sang Soft Pointer Reference.

Một ví dụ cho thấy việc dùng hard reference vừa lợi vừa hại:

Giả sử như class nhân vật bạn trong quá trình sử dụng có thể spawn ra class vũ khí, thuốc thang, thức ăn,..

Cấu trúc của class nhân vật có thể như sau

Ảnh 3. Spawn class vũ khí, thực phẩm và thuốc

Như vậy, nếu như Medicine có một loạt các hình ảnh hiển thị (HUD), mesh viên thuốc, hiệu ứng, âm thanh,.. thì tất cả mọi thứ đều sẽ được lưu vào RAM bất cứ khi nào nhân vật được dùng.

Tuy nhiên đổi lại, khi ta cần sử dụng medicine, việc truy xuất lên để sử dụng sẽ cực kì nhanh (nhờ lưu ở RAM).

Ảnh 4. 3 actor mới hiển thị trong reference viewer

Bây giờ hãy thử chuyển tất cả qua Soft Pointer Class Reference

Trước khi ta gọi Spawn Actor From Class, hãy load class đó từ dưới ổ lưu trữ lên trước bằng Async Load Class Asset

Ảnh 5. Load Soft Class Reference

Sau khi load xong, bởi vì Spawn Actor yêu cầu một Actor Class, ta chỉ việc cast vào Actor Class và nối vào đầu Class là xong. Làm tương tự với Weapon và Medicine.

Lưu ý: Async Load Class Asset là hàm latent, chạy song song với thread chính. Nếu bạn cho thực thi hành động ở đầu nối trên cùng, thì nếu việc load chưa xong nhưng bạn lại sử dụng kết quả trả lại Class thì sẽ thất bại. Đầu nối Completed sẽ luôn được gọi sau khi quá trình load đã xong.

Và khi đó khi kiểm tra lại Reference Viewer, Food/Medicine/Weapon đã không còn được hard reference nữa

Ảnh 6. Hard reference của Food/Medicine/Weapon đã không còn

Như vậy ta đã bớt đi một phần lưu trữ bộ nhớ của Food/Medicine/Weapon, và chỉ tải lên cái nào cần thiết sử dụng.

Lưu ý: Sau khi load lên để sử dụng, sau một thời gian nếu không còn gì sử dụng nó, UE sẽ tự garbage collect đi.

Tương tự như với Soft Pointer Reference

Ảnh 7. Ví dụ Async load một static mesh từ disk

Ở ví dụ trên là mình chỉ việc chọn Static Mesh mình muốn load ở mục Asset, và sau đó cast vào StaticMesh để sử dụng bình thường.

]]>
702