סנכרן גופים קשיחים ברשת באמצעות 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 לאחר שהכל נעשה.
עכשיו בואו נעשה בנייה ונבדוק אותה!
הכל עובד כצפוי, כעת ניתן לסנכרן את Rigidbodies דרך הרשת תוך יצירת אינטראקציה.