Camera xoay góc nhìn thứ ba
Assets/
Scenes/
Arena.unity
Scripts/
đã có sẵnbài này thêmbài này thay thế
Bước hai. FollowCamera nhìn từ một góc cố định — bạn không bao giờ ngó ra sau lưng Knight được. Gỡ nó khỏi Main Camera và thay bằng script này.
Camera góc nhìn thứ ba là camera gắn ở đầu một cái cần. Cần đó neo vào nhân vật; chuột xoay cái cần đó.
Chuột ngang xoay cần theo phương ngang (yaw), chuột dọc nâng hạ nó (pitch).
Bộ cần xoay
using UnityEngine;
public class OrbitCamera : MonoBehaviour
{
[SerializeField] private Transform target; // đối tượng con CameraTarget của Knight, tạo ở tab 02
[SerializeField] private float distance = 6f;
[SerializeField] private float sensitivity = 240f;
[SerializeField] private float minPitch = -25f;
[SerializeField] private float maxPitch = 65f;
[SerializeField] private LayerMask obstacles;
private float yaw;
private float pitch = 20f;
void Start()
{
Cursor.lockState = CursorLockMode.Locked; // ẩn con trỏ và giữ nó ở giữa màn hình
Cursor.visible = false;
}
void LateUpdate()
{
//cộng dồn góc ----
yaw += Input.GetAxis("Mouse X") * sensitivity * Time.deltaTime;
pitch -= Input.GetAxis("Mouse Y") * sensitivity * Time.deltaTime;
pitch = Mathf.Clamp(pitch, minPitch, maxPitch); // không cho lộn ngược
//dựng góc rồi lùi ra sau ----
Quaternion rot = Quaternion.Euler(pitch, yaw, 0f);
Vector3 pivot = target.position;
Vector3 wanted = pivot + rot * new Vector3(0f, 0f, -distance);
//kéo vào nếu vướng tường ----
float realDistance = distance;
if (Physics.SphereCast(pivot, 0.3f, (wanted - pivot).normalized,
out RaycastHit hit, distance, obstacles))
realDistance = hit.distance - 0.2f;
transform.position = pivot + rot * new Vector3(0f, 0f, -realDistance);
transform.rotation = rot;
}
public float Yaw => yaw; // để phần di chuyển biết đâu là phía trước
}Dùng pitch -= mouseY vì trong Unity pitch dương là cúi xuống. Trừ đi cho ra cảm giác chuẩn 'đẩy chuột lên là ngước lên'.
Giới hạn góc pitch là bắt buộc. Không giới hạn thì camera lộn qua đầu và cả thế giới quay ngược.
Phép rot * new Vector3(0, 0, -distance) là toàn bộ mẹo: xoay một vector lùi, ra ngay vị trí camera.
Nối vào phần di chuyển
PlayerMovement của bạn đã đọc Camera.main.transform.eulerAngles.y, nên camera này chạy được ngay — đi tới trước giờ là đi ra xa camera này.
Độ nhạy chuột đúng nghĩa
- 1
Mouse X/Y vốn đã là chênh lệch theo khung hình, nên nhân Time.deltaTime về lý thuyết là sai — nhưng nó giúp số trong Inspector ổn định giữa các mức FPS. Chọn một quy ước rồi giữ nguyên.
- 2
Đưa độ nhạy ra menu cài đặt. Mỗi người chơi có DPI chuột khác nhau.
- 3
Thêm nút đảo trục Y. Khoảng một phần năm người chơi cần nó, thiếu là họ bỏ game.
if (Input.GetKeyDown(KeyCode.Escape))
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}Lỗi hay gặp
Cất yaw và pitch vào transform.eulerAngles rồi đọc lại là hỏng phần clamp: Unity quy các góc về 0–360, nên pitch đọc ra 350 thay vì -10. Giữ hai góc trong hai field float của riêng bạn.
Một camera thứ hai mang tag MainCamera, thêm vào cho menu hay do Cinemachine tạo, khiến Camera.main trả về cái nào nó thấy trước, và hướng tới trước bị lật. Giữ đúng một tag MainCamera, hoặc đọc Yaw từ script này.
obstacles để Nothing thì SphereCast không bao giờ trúng và camera vẫn xuyên tường; đặt nó thành layer của hình khối màn chơi. Đừng bao giờ gồm cả layer Player, không thì camera trốn sau chính nhân vật.