Synkronisera stela kroppar över nätverk med PUN 2
Att synkronisera objekt i PUN 2 är enkelt, men hur är det med att synkronisera Rigidbodies?
Till skillnad från vanliga GameObjects, påverkas Rigidbody också av Gravity (om inte Kinematic) och andra objekt också. Så istället för att bara synkronisera objektets Transform, måste vi också synkronisera ett par ytterligare parametrar, såsom hastighet och vinkelhastighet.
I det här inlägget kommer jag att visa hur man gör interaktiva Rigidbodies som kan påverkas av varje spelare i rummet och synkroniseras över nätverket.
Unity version som används i denna handledning: Unity 2018.3.0f2 (64-bitars)
Del 1: Ställa in PUN 2 och Multiplayer Exempel
Vi har redan en handledning om hur man ställer in ett multiplayer-exempel med PUN 2, kolla länken nedan:
Gör ett spel för flera spelare i Unity 3D med PUN 2
Kom tillbaka när du är klar med att skapa ett flerspelarprojekt så att vi kan fortsätta.
Alternativt kan du spara tid genom att hämta källprojektet här.
Del 2: Lägga till interaktiva stela kroppar
Om du följde handledningen ovan skulle du nu ha 2 scener "GameLobby" och "GameLevel"
- Öppna "GameLevel"-scenen och skapa ett par kuber (GameObject -> 3D Object -> Cube)
- Lägg till en Rigidbody-komponent till varje kub
- Lägg till en PhotonView-komponent till varje kub
Nu måste vi skapa ett nytt skript som kommer att synkronisera Rigidbodies över nätverket.
- Skapa ett nytt skript och kalla 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);
}
}
}
}
- Fäst PUN2_RigidbodySync till båda kuberna och tilldela den även till Photon View "Observed Components":
Vi måste också göra några ändringar i PUN2_PlayerSync-skriptet från Multiplayer-handledningen:
- Öppna PUN2_PlayerSync.cs
- In void Start(), inuti if(photonView.IsMine) lägg till denna kod:
//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 ska void Start() se ut så här:
// 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);
}
}
}
Genom att lägga till en Rigidbody-komponent ser vi till att spelarinstansen kan interagera med andra Rigidbodies och genom att ändra taggen till "Player" kan vi upptäcka om det var en lokal instans som kolliderade med en Rigidbody.
- Spara GameLevel-scenen när allt är klart.
Låt oss nu bygga och testa den!
Allt fungerar som förväntat, nu kan Rigidbodies synkroniseras över nätverk samtidigt som de är interagerbara.