סנכרן גופים קשיחים ברשת באמצעות PUN 2

סנכרון אובייקטים ב-PUN 2 הוא פשוט, אבל מה לגבי סנכרון Rigidbodies?

בניגוד ל-GameObjects רגילים, Rigidbody מושפע גם מ-Gravitation (אם לא Kinematic) ומאובייקטים אחרים. אז במקום לסנכרן רק את ה-Transform של האובייקט, אנחנו צריכים גם לסנכרן כמה פרמטרים נוספים, כגון velocity ו-angularVelocity.

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

Unity גרסה בשימוש במדריך זה: Unity 2018.3.0f2 (64 סיביות)

חלק 1: הגדרת PUN 2 ודוגמה מרובה משתתפים

כבר יש לנו מדריך כיצד להגדיר דוגמה מרובה משתתפים באמצעות PUN 2, בדוק את הקישור למטה:

צור משחק מרובה משתתפים ב-Unity 3D באמצעות PUN 2

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

לחלופין, אתה יכול לחסוך זמן על ידי קבלת פרויקט המקור מ-כאן.

חלק 2: הוספת קשיחים אינטראקטיביים

אם הייתם עוקבים אחר המדריך שלמעלה היו לכם כעת 2 סצנות "GameLobby" ו "GameLevel"

  • פתח את הסצנה "GameLevel" וצור כמה קוביות (GameObject -> 3D Object -> Cube)

  • הוסף רכיב Rigidbody לכל קובייה
  • הוסף רכיב PhotonView לכל קובייה

כעת עלינו ליצור סקריפט חדש שיסנכרן את Rigidbodies ברשת.

  • צור סקריפט חדש וקרא לו 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);
            }
        }
    }
}
  • חבר את PUN2_RigidbodySync לשתי הקוביות וגם הקצה אותו ל-Photon View "Observed Components":

אנחנו גם צריכים לבצע כמה שינויים בסקריפט PUN2_PlayerSync מתוך המדריך מרובי משתתפים:

  • פתח את PUN2_PlayerSync.cs
  • ב-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;

אז עכשיו void Start() אמור להיראות כך:

    // 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);
            }
        }
    }

על ידי הוספת רכיב Rigidbody אנו מוודאים שהמופע של השחקן יכול לקיים אינטראקציה עם Rigidbodies אחרים ועל ידי שינוי התג ל-"Player" נוכל לזהות אם זה היה מופע מקומי שהתנגש עם Rigidbody.

  • שמור את סצנת GameLevel לאחר שהכל נעשה.

עכשיו בואו נעשה בנייה ונבדוק אותה!

Sharp Coder נגן וידאו

הכל עובד כצפוי, כעת ניתן לסנכרן את Rigidbodies דרך הרשת תוך יצירת אינטראקציה.