Synkroniser rigidbodies over nettverk ved hjelp av PUN 2
Synkronisering av objekter i PUN 2 er enkelt, men hva med å synkronisere Rigidbodies?
I motsetning til vanlige GameObjects, er Rigidbody også påvirket av Gravity (hvis ikke kinematisk) og andre objekter også. Så i stedet for å synkronisere bare objektets Transform, må vi også synkronisere et par ekstra parametere, for eksempel velocity og angularVelocity.
I dette innlegget vil jeg vise hvordan du lager interaktive Rigidbodies som kan påvirkes av hver spiller i rommet og synkroniseres over nettverket.
Unity versjon brukt i denne opplæringen: Unity 2018.3.0f2 (64-bit)
Del 1: Sette opp PUN 2 og flerspillereksempel
Vi har allerede en veiledning for hvordan du setter opp et flerspillereksempel ved å bruke PUN 2, sjekk lenken nedenfor:
Lag et flerspillerspill i Unity 3D med PUN 2
Kom tilbake når du er ferdig med å sette opp et flerspillerprosjekt, slik at vi kan fortsette.
Alternativt kan du spare tid ved å hente kildeprosjektet fra her.
Del 2: Legge til interaktive rigidbodies
Hvis du fulgte opplæringen ovenfor, ville du nå ha 2 scener "GameLobby" og "GameLevel"
- Åpne "GameLevel"-scenen og lag et par kuber (GameObject -> 3D Object -> Cube)
- Legg til en Rigidbody-komponent til hver kube
- Legg til en PhotonView-komponent til hver kube
Nå må vi lage et nytt skript som vil synkronisere Rigidbodies over nettverket.
- Lag et nytt skript og kall 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);
}
}
}
}
- Fest PUN2_RigidbodySync til begge kuber og tilordne det også til Photon View "Observed Components":
Vi må også gjøre noen endringer i PUN2_PlayerSync-skriptet fra flerspilleropplæringen:
- Åpne PUN2_PlayerSync.cs
- In void Start(), inni if(photonView.IsMine) legg til denne koden:
//Player is local
gameObject.tag = "Player";
//Add Rigidbody to make the player interact with rigidbody
Rigidbody r = gameObject.AddComponent<Rigidbody>();
r.isKinematic = true;
Så nå skal void Start() se slik ut:
// 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 å legge til en Rigidbody-komponent sørger vi for at spillerforekomsten kan samhandle med andre Rigidbodies og ved å endre taggen til "Player" kan vi oppdage om det var en lokal forekomst som kolliderte med en Rigidbody.
- Lagre GameLevel-scenen etter at alt er gjort.
La oss nå lage et bygg og teste det!
Alt fungerer som forventet, nå kan Rigidbodies synkroniseres over nettverket mens de fortsatt kan kommuniseres.