PUN 2'yi Kullanarak Sert Cisimleri Ağ Üzerinden Senkronize Etme
PUN 2'te Nesneleri senkronize etmek basittir, peki ya Sert Cisimleri senkronize etmeye ne dersiniz?
Normal GameObject'lerin aksine, Rigidbody aynı zamanda Yerçekiminden (Kinematik değilse) ve diğer nesnelerden de etkilenir. Dolayısıyla, yalnızca nesnenin Dönüşümünü senkronize etmek yerine, velocity ve angularVelocity gibi birkaç ek parametreyi de senkronize etmemiz gerekir.
Bu yazıda, Odadaki her Oyuncu tarafından etkilenebilen ve Ağ üzerinden senkronize edilebilen etkileşimli Sert Cisimlerin nasıl yapılacağını göstereceğim.
Unity Bu eğitimde kullanılan sürüm: Unity 2018.3.0f2 (64-bit)
Bölüm 1: PUN 2'yi ve Çok Oyunculu Örneği Kurma
PUN 2'yi kullanarak çok oyunculu bir örneğin nasıl kurulacağına dair zaten bir eğitimimiz var, aşağıdaki bağlantıyı kontrol edin:
Unity 3D'te PUN 2'yi kullanarak çok oyunculu bir oyun yapın
Çok oyunculu bir proje oluşturmayı bitirdiğinizde devam edebilmemiz için tekrar gelin.
Alternatif olarak, kaynak projeyi buradan adresinden alarak zamandan tasarruf edebilirsiniz.
Bölüm 2: Etkileşimli Sert Cisimler Ekleme
Yukarıdaki eğitimi izlediyseniz artık 2 Sahneye sahip olursunuz "GameLobby" ve "GameLevel"
- "GameLevel" Sahnesini açın ve birkaç Küp oluşturun (GameObject -> 3D Object -> Cube)
- Her Küp'e bir Sert Cisim bileşeni ekleyin
- Her Küp'e bir PhotonView bileşeni ekleyin
Şimdi Rigidbody'leri ağ üzerinden senkronize edecek yeni bir Script oluşturmamız gerekiyor.
- Yeni bir Komut Dosyası oluşturun ve onu PUN2_RigidbodySync olarak adlandırın
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'i her iki Küp'e ekleyin ve ayrıca Photon View "Observed Components":'e atayın.
Ayrıca Multiplayer eğitimindeki PUN2_PlayerSync betiğinde de bazı değişiklikler yapmamız gerekiyor:
- PUN2_PlayerSync.cs'yi açın
- void Start()'ta, if(photonView.IsMine) içine şu kodu ekleyin:
//Player is local
gameObject.tag = "Player";
//Add Rigidbody to make the player interact with rigidbody
Rigidbody r = gameObject.AddComponent<Rigidbody>();
r.isKinematic = true;
Şimdi void Start() şöyle görünmeli:
// 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);
}
}
}
Bir Rigidbody bileşeni ekleyerek oynatıcı örneğinin diğer Rigidbody'lerle etkileşime girebilmesini sağlıyoruz ve etiketi "Player" olarak değiştirerek bunun bir Rigidbody ile çarpışan yerel bir örnek olup olmadığını tespit edebiliyoruz.
- Her şey tamamlandıktan sonra GameLevel Sahnesini kaydedin.
Şimdi bir yapı oluşturalım ve test edelim!
Her şey beklendiği gibi çalışıyor, artık Rigidbody'ler hâlâ etkileşimliyken Ağ üzerinden senkronize edilebiliyor.