מצלמת גוף שלישי באחדות

מצלמה מגוף שלישי היא סוג של מצלמה המוצבת מאחורי השחקן, בדרך כלל מוזזת מעט הצידה, נותנת ייצוג חזותי של רמת המשחק והשחקן עצמו.

כדי ליצור מצלמת יורה של אדם שלישי (TPS) ב-Unity נשתמש בשילוב של תנועת נגן רגילה ותצוגת גוף שלישי.

Sharp Coder נגן וידאו

שלב 1: צור את בקר הנגן

ראשית, ניצור בקר נגן שיטפל בסיבוב ובתנועה:

  • צור אובייקט משחק חדש (Game Object -> Create Empty) ותן לו שם "Player"
  • צור קפסולה חדשה (אובייקט משחק -> אובייקט תלת מימדי -> קפסולה) והזז אותה בתוך האובייקט "Player"
  • הסר את רכיב Capsule Collider מהקפסולה ושנה את מיקומו ל- (0, 1, 0)
  • צור GameObject חדש ושם לו "CameraParent" והזז אותו בתוך האובייקט "Player", שנה את מיקומו ל- (0, 1.64, 0)
  • הזז את המצלמה הראשית בתוך האובייקט "CameraParent" והזז אותה מאחורי הנגן (במקרה שלי העברתי אותה למיקום הזה: (0.5, 0.6, -2.9))

מצלמת גוף שלישי באחדות

  • צור סקריפט חדש, קרא לו SC_TPSController והדבק בתוכו את הקוד למטה:

SC_TPSController.cs

using UnityEngine;

[RequireComponent(typeof(CharacterController))]

public class SC_TPSController : MonoBehaviour
{
    public float speed = 7.5f;
    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;
    public Transform playerCameraParent;
    public float lookSpeed = 2.0f;
    public float lookXLimit = 60.0f;

    CharacterController characterController;
    Vector3 moveDirection = Vector3.zero;
    Vector2 rotation = Vector2.zero;

    [HideInInspector]
    public bool canMove = true;

    void Start()
    {
        characterController = GetComponent<CharacterController>();
        rotation.y = transform.eulerAngles.y;
    }

    void Update()
    {
        if (characterController.isGrounded)
        {
            // We are grounded, so recalculate move direction based on axes
            Vector3 forward = transform.TransformDirection(Vector3.forward);
            Vector3 right = transform.TransformDirection(Vector3.right);
            float curSpeedX = canMove ? speed * Input.GetAxis("Vertical") : 0;
            float curSpeedY = canMove ? speed * Input.GetAxis("Horizontal") : 0;
            moveDirection = (forward * curSpeedX) + (right * curSpeedY);

            if (Input.GetButton("Jump") && canMove)
            {
                moveDirection.y = jumpSpeed;
            }
        }

        // Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
        // when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
        // as an acceleration (ms^-2)
        moveDirection.y -= gravity * Time.deltaTime;

        // Move the controller
        characterController.Move(moveDirection * Time.deltaTime);

        // Player and Camera rotation
        if (canMove)
        {
            rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
            rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
            rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
            playerCameraParent.localRotation = Quaternion.Euler(rotation.x, 0, 0);
            transform.eulerAngles = new Vector2(0, rotation.y);
        }
    }
}
  • צרף את הסקריפט SC_TPSController לאובייקט "Player" (תבחין שהוא הוסיף גם רכיב נוסף בשם Character Controller. שנה את הערך המרכזי שלו ל- (0, 1, 0))
  • הקצה את האובייקט "CameraParent" למשתנה "Player Camera Parent"

שלב 2: הוסף זיהוי התנגשות במצלמה

זיהוי התנגשות מצלמה יהיה מורכב מסקריפט שיבדוק אם יש משהו בין המצלמה לנגן, ויקרב אוטומטית את המצלמה, ובכך ימנע מהמצלמה לחתוך דרך האובייקטים.

  • צור סקריפט חדש, שם לו SC_CameraCollision ואז הדבק בתוכו את הקוד למטה:

SC_CameraCollision.cs

using UnityEngine;

public class SC_CameraCollision : MonoBehaviour
{
    public Transform referenceTransform;
    public float collisionOffset = 0.3f; //To prevent Camera from clipping through Objects
    public float cameraSpeed = 15f; //How fast the Camera should snap into position if there are no obstacles

    Vector3 defaultPos;
    Vector3 directionNormalized;
    Transform parentTransform;
    float defaultDistance;

    // Start is called before the first frame update
    void Start()
    {
        defaultPos = transform.localPosition;
        directionNormalized = defaultPos.normalized;
        parentTransform = transform.parent;
        defaultDistance = Vector3.Distance(defaultPos, Vector3.zero);

        //Lock cursor
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    // LateUpdate is called after Update
    void LateUpdate()
    {
        Vector3 currentPos = defaultPos;
        RaycastHit hit;
        Vector3 dirTmp = parentTransform.TransformPoint(defaultPos) - referenceTransform.position;
        if (Physics.SphereCast(referenceTransform.position, collisionOffset, dirTmp, out hit, defaultDistance))
        {
            currentPos = (directionNormalized * (hit.distance - collisionOffset));

            transform.localPosition = currentPos;
        }
        else
        {
            transform.localPosition = Vector3.Lerp(transform.localPosition, currentPos, Time.deltaTime * cameraSpeed);
        }
    }
}
  • צרף את הסקריפט SC_CameraCollision למצלמה הראשית
  • הקצה את האובייקט "CameraParent" למשתנה "Reference Transform"
  • כוונן את ערכי "Collision Offset" ו-"Camera Speed" למקרה שהמצלמה חוצה את הקירות

מצלמת TPS מוכנה כעת, הקש על הפעל כדי לבדוק אותה.

מָקוֹר
TPSCamera.unitypackage172.07 KB