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!

Sharp Coder Videospiller

Alt fungerer som forventet, nå kan Rigidbodies synkroniseres over nettverket mens de fortsatt kan kommuniseres.

Foreslåtte artikler
Lag et flerspillerspill i Unity med PUN 2
Lag et bilspill med flere spillere med PUN 2
Multiplayer datakomprimering og bitmanipulering
PUN 2 Lagkompensasjon
Unity legger til flerspillerchat til PUN 2-rommene
Unity Login System med PHP og MySQL
Photon Network (klassisk) nybegynnerveiledning