Bạn có thể nhập các lưới tùy chỉnh để tạo ra mọi thứ từ NPC đến một mảnh vải hoạt hình của một chiếc thuyền buồm. Chúng tôi đã sử dụng cài đặt tùy chỉnh của Trình nhập để đưa vào những nhân vật tùy chỉnh kỳ lạ hơn, như những sinh vật lỗ đen bí ẩn và những con rô-bốt phục vụ thân thiện, nếu không nhận thức được.
Các phần sau sẽ trình bày cách chúng tôi đã sử dụng rigging và skinning, PBR (bề mặt), và VFX để xây dựng một trong những nhân vật phức tạp hơn mà chúng tôi gọi là "Sinh vật." Chúng tôi muốn nó phát sáng, phát ra một số ánh sáng, có những vệt khói hạt, và chuyển động mượt mà liên quan đến việc skin một rig với đủ khớp để tạo ra những làn sóng thuyết phục của các xúc tu của nó.

Rig
Khi chúng tôi đang rigging Sinh vật, chúng tôi thấy tốt nhất là mô hình nhân vật ở tư thế trung lập, vì tư thế đó phù hợp nhất để uốn cong theo nhiều hướng. Nếu chúng tôi mô hình Sinh vật với các xúc tu đã cuộn lại, điều đó sẽ dẫn đến việc kéo dài nếu chúng tôi hoạt hình các xúc tu để uốn cong theo hướng ngược lại. Các ảnh chụp màn hình sau đây cho thấy Sinh vật trong trạng thái tự nhiên của nó:


Từ một tư thế trung lập, chúng tôi đã thêm các khớp một cách tiết kiệm, tập trung vào những khu vực cần nhiều chuyển động nhất. Càng ít khớp càng tốt, vì bạn sẽ phải quản lý chúng khi skin nhân vật của mình, và bạn sẽ có ít thứ hơn để điều khiển khi bạn hoạt hình chúng. Trong các ảnh chụp màn hình trước đó, Sinh vật trông như có rất nhiều khớp ở giữa, nhưng phần thân chính chỉ có một khớp.
Hầu hết các khớp khác nằm gần các xúc tu và hàm. Với các xúc tu, chúng tôi muốn có nhiều chuyển động thứ cấp, hoặc chuyển động được xếp lớp, để tạo ra hiệu ứng thuyết phục rằng chúng đang di chuyển độc lập. Tuy nhiên, khối lượng trung tâm của các xúc tu quá gần nhau đến mức cảm thấy lãng phí khi tạo khớp cho tất cả chúng, cả về hiệu suất và công sức để hoạt hình. Vì vậy, thay vào đó, chúng tôi đã coi khối lượng trung tâm như một xúc tu lớn duy nhất với những "đuôi" nhỏ hơn nơi các đầu rời khỏi khối lượng trung tâm.

Chúng tôi thấy các hướng dẫn sau đây hữu ích, để đảm bảo rằng lưới nhân vật được nhập đúng vào Studio:
- Các khớp và xương riêng lẻ phải có tên duy nhất.
- Các lưới không được có cùng tên với các khớp và xương.
- Các lưới nên không có biến đổi trước khi skin/binding; nói cách khác, các biến đổi nên là 0 và tỷ lệ nên là 1.
- Các mặt phẳng của lưới nên hướng ra ngoài (mô hình không nên nhìn bên trong ra ngoài).
- Các bộ xương không nên có bất kỳ yếu tố tỷ lệ nào; tất cả các khớp nên là [1, 1, 1].
Skin
Khi chúng tôi hoàn thành bộ xương của Sinh vật, bước tiếp theo là skin lưới. Skinning có thể là một nhiệm vụ khó khăn, vì vậy để làm cho mọi thứ dễ dàng hơn, tốt nhất là bạn nên quen thuộc với các cài đặt skinning ban đầu khác nhau của ứng dụng DCC của bạn để tìm ra cái mà bạn thích. Vì đây là một nhân vật hữu cơ, chúng tôi đã skin nó với nhiều độ giảm ở mỗi khớp và chồng chéo giữa chúng. Bằng cách này, việc uốn cong cảm thấy mượt mà chứ không sắc nét. Các ảnh chụp màn hình sau đây cho thấy skinning kém và skinning mượt mà tương ứng:


