OnPhotonSerializeView not Updating Correctly

Options
Hello,

I am attempting to synchronize the health system in my game using Photon. The problem is that every player always has full health, so a player only loses health momentarily and then it goes back to full health. The player fires a bullet and then bullet.cs uses a raycast to see if the bullet hits someone. Bullet then changes the health variable and OnPhoton Serialize View should then synchronize the health. Does anyone know why health changes momentarily, but then returns to full health?

Always.cs contains the OnPhotonSerializeView
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Always : Photon.MonoBehaviour, IPunObservable {
	public float health = 2f; 
	public float oldHealth = 2f; 
	public GameObject game;

	void Update (){
		game = transform.GetChild (0).gameObject; 
		if (transform.GetChild (0).gameObject.transform.localScale.x == 0f || transform.GetChild (0).gameObject.transform.localScale.x < 0f) {
			PhotonNetwork.Destroy (this.gameObject); 
		}
		if (photonView.isMine) {
		} else {
			game.transform.localScale = new Vector3 (health, 2f, 1f); 
		}

	}

	#region IPunObservable implementation
	void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
	{
		if (stream.isWriting && photonView.isMine) {
				//We own this player: send the others our data
				stream.SendNext (health);
				Debug.Log ("health");
			} 
		else if(stream.isReading) {
			
				float scale = (float)stream.ReceiveNext (); 
				Debug.Log (scale);
				health = scale;  
				oldHealth = scale; 
			}

	}
	#endregion
}
Bullet.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;



public class Bullet : MonoBehaviour {

	private IEnumerator coroutine; 
	private IEnumerator death; 

	// Use this for initialization
	void Start () {
		coroutine = die (1.5f);
		//StartCoroutine (coroutine);
		 
	}
	
	// Update is called once per frame
	void Update () {

		RaycastHit2D[] hits;

		//Debug.DrawRay(this.gameObject.transform.position, (transform.GetComponent<Rigidbody2D> ().velocity) / 60, Color.green, 20, false);
		hits = Physics2D.RaycastAll(this.gameObject.transform.position, (transform.GetComponent<Rigidbody2D> ().velocity) / 60);
	//	RaycastHit2D myHit = Physics2D.Raycast (transform.position, (transform.GetComponent<Rigidbody2D> ().velocity) / 60);
		for(int x = 0; x<hits.Length; x++)
		{
		if (hits[x]) {
			GameObject myObject = hits[x].collider.gameObject;  
			if (myObject.tag != "mine" && myObject.tag != "bullet") {
				if (myObject != null && myObject.tag == "spinners") {
					Debug.Log ("hit");
					GameObject health = myObject.transform.GetChild (0).gameObject; 
					if (health.transform.localScale.x == 0f || health.transform.localScale.x < 0f) {
							//myObject.GetPhotonView().RPC ("die", PhotonTargets.All);
						death = (kill (.5f));
							break; 

					} else {
						
							//myObject.GetPhotonView().RPC ("health", PhotonTargets.All); 

							myObject.GetComponent<Always>().health -= .1f; 
							health.transform.localScale = new Vector3 (myObject.GetComponent<Always>().health, 2f, 1f);
						death = (kill (.5f));
							break;

					}
				}
			}
		}
	  }
	}

			
		
	
	/*public void setCreator(GameObject myObject)
	{
		creator = myObject;
	}*/

	private IEnumerator die(float time){
		yield return new WaitForSeconds (time);
		Destroy (transform.gameObject);
	}

	private IEnumerator kill(float time)
	{
		yield return new WaitForSeconds (time);
		Destroy (transform.gameObject);
	}

	[PunRPC]
	void die()
	{
		GameObject health = transform.GetChild (0).gameObject; 
		if (health.transform.localScale.x == 0f || health.transform.localScale.x < 0f) {
			PhotonNetwork.Destroy (this.gameObject);
		}
	}

	/*[PunRPC]
	void health()
	{
		GameObject health = transform.GetChild (0).gameObject; 
		health.transform.localScale += new Vector3 (-.1f, 0, 0); 
	}*/

}

Comments

  • Hi @coderGuy123,

    as far as I can see you are only lowering the health value on the local client. It gets automatically 'reset' when OnPhotonSerializeView is called because the owner of the object doesn't know about the modification and send his original value. So whenever the local client fires a bullet and you check for any hits, you must notify the owner of the hit object and tell him, that he actually was hit. You can do this for example by calling a RPC on the player's game object. This maybe looks like the following, to give you an idea: hit.gameObject.GetComponent<PhotonView>().RPC("DoSomething", PhotonTargets.All);.

    When using this approach and synchronizing health values by using RPCs you can also remove the OnPhotonSerializeView function.