Đồng bộ hóa các vật thể cứng qua mạng bằng PUN 2

Đồng bộ hóa các đối tượng trong PUN 2 rất đơn giản, nhưng còn việc đồng bộ hóa các vật thể cứng thì sao?

Không giống như GameObject thông thường, Rigidbody cũng bị ảnh hưởng bởi Gravity (nếu không phải là Kinetic) và các đối tượng khác. Vì vậy, thay vì chỉ đồng bộ hóa Biến đổi của đối tượng, chúng ta cũng cần đồng bộ hóa một vài tham số bổ sung, chẳng hạn như velocityangularVelocity.

Trong bài đăng này, tôi sẽ trình bày cách tạo các Rigidbody tương tác có thể bị ảnh hưởng bởi mọi Người chơi trong Phòng và được đồng bộ hóa qua Mạng.

Unity phiên bản được sử dụng trong hướng dẫn này: Unity 2018.3.0f2 (64-bit)

Phần 1: Ví dụ thiết lập PUN 2 và nhiều người chơi

Chúng tôi đã có hướng dẫn về cách thiết lập ví dụ nhiều người chơi bằng PUN 2, hãy xem liên kết bên dưới:

Tạo trò chơi nhiều người chơi trong Unity 3D bằng PUN 2

Hãy quay lại sau khi bạn thiết lập xong dự án nhiều người chơi để chúng ta có thể tiếp tục.

Ngoài ra, bạn có thể tiết kiệm thời gian bằng cách lấy dự án nguồn từ here.

Phần 2: Thêm các vật cứng tương tác

Nếu bạn làm theo hướng dẫn ở trên thì bây giờ bạn sẽ có 2 Cảnh "GameLobby" và "GameLevel"

  • Mở Cảnh "GameLevel" và tạo một vài Khối (GameObject -> Đối tượng 3D -> Khối)

  • Thêm thành phần Rigidbody vào mỗi khối
  • Thêm thành phần PhotonView vào mỗi khối

Bây giờ chúng ta cần tạo một Tập lệnh mới sẽ đồng bộ hóa các Rigidbody qua mạng.

  • Tạo một Tập lệnh mới và gọi nó là PUN2_RigidbodySync

PUN2_RigidbodySync.cs

using UnityEngine;
using Photon.Pun;

public class PUN2_RigidbodySync : MonoBehaviourPun, IPunObservable
{

    Rigidbody r;

    Vector3 latestPos;
    Quaternion latestRot;
    Vector3 velocity;
    Vector3 angularVelocity;

    bool valuesReceived = false;

    // Start is called before the first frame update
    void Start()
    {
        r = GetComponent<Rigidbody>();
    }

    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.IsWriting)
        {
            //We own this player: send the others our data
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
            stream.SendNext(r.velocity);
            stream.SendNext(r.angularVelocity);
        }
        else
        {
            //Network player, receive data
            latestPos = (Vector3)stream.ReceiveNext();
            latestRot = (Quaternion)stream.ReceiveNext();
            velocity = (Vector3)stream.ReceiveNext();
            angularVelocity = (Vector3)stream.ReceiveNext();

            valuesReceived = true;
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (!photonView.IsMine && valuesReceived)
        {
            //Update Object position and Rigidbody parameters
            transform.position = Vector3.Lerp(transform.position, latestPos, Time.deltaTime * 5);
            transform.rotation = Quaternion.Lerp(transform.rotation, latestRot, Time.deltaTime * 5);
            r.velocity = velocity;
            r.angularVelocity = angularVelocity;
        }
    }

    void OnCollisionEnter(Collision contact)
    {
        if (!photonView.IsMine)
        {
            Transform collisionObjectRoot = contact.transform.root;
            if (collisionObjectRoot.CompareTag("Player"))
            {
                //Transfer PhotonView of Rigidbody to our local player
                photonView.TransferOwnership(PhotonNetwork.LocalPlayer);
            }
        }
    }
}
  • Đính kèm PUN2_RigidbodySync cho cả hai Khối và cũng gán nó cho Photon View "Observed Components":

Chúng tôi cũng cần thực hiện một số thay đổi đối với tập lệnh PUN2_PlayerSync từ hướng dẫn Nhiều người chơi:

  • Mở PUN2_PlayerSync.cs
  • Trong void Start(), bên trong if(photonView.IsMine) thêm mã này:
            //Player is local
            gameObject.tag = "Player";
            //Add Rigidbody to make the player interact with rigidbody
            Rigidbody r = gameObject.AddComponent<Rigidbody>();
            r.isKinematic = true;

Vì vậy, bây giờ void Start() sẽ trông như thế này:

    // Use this for initialization
    void Start()
    {
        if (photonView.IsMine)
        {
            //Player is local
            gameObject.tag = "Player";
            //Add Rigidbody to make the player interact with rigidbody
            Rigidbody r = gameObject.AddComponent<Rigidbody>();
            r.isKinematic = true;
        }
        else
        {
            //Player is Remote, deactivate the scripts and object that should only be enabled for the local player
            for (int i = 0; i < localScripts.Length; i++)
            {
                localScripts[i].enabled = false;
            }
            for (int i = 0; i < localObjects.Length; i++)
            {
                localObjects[i].SetActive(false);
            }
        }
    }

Bằng cách thêm thành phần Rigidbody, chúng tôi đảm bảo rằng phiên bản trình phát có thể tương tác với các Rigidbody khác và bằng cách thay đổi thẻ thành "Player", chúng tôi có thể phát hiện xem đó có phải là phiên bản cục bộ đã va chạm với Rigidbody hay không.

  • Lưu Cảnh GameLevel sau khi mọi thứ hoàn tất.

Bây giờ hãy xây dựng và kiểm tra nó!

Sharp Coder Trình phát video

Mọi thứ hoạt động như mong đợi, giờ đây Rigidbody có thể được đồng bộ hóa qua Mạng trong khi vẫn có thể tương tác.

Bài viết được đề xuất
Tạo trò chơi nhiều người chơi trong Unity bằng PUN 2
Tạo trò chơi ô tô nhiều người chơi với PUN 2
Xây dựng các trò chơi nối mạng nhiều người chơi trong Unity
Bù độ trễ PUN 2
Hướng dẫn cho người mới bắt đầu về Mạng Photon (Cổ điển)
Nén dữ liệu nhiều người chơi và thao tác bit
Hướng dẫn về bảng xếp hạng trực tuyến Unity