Chúng tôi thấy các hướng dẫn sau đây tạo ra kết quả tốt nhất cho skinning:
- Các ảnh hưởng skinning (có nghĩa là chúng ảnh hưởng đến một phần của mô hình khi di chuyển) nên tối đa là 4 ảnh hưởng cho mỗi đỉnh.
- Tên khớp và lưới cần phải duy nhất, cả trong và giữa nhau.
- Bất kỳ khớp nào bạn muốn nhập vào Studio phải có một số ảnh hưởng đến skinning của mô hình, nếu không thì engine sẽ không nhập nó. Bất cứ khi nào có thể, hãy skin mô hình của bạn ở tư thế ban đầu hoặc "bind".
Nhập lưới vào Studio
Nhập các nhân vật tùy chỉnh của bạn vào Studio là một trong những phần thú vị hơn của quá trình, vì bạn sẽ thấy những sáng tạo của mình trong trò chơi mà bạn đang xây dựng!
Để nhập lưới vào Studio:
Xuất nhân vật từ ứng dụng DCC và đảm bảo các điều sau:
- Tất cả các mặt phẳng, tỷ lệ và tên đều chính xác.
- Nhân vật có tất cả cấu trúc khớp và xương và tất cả các lưới.
- Các lưới đều dưới 10.000 tam giác cho mỗi phần của lưới.
- Tổng kích thước lưới không vượt quá 2000 đơn vị trên bất kỳ trục nào.
- Xem Yêu cầu Lưới để có danh sách đầy đủ các thông số mô hình.

Trong Trình nhập, nhập tệp .fbx hoặc .obj tùy chỉnh.

Làm cho sinh vật phát sáng
Khi mô hình của Sinh vật đã ổn định và không cần nhập thêm vào Studio, chúng tôi bắt đầu lắp ráp các đối tượng SurfaceAppearance, đèn và hiệu ứng hình ảnh. Chúng tôi đã làm điều này để đảm bảo rằng chất lượng của mô hình đủ tốt trước khi tiếp tục đặt và chỉnh sửa bất kỳ khía cạnh nào của nó.

Chúng tôi biết rằng chúng tôi muốn Sinh vật có màu tối, và các điểm nhấn là đôi mắt và các xúc tu "nắm bắt" của nó. Các điểm tương phản cao thường thu hút sự chú ý, vì vậy việc có một vài điểm mạnh sẽ đảm bảo người xem biết nên tập trung vào đâu. Studio hỗ trợ các vật liệu neon tự phát sáng, vì vậy ngay từ đầu chúng tôi đã tách đôi mắt ra để chúng có thể là vật liệu riêng biệt với phần còn lại của nhân vật. Chúng tôi đã làm điều tương tự cho các xúc tu, để chúng chỉ phát sáng ở đầu.

Vật liệu neon không phát ra ánh sáng thực, vì vậy sau một số thử nghiệm, chúng tôi đã thêm các phần riêng biệt để kiểm soát vị trí và hướng phát ra ánh sáng. Điều này đảm bảo rằng ánh sáng được hướng theo cách để tăng cường độ sáng của đôi mắt và cũng phát ra nguồn ánh sáng riêng của nó.

Lưu ý rằng các SpotLights thêm hiệu ứng hình ảnh cho Sinh vật gần các bề mặt khác hoặc một người chơi.

Ngoài ra, chúng tôi muốn các xúc tu của Sinh vật phát ra một số hạt, để nó có thể để lại một vệt khói khi di chuyển. Bởi vì các xúc tu rất dài, việc thêm ParticleEmitter vào toàn bộ xúc tu sẽ khiến các hạt phát ra từ toàn bộ xúc tu thay vì từ đầu. Để khắc phục điều này, chúng tôi đã sử dụng một phần nhỏ được đặt gần đầu của xúc tu, để chúng tôi có thể kiểm soát kích thước phát ra, vị trí và hướng của các hạt.

