Tự xử lý trọng lực
Thuộc phần Xây dựng trò chơi thực tế trong hành trình Unity của Coddy. Bài học 39 trên 60.
Một CharacterController chỉ rơi khi script khiến nó rơi, và khi rơi thật, tốc độ sẽ tăng dần: trọng lực cộng thêm khoảng 9.81 đơn vị mỗi giây vào tốc độ rơi sau mỗi giây. Vì vậy, script lưu tốc độ theo chiều dọc trong một trường, mỗi khung hình cộng thêm gravity * Time.deltaTime vào đó, rồi dùng tốc độ này để di chuyển trong cùng lệnh Move với bước đi:
public float gravity = -9.81f;
float verticalSpeed;
void Update()
{
if (controller.isGrounded && verticalSpeed < 0f)
{
verticalSpeed = -2f; // Khi chạm đất: dừng rơi, duy trì lực đẩy nhẹ xuống dưới
}
verticalSpeed += gravity * Time.deltaTime;
Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
move.y = verticalSpeed;
controller.Move(move * Time.deltaTime);
}Time.deltaTime xuất hiện hai lần cho hai việc: gravity * Time.deltaTime là lượng tốc độ tăng thêm trong khung hình này, còn tốc độ nhân với Time.deltaTime là quãng đường di chuyển trong khung hình này. Tốc độ được lưu trong một trường vì nó cần được giữ nguyên qua các khung hình; biến cục bộ sẽ bắt đầu lại từ 0 ở mỗi khung hình. Khi rơi từ trạng thái đứng yên, sau nửa giây, tốc độ của bộ điều khiển là -4.9 đơn vị mỗi giây, và sau một giây là -9.81.
Việc đặt lại cũng quan trọng như việc rơi. Khi ở trên sàn, Move dừng bộ điều khiển, nhưng không có gì dừng trường này: nếu không đặt lại, giá trị sẽ tiếp tục tăng khi người chơi đứng yên, và khi bước khỏi mép vực, người chơi sẽ rơi xuống với tốc độ tối đa. Giá trị được đặt lại thành một số âm nhỏ thay vì 0 để mỗi Move vẫn đẩy bộ điều khiển xuống sàn: ở tốc độ khung hình cao, lực đẩy do trọng lực trong một khung hình có thể ngắn hơn Min Move Distance, khiến Move không làm gì và isGrounded chuyển thành false. isGrounded được đọc trước Move, nên nó mô tả Move của khung hình trước.
Thử thách
Trung bìnhThêm trọng lực cho thợ lặn để tốc độ rơi tăng dần.
- Ở đầu
Update(), khicontroller.isGroundedvàverticalSpeed < 0f, đặtverticalSpeed = -1f;. - Cộng
gravity * Time.deltaTimevào biến này, rồi giữ giá trị của nó ở mức-maxFalltrở lên bằngMathf.Max. - Trước dòng
controller.Move, đặtmove.y = verticalSpeed;.
Nhấn Chơi rồi bước khỏi tòa tháp: tốc độ rơi tăng lên đến 10 đơn vị mỗi giây. Sau đó nhấn Kiểm tra.
Tự làm thử
using UnityEngine;
public class Diver : MonoBehaviour
{
public float speed = 4f;
public float gravity = -12f;
public float maxFall = 10f;
CharacterController controller;
float verticalSpeed;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
// Trọng lực: đặt lại verticalSpeed khi chạm đất, cộng thêm gia tốc trọng trường, giới hạn tốc độ rơi rồi gán vào move.y
Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
controller.Move(move * Time.deltaTime);
}
}
Tất cả bài học trong Xây dựng trò chơi thực tế
1Văn bản trên màn hình
Canvas và văn bảnHiển thị điểm sốĐịnh dạng sốĐồng hồ đếm ngượcÔn tập: Đồng hồ tốc độ7Điều khiển thời gian
Tạm dừng bằng timeScaleChuyển động chậmThời gian không bị co giãnÔn tập: Bullet Time2Nút bấm và màn hình
Nút bấm và onClickLambdaKết nối trong InspectorBật và tắt bảngThanh máuÔn tập: Cửa hàng nâng cấp5Lưu dữ liệu với PlayerPrefs
Lưu một sốTải với giá trị mặc địnhĐiểm cao nhấtLưu cài đặtÔn tập: Tiền xu trong ngân hàng8Bộ điều khiển nhân vật
CharacterController.MoveTự xử lý trọng lựcNhảyĐẩy vật thểDi chuyển theo hướng nhìnÔn tập: nhảy képTự luyện tập: Playground Unity