Synkroniser rigidbodies over netværk ved hjælp af PUN 2
Synkronisering af objekter i PUN 2 er enkelt, men hvad med at synkronisere Rigidbodies?
I modsætning til almindelige GameObjects, påvirkes Rigidbody også af Gravity (hvis ikke kinematisk) og andre objekter. Så i stedet for kun at synkronisere objektets Transform, skal vi også synkronisere et par ekstra parametre, såsom velocity og angularVelocity.
I dette indlæg vil jeg vise, hvordan man laver interaktive Rigidbodies, der kan påvirkes af hver spiller i rummet og synkroniseres over netværket.
Unity version brugt i denne øvelse: Unity 2018.3.0f2 (64-bit)
Del 1: Opsætning af PUN 2 og multiplayer eksempel
Vi har allerede en tutorial om, hvordan man opsætter et multiplayer-eksempel ved hjælp af PUN 2, tjek linket nedenfor:
Lav et multiplayer-spil i Unity 3D ved hjælp af PUN 2
Vend tilbage, når du er færdig med at oprette et multiplayer-projekt, så vi kan fortsætte.
Alternativt kan du spare tid ved at hente kildeprojektet fra her.
Del 2: Tilføjelse af interaktive rigidbodies
Hvis du fulgte vejledningen ovenfor, ville du nu have 2 scener "GameLobby" og "GameLevel"
- Åbn "GameLevel"-scenen, og lav et par kuber (GameObject -> 3D-objekt -> Cube)
- Tilføj en Rigidbody-komponent til hver terning
- Tilføj en PhotonView-komponent til hver terning
Nu skal vi oprette et nyt script, der vil synkronisere Rigidbodies over netværket.
- Opret et nyt script og kald det 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);
}
}
}
}
- Vedhæft PUN2_RigidbodySync til begge terninger, og tildel den også til Photon View "Observed Components":
Vi skal også lave nogle ændringer til PUN2_PlayerSync-scriptet fra Multiplayer-vejledningen:
- Åbn PUN2_PlayerSync.cs
- In void Start(), inde i if(photonView.IsMine) tilføj denne kode:
//Player is local
gameObject.tag = "Player";
//Add Rigidbody to make the player interact with rigidbody
Rigidbody r = gameObject.AddComponent<Rigidbody>();
r.isKinematic = true;
Så nu skulle void Start() se sådan ud:
// 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);
}
}
}
Ved at tilføje en Rigidbody-komponent sikrer vi, at spillerinstansen kan interagere med andre Rigidbodies, og ved at ændre tagget til "Player" kan vi opdage, om det var en lokal instans, der kolliderede med en Rigidbody.
- Gem GameLevel-scenen, når alt er færdigt.
Lad os nu lave en build og teste den!
Alt fungerer som forventet, nu kan Rigidbodies synkroniseres over netværket, mens de stadig kan interageres.