Làm cho VFX theo dõi nhân vật
Các vị trí lưới của nhân vật đã được skin không được cập nhật khi Sinh vật hoạt hình, vì vậy chúng tôi cần một phương pháp để đảm bảo rằng VFX, SFX và ánh sáng đều theo dõi đúng Sinh vật. Để thực hiện điều này, chúng tôi đã tạo một kịch bản điều khiển VFX và sử dụng CollectionService để thông báo cho các phần chứa VFX nơi các khớp của sinh vật nằm và theo dõi chúng.
Chúng tôi đã đặt LocalScript sau vào StarterPlayer → StarterPlayerScripts. Điều này về cơ bản chạy chức năng cập nhật VFX.
Kịch bản Địa phương-- Thêm đoạn mã này vào một kịch bản địa phương hiện có mà tạo kết nối PreSimulationlocal RunService = game:GetService("RunService")local vfx = require(workspace.VfxUpdateModule)RunService.PreSimulation:Connect(vfx.updateVfx)Kịch bản Mô-đun-- Mô-đun này gắn các phần vào hoạt hình để chúng được cập nhật khi-- hoạt hình phát. Đây là một giải pháp thay thế cho các hạn chế hiện tại-- với Khớp và Xương và sẽ không luôn cần thiết.---- Điều kiện tiên quyết:-- Để được bao gồm, các mô hình cần có thẻ "AnimatedVfxModel", và một thư mục-- chứa tất cả các phần mà bạn muốn đồng bộ với hoạt hình. Mỗi phần cần-- một thuộc tính gọi là "AttachedBoneName" tham chiếu đến tên của-- xương mà bạn muốn gắn vào. Các phần cũng nên đã ở trong vị trí-- chính xác của chúng tương đối với xương mong muốn.---- Cách sử dụng:-- Một LocalScript nên yêu cầu mô-đun này, sau đó kết nối-- VfxUpdateModule.updateVfx với sự kiện RunService.PreSimulation.local VfxUpdateModule = {}local CollectionService = game:GetService("CollectionService")-- CÀI ĐẶT - điều này nên chạy một lần trên mỗi client.-- Thu thập tất cả các mô hình có thẻlocal vfxModels = CollectionService:GetTagged("AnimatedVfxModel")local vfxTable = {} -- nơi chúng tôi sẽ lưu trữ tất cả các phần và độ lệch-- Gán một bảng cho mỗi mô hình sẽ chứa tất cả các phần vfx và độ lệchfor _, model in vfxModels dovfxTable[model] = {}local vfxParts = model:FindFirstChild("VFX"):GetChildren() -- Tìm thư mục VFX-- Tìm xương qua thuộc tính và tính toán độ lệch cho mỗi phần.for _,part in vfxParts dolocal name = part:GetAttribute("AttachedBoneName")local bone = model:FindFirstChild(name, true)if bone thenlocal offset = (bone.TransformedWorldCFrame:inverse() * part.CFrame)vfxTable[model][part] = {bone, offset}elsewarn("Phần Vfx tham chiếu đến xương không thể tìm thấy.")endendendprint(vfxTable)-- CẬP NHẬT - Điều này nên được liên kết với PreSimulation của RunService trên mỗi client-- Đi qua tất cả các mô hình, sau đó cập nhật tất cả các phần trên mô hình để khớp với bonecframe.function VfxUpdateModule.updateVfx()for model, vfxParts in vfxTable dofor part, bone in vfxParts dopart.CFrame = bone[1].TransformedWorldCFrame * bone[2]endendendreturn VfxUpdateModuleChúng tôi đã tạo một VFXUpdateModule ModuleScript để thông báo cho bất kỳ đối tượng nào được gán thẻ thích hợp với AnimatedVfxModel để cập nhật trong sự kiện chơi.
Chúng tôi đã gán các nhóm mô hình cần thiết với AnimatedVfxModel bằng cách sử dụng phần Thẻ trong thuộc tính của nó. Việc sử dụng thẻ cho phép VFXUpdateModule biết đối tượng nào cần tìm kiếm như là đứa trẻ VFX đầu tiên và áp dụng cập nhật.

Cuối cùng, chúng tôi đã thêm một thuộc tính tùy chỉnh AttachedBoneName vào phần mà chúng tôi muốn hoạt hình và thêm tên chính xác của khớp mà chúng tôi muốn nó theo dõi.
Tạo kết cấu cho sinh vật
Tiếp theo, chúng tôi đã thiết lập các bản đồ kết cấu PBR (Physically Based Rendered). Những bitmap mạnh mẽ này mang lại cho sinh vật độ bóng và biến thể bề mặt khác nhau để làm cho nó trông như có nhiều vết sần và khuyết điểm nhỏ. Hiệu ứng hình ảnh này giúp bán được vẻ ngoài của Sinh vật khi nó gần người chơi hơn.

Dưới đây là cách chúng tôi tạo ra các bản đồ kết cấu bề mặt:
Các bản đồ kết cấu cho nhân vật này đều nằm trên một "tấm" cho mỗi bản đồ. Điều này làm cho sinh vật hiệu quả hơn và có nghĩa là chúng tôi phải xử lý ít bản đồ kết cấu hoặc các đối tượng SurfaceAppearance hơn.




Đối với các khu vực cần phát sáng hoặc tự phát sáng, chẳng hạn như "các xúc tu nắm bắt," chúng tôi cũng đã sử dụng độ trong suốt trên SurfaceAppearance để hòa trộn với những phần đó.

Chúng tôi thấy hữu ích khi tuân theo các hướng dẫn này khi tạo các bản đồ kết cấu bề mặt:
- Đảm bảo rằng các bản đồ của bạn không lớn hơn 1024×1024.
- Kênh xanh của bạn có thể cần được lật tùy thuộc vào ứng dụng mà bạn đã làm việc.
Hoạt hình sinh vật
Hoạt hình là rất chủ quan và có phong cách cá nhân. Các tùy chọn bao gồm ghi hình chuyển động, hoạt hình "key frame" bằng tay trong ứng dụng DCC của bạn, hoặc sử dụng Animation Editor mạnh mẽ của Studio.
Như chúng tôi đã đề cập trước đó, chúng tôi muốn đảm bảo rằng chúng tôi có đủ khớp cho chuyển động mượt mà cũng như đủ chi, để hoạt hình sinh vật cảm thấy tự nhiên và "xếp lớp." Xếp lớp, còn được gọi là chuyển động thứ cấp, là điều bạn thấy trong cuộc sống hàng ngày — khi bạn ném cánh tay ra, mỗi khớp đều phản ứng với xung lực ban đầu từ cánh tay trên của bạn, và mỗi khớp trong cơ thể bạn không di chuyển hoặc nghỉ ngơi cùng một lúc.
Chúng tôi đã sử dụng kỹ thuật này để hoạt hình Sinh vật cảm thấy như các chi đang phản ứng với chuyển động do cơ thể của nó điều khiển như được thể hiện ở đây:

Nếu sử dụng một ứng dụng DCC bên ngoài để hoạt hình, chúng tôi thấy các hướng dẫn sau đây hoạt động tốt nhất:
- Đặt tỷ lệ khung hình ít nhất là 30 FPS.
- Tạo các hoạt hình của bạn với cùng một nhân vật mà bạn đang áp dụng cho nó.
- Xuất dữ liệu hoạt hình của bạn dưới dạng tệp .fbx riêng biệt.
Bởi vì chúng tôi đã hoạt hình nhân vật bên ngoài Studio, chúng tôi cần sử dụng Animation Editor để nhập tệp hoạt hình .fbx. Trình chỉnh sửa cho phép bạn chọn bất kỳ hình đại diện nào có khớp hoặc động cơ và điều khiển chúng qua các điểm trong dòng thời gian.
Để nhập một hoạt hình:
Trong tab Avatar trên thanh công cụ, nhấp vào Clip Editor.
Chọn nhân vật đã được rig mà bạn muốn hoạt hình trong Roblox. Nhân vật nên là nhân vật mà bạn đang rig trong ứng dụng DCC bên ngoài của bạn.
Nhấp vào nút ⋯ ở phần trên bên trái của cửa sổ trình chỉnh sửa, chọn Import From FBX Animation, và tìm tệp hoạt hình .fbx đã xuất của bạn.

Khi bạn hài lòng với hoạt hình của mình, bạn có thể xuất nó để khám phá ID hoạt hình, mà bạn có thể sử dụng trong các kịch bản Roblox để chạy chúng. Ví dụ, bạn có thể thêm một Script vào nhóm mô hình của nhân vật đã nhập và sử dụng mã sau để chạy hoạt hình:
local animationId = "YOUR_ANIMATION_ID"local char = script.Parentlocal animController = char:FindFirstChildWhichIsA("Humanoid") or char:FindFirstChildOfClass("AnimationController")local animation = Instance.new("Animation")animation.AnimationId = "rbxassetid://" .. tostring(animationId)local animTrack = animController:LoadAnimation(animation)animTrack:Play(0, 1, 1)
Kết quả cuối cùng
Sau một vài điều chỉnh hoàn thiện về màu sắc, độ sáng của ánh sáng, và một số hiệu ứng hạt nữa để tạo ra hiệu ứng hào quang mạnh mẽ hơn trước các cửa sổ, đây là kết quả cuối cùng trong trạm không gian!
