Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Third Party null references error when the player dies(Photon)

Discussion in 'Multiplayer' started by unity_A4E6F287CE1664E193BF, Aug 2, 2022.

  1. unity_A4E6F287CE1664E193BF

    unity_A4E6F287CE1664E193BF

    Joined:
    Jun 9, 2022
    Posts:
    18
    null references error when the player dies, does anyone know how to fix it? I'm new to multiplayer development.
    Code (CSharp):
    1. using Photon.Pun;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6. using Photon.Realtime;
    7.  
    8. public class HealthOnline : MonoBehaviour,IPunObservable
    9. {
    10.     [SerializeField] float maxHealth = 100;
    11.     [SerializeField]Image healthFillImg;
    12.     public float MaxHealth { get { return maxHealth; } }
    13.     public float CurrentHealth { get; private set; }
    14.     public bool IsAlive { get { return CurrentHealth > 0; } }
    15.     public bool IsPlayer;
    16.     bool active;
    17.     PhotonView photonView;
    18.  
    19.     void UpdateHealth()
    20.     {
    21.         healthFillImg.fillAmount = CurrentHealth/maxHealth;
    22.     }
    23.  
    24.     void Start()
    25.     {
    26.         photonView = GetComponent<PhotonView>();
    27.         CurrentHealth = maxHealth;
    28.         UpdateHealth();
    29.     }
    30.  
    31.  
    32.     void OnEnable()
    33.     {
    34.     }
    35.  
    36.     [PunRPC]
    37.     public void RPC_TakeDamage(float damage, Player attacker=null, int weapon = 0)
    38.     {
    39.         if(!photonView.IsMine)return;
    40.         if (!IsAlive) return;
    41.  
    42.         float previousHealth = CurrentHealth;
    43.         CurrentHealth -= damage;
    44.         CurrentHealth = Mathf.Clamp(CurrentHealth, 0, maxHealth);
    45.         UpdateHealth();
    46.  
    47.         if(IsPlayer)
    48.         {
    49.               RaiseEventOptions options = new RaiseEventOptions()
    50.             {
    51.                 CachingOption = EventCaching.DoNotCache,
    52.                 Receivers = ReceiverGroup.All,
    53.  
    54.             };
    55.             object[] eventData = new object[]{photonView.Owner,previousHealth,CurrentHealth,attacker};
    56.             PhotonNetwork.RaiseEvent((byte)GameEvents.OnPlayerHealthChance,eventData,options,ExitGames.Client.Photon.SendOptions.SendReliable);
    57.         }
    58.         else if(!IsPlayer)
    59.         {
    60.            
    61.               RaiseEventOptions options = new RaiseEventOptions()
    62.             {
    63.                 CachingOption = EventCaching.DoNotCache,
    64.                 Receivers = ReceiverGroup.All,
    65.  
    66.             };
    67.             object[] eventData = new object[]{photonView.ViewID,previousHealth,CurrentHealth};
    68.             PhotonNetwork.RaiseEvent((byte)GameEvents.OnElementHealthChange,eventData,options,ExitGames.Client.Photon.SendOptions.SendReliable);
    69.         }
    70.  
    71.         if (IsAlive)
    72.         {
    73.  
    74.         }
    75.         else
    76.         {
    77.              RaiseEventOptions options = new RaiseEventOptions()
    78.             {
    79.                 CachingOption = EventCaching.DoNotCache,
    80.                 Receivers = ReceiverGroup.All,
    81.  
    82.             };
    83.  
    84.             if(!IsPlayer)
    85.                 PhotonNetwork.Destroy(gameObject);
    86.             else
    87.                 PhotonNetwork.Destroy(gameObject);
    88.                 //gameObject.SetActive(false);
    89.  
    90.         }
    91.     }
    92.  
    93.     public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    94.     {
    95.         if (stream.IsWriting)
    96.         {
    97.             stream.SendNext(CurrentHealth);
    98.             if (IsPlayer)
    99.                 stream.SendNext(gameObject.activeInHierarchy);
    100.         }
    101.         else if(stream.IsReading)
    102.         {
    103.             CurrentHealth = (float)stream.ReceiveNext();
    104.             UpdateHealth();
    105.             if (IsPlayer)
    106.             {
    107.                 active = (bool)stream.ReceiveNext();
    108.                 //gameObject.SetActive(active);
    109.             }
    110.         }
    111.     }
    112.  
    113. [PunRPC]
    114.     public void RPC_RestoreHealth(float ammount)
    115.     {
    116.         if(!photonView.IsMine)return;
    117.         if (!IsAlive) return;
    118.         CurrentHealth += ammount;
    119.         CurrentHealth = Mathf.Clamp(CurrentHealth, 0, maxHealth);
    120.         UpdateHealth();
    121.     }
    122. }
    123.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5. using Photon.Realtime;
    6. using UnityEngine.UI;
    7. using UnityEngine.SceneManagement;
    8. using Photon.Pun.UtilityScripts;
    9. using System.Linq;
    10.  
    11. public class MultiplayerGamePlayController : MonoBehaviourPunCallbacks,IPunObservable
    12. {
    13.     [SerializeField]Transform[] playersSpawnPoint;
    14.     [SerializeField]string playerUSAPrefabName = "player";
    15.     [SerializeField]string playerGERPrefabName = "player";
    16.     CameraFollowPosition cameraFollowPosition;
    17.     [SerializeField]int ROUND_TIME_SECONDS = 5*1;
    18.     [SerializeField]Text timeText;
    19.     [SerializeField]GameObject gameEndPanel;
    20.     bool timeFinish;
    21.     int playerSpawnTime = 0;
    22.     bool isGameOver;
    23.     KillMessageBehaviour killMessageBehaviour;
    24.  
    25.  
    26.     void Awake()
    27.     {
    28.         cameraFollowPosition = FindObjectOfType<CameraFollowPosition>();
    29.         killMessageBehaviour = FindObjectOfType<KillMessageBehaviour>();
    30.  
    31.  
    32.         if(PhotonNetwork.IsMasterClient)
    33.         {
    34.             var props = PhotonNetwork.CurrentRoom.CustomProperties;
    35.             props.Add("endTime",PhotonNetwork.Time + (double)ROUND_TIME_SECONDS);
    36.             PhotonNetwork.CurrentRoom.SetCustomProperties(props);
    37.         }
    38.         PhotonNetwork.NetworkingClient.EventReceived += OnEventReceive;
    39.         StartCoroutine(TimeTickCoroutine());
    40.         SpawnPlayer();
    41.     }
    42.  
    43.     public override void OnDisable()
    44.     {
    45.        PhotonNetwork.NetworkingClient.EventReceived -= OnEventReceive;
    46.     }
    47.  
    48.  
    49.      void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    50.         {
    51.             if (stream.IsWriting)
    52.             {
    53.                 stream.SendNext(isGameOver);
    54.             }
    55.             else
    56.             {
    57.                isGameOver = (bool)stream.ReceiveNext();
    58.             }
    59.         }
    60.  
    61.     void OnEventReceive(ExitGames.Client.Photon.EventData data)
    62.     {
    63.         if(data.Code == (byte)GameEvents.OnTimeOver)
    64.         {
    65.            
    66.         }
    67.         else if(data.Code == (byte)GameEvents.OnPlayerHealthChance)
    68.         {
    69.             object[] datas = (object[])data.CustomData;
    70.             Player sourcePlayer = (Player)data[0];
    71.             float previousHealth = (float)datas[1];
    72.             float currentHealth = (float)datas[2];
    73.             Player attackPlayer = (Player)datas[3];
    74.  
    75.             if(sourcePlayer!=null)
    76.             {
    77.                 Debug.Log("sourcePlayer = "+sourcePlayer.NickName);
    78.             }
    79.             if(previousHealth != -1)
    80.             {
    81.                 Debug.Log("previousHealth = "+previousHealth);
    82.             }
    83.             if(currentHealth != -1)
    84.             {
    85.                 Debug.Log("currentHealth = "+currentHealth);
    86.             }
    87.              if(attackPlayer!=null)
    88.             {
    89.                 Debug.Log("attackPlayer = "+attackPlayer.NickName);
    90.             }
    91.  
    92.             if(currentHealth > previousHealth)
    93.             {
    94.                 // recover
    95.             }
    96.             else
    97.             {
    98.                 // damage
    99.                 if(currentHealth == 0) // dead
    100.                 {
    101.                     Debug.Log("OnPlayerWasted victimPlayer: "+sourcePlayer.NickName);
    102.                     Debug.Log("OnPlayerWasted killer = "+attackPlayer.NickName);
    103.                     if(GetPlayersAliveInTeam(sourcePlayer.GetPhotonTeam().Name).Count == 0)
    104.                     {
    105.                         // game over
    106.                         string winnerTeam = attackPlayer.GetPhotonTeam().Name;
    107.                         string player1Name = attackPlayer.NickName;
    108.                         string player2Name = "";
    109.                         Player[] winnerPlayers;
    110.                         PhotonTeamsManager.Instance.TryGetTeamMembers(attackPlayer.GetPhotonTeam().Code,out winnerPlayers);
    111.                         if(winnerPlayers != null)
    112.                         {
    113.                             for(int i=0; i<winnerPlayers.Length; i++)
    114.                             {
    115.                                 if(winnerPlayers[i].NickName!=player1Name)
    116.                                     player2Name = winnerPlayers[i].NickName;
    117.                             }
    118.                         }
    119.                         StartCoroutine(ShowGameEndPanel(winnerTeam,player1Name,player2Name));
    120.  
    121.                        
    122.                     }
    123.                 }
    124.                 else // alive
    125.                 {
    126.  
    127.                 }
    128.             }
    129.         }
    130.         else if(data.Code == (byte)GameEvents.OnPlayerWasted)
    131.         {
    132.            object[] datas = (object[])data.CustomData;
    133.            Player victimPlayer = UtilsNetwork.GetPlayerByID((int)datas[0]);
    134.            Player killerPlayer = UtilsNetwork.GetPlayerByID((int)datas[1]);
    135.            Debug.Log("OnPlayerWasted victimPlayer = "+victimPlayer.NickName+" killer = "+killerPlayer.NickName);
    136.         }
    137.         else if(data.Code == (byte)GameEvents.OnElementHealthChange)
    138.         {
    139.  
    140.         }
    141.     }
    142.  
    143.     IEnumerator ShowGameEndPanel(string winnerTeam, string player1Name, string player2Name)
    144.     {
    145.         gameEndPanel.SetActive(true);
    146.         gameEndPanel.transform.Find("player1NameText").GetComponent<Text>().text = string.Format("{0}",player1Name);
    147.         gameEndPanel.transform.Find("player2NameText").GetComponent<Text>().text = string.Format("{0}",player2Name);
    148.         if(winnerTeam == "USA")
    149.         {
    150.             gameEndPanel.transform.Find("usaFlagImg").gameObject.SetActive(true);
    151.             gameEndPanel.transform.Find("gerFlagImg").gameObject.SetActive(false);
    152.         }
    153.         else
    154.         {
    155.             gameEndPanel.transform.Find("usaFlagImg").gameObject.SetActive(false);
    156.             gameEndPanel.transform.Find("gerFlagImg").gameObject.SetActive(true);
    157.         }
    158.         yield return new WaitForSeconds(3.2f);
    159.         // TODO: to single player
    160.     }
    161.  
    162.  
    163.     public List<PlayerControllerMultiplayer> GetPlayersAlive()
    164.     {
    165.         List<PlayerControllerMultiplayer> players = new List<PlayerControllerMultiplayer>();
    166.         var allPlayer = GameObject.FindObjectsOfType<PlayerControllerMultiplayer>();
    167.         for(int i=0; i<allPlayer.Length; i++)
    168.         {
    169.             if(allPlayer[i].GetComponent<HealthOnline>().IsAlive)
    170.                 players.Add(allPlayer[i]);
    171.         }
    172.  
    173.         return players;
    174.     }
    175.  
    176.     public List<PlayerControllerMultiplayer> GetPlayersAliveInTeam(string team)
    177.     {
    178.         List<PlayerControllerMultiplayer> players = new List<PlayerControllerMultiplayer>();
    179.         var alives = GetPlayersAlive();
    180.         for(int i=0; i<alives.Count; i++)
    181.         {
    182.             if(alives[i].photonView.Owner.GetPhotonTeam().Name == team)
    183.                 players.Add(alives[i]);
    184.         }
    185.         return players;
    186.     }
    187.  
    188.     void SpawnPlayer()
    189.     {
    190.         int spawn = 0;
    191.         var props = PhotonNetwork.LocalPlayer.CustomProperties;
    192.         int id = (int)props["id"];
    193.         spawn = id;
    194.         string playerPrefabName = id < 2 ? playerUSAPrefabName : playerGERPrefabName;
    195.         GameObject playerPrefab = PhotonNetwork.Instantiate(playerPrefabName,playersSpawnPoint[spawn].position,playersSpawnPoint[spawn].rotation);
    196.    
    197.     }
    198.  
    199.     IEnumerator TimeTickCoroutine()
    200.     {
    201.         yield return new WaitForSeconds(1);
    202.         var props = PhotonNetwork.CurrentRoom.CustomProperties;
    203.         var future = (double)props["endTime"];
    204.         var elapsed = (int)(future - PhotonNetwork.Time);
    205.         if(elapsed <= 0)
    206.         {
    207.             elapsed = 0;
    208.             timeFinish = true;
    209.             RaiseEventOptions options = new RaiseEventOptions()
    210.             {
    211.                 CachingOption = EventCaching.DoNotCache,
    212.                 Receivers = ReceiverGroup.All,
    213.  
    214.             };
    215.          
    216.             PhotonNetwork.RaiseEvent((byte)GameEvents.OnTimeOver,null,options,ExitGames.Client.Photon.SendOptions.SendReliable);
    217.         }
    218.         else
    219.         {
    220.             if(!isGameOver)
    221.                 StartCoroutine(TimeTickCoroutine());
    222.         }
    223.         timeText.text = elapsed.ToString();
    224.  
    225.     }
    226.  
    227.     public void SetGameOver(string reason)
    228.     {
    229.         if(isGameOver)return;
    230.         isGameOver = true;
    231.         PhotonNetwork.NetworkingClient.EventReceived -= OnEventReceive;
    232.         StopCoroutine(TimeTickCoroutine());
    233.         StartCoroutine(RemovePlayerFromRoom());
    234.     }
    235.  
    236.     IEnumerator RemovePlayerFromRoom()
    237.     {
    238.         PhotonNetwork.AutomaticallySyncScene = false;
    239.         if(photonView.IsMine)
    240.         {
    241.             SceneManager.LoadScene("minigameSelect");
    242.             PhotonNetwork.Disconnect();
    243.             yield return new WaitForSeconds(0.1f);
    244.         }
    245.         /*if(PhotonNetwork.IsMasterClient)
    246.         {
    247.             PhotonNetwork.DestroyAll();
    248.             PhotonNetwork.Disconnect();
    249.             SceneManager.LoadScene("minigameSelect");
    250.  
    251.         }
    252.  
    253.         */
    254.        
    255.     }
    256. }
    257.  
    258. public enum GameEvents
    259. {
    260.     OnPlayerHealthChance = 0,
    261.     OnPlayerWasted = 1,
    262.     OnTimeOver = 2,
    263.     OnElementHealthChange = 3
    264. }
    265.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5. using Photon.Realtime;
    6.  
    7. public class ProjectilOnline : MonoBehaviour
    8. {
    9.     [SerializeField]float movementSpeed = 10f;
    10.     [SerializeField]float damage = 10f;
    11.     [SerializeField]float damageArea = 0;
    12.     [SerializeField]float destroyTime = 3;
    13.     [SerializeField]DamageType damageType;
    14.     [SerializeField]string explosionSound = string.Empty;
    15.     [SerializeField]GameObject explosionPrefab;
    16.     Rigidbody2D rb;
    17.     PhotonView photonView;
    18.     [SerializeField]int KillerWeaponIcon = 0;
    19.     [SerializeField]float activationTime = 0;
    20.     [SerializeField]string activationSound = string.Empty;
    21.  
    22.     bool isActive;
    23.  
    24.     void Start() // enable
    25.     {
    26.         photonView = GetComponent<PhotonView>();
    27.         rb = GetComponent<Rigidbody2D> ();
    28.         rb.velocity = Vector2.zero;
    29.         rb.AddRelativeForce (Vector2.up * movementSpeed,ForceMode2D.Impulse);
    30.         if(photonView.IsMine)
    31.             StartCoroutine(ActiveCoroutine());
    32.     }
    33.  
    34.     IEnumerator DestroyCoroutine()
    35.     {
    36.         yield return new WaitForSeconds(destroyTime);
    37.         Explode();
    38.     }
    39.  
    40.     IEnumerator ActiveCoroutine()
    41.     {
    42.         isActive = false;
    43.         yield return new WaitForSeconds(activationTime);
    44.         isActive = true;
    45.         if(activationSound!=string.Empty)
    46.             AudioManagerOnline.Singleton.PlaySfx (activationSound, volume: 1f);
    47.         StartCoroutine(DestroyCoroutine());
    48.     }
    49.  
    50.     void Explode()
    51.     {
    52.         if(explosionSound!=string.Empty)
    53.             AudioManagerOnline.Singleton.PlaySfx (explosionSound, volume: 0.7f);
    54.         if(explosionPrefab != null)
    55.             PhotonNetwork.Instantiate(explosionPrefab.name,transform.position,transform.rotation);
    56.         DamageRadial();
    57.     }
    58.  
    59.     void DamageRadial()
    60.     {
    61.         var cols = Physics2D.OverlapCircleAll(transform.position,damageArea);
    62.         for(int i=0; i<cols.Length; i++)
    63.         {
    64.             var hb = cols[i].GetComponent<HealthOnline>();
    65.  
    66.             if(hb!=null)
    67.             {
    68.                 float distance = Vector2.Distance(transform.position,cols[i].transform.position);
    69.  
    70.                 if(distance<damageArea)
    71.                 {
    72.  
    73.                     float calculadDamage =(1f - (distance/damageArea)) * damage;
    74.                     calculadDamage = Mathf.Clamp(calculadDamage,0,damage);
    75.                     PhotonView pv = cols[i].GetComponent<PhotonView>(); // victim
    76.                     pv.RPC("RPC_TakeDamage", RpcTarget.All, calculadDamage,photonView.Owner,KillerWeaponIcon);
    77.                 }
    78.             }
    79.         }
    80.        
    81.          if(photonView.IsMine)
    82.             PhotonNetwork.Destroy(gameObject);
    83.     }
    84.  
    85.  
    86.  
    87.     void OnTriggerEnter2D(Collider2D col)
    88.     {
    89.         if (photonView.IsMine)
    90.         {
    91.             if(!isActive)return;
    92.             if(damageType == DamageType.COLLISION)
    93.             {
    94.                 HealthOnline health = col.GetComponent<HealthOnline>();
    95.                 if (health!= null)
    96.                 {
    97.                     PhotonView pv = col.GetComponent<PhotonView>();
    98.                     pv.RPC("RPC_TakeDamage", RpcTarget.All, damage, photonView.Owner,KillerWeaponIcon);
    99.                  
    100.                 }
    101.                  PhotonNetwork.Destroy(gameObject);
    102.             }
    103.             else
    104.             {
    105.                 Explode();
    106.             }
    107.          
    108.         }
    109.         else
    110.         {
    111.         }
    112.        
    113.     }
    114.  
    115.  
    116.     void OnCollisionEnter2D(Collision2D col)
    117.     {
    118.          if (photonView.IsMine)
    119.         {
    120.             if(!isActive)return;
    121.             if(damageType == DamageType.COLLISION)
    122.             {
    123.                 HealthOnline health = col.gameObject.GetComponent<HealthOnline>();
    124.                 if (health!= null)
    125.                 {
    126.                     PhotonView pv = col.gameObject.GetComponent<PhotonView>();
    127.                     pv.RPC("RPC_TakeDamage", RpcTarget.All, damage, photonView.Owner,KillerWeaponIcon);
    128.                    
    129.                 }
    130.                  PhotonNetwork.Destroy(gameObject);
    131.             }
    132.             else
    133.             {
    134.                 Explode();
    135.             }
    136.          
    137.          
    138.         }
    139.         else
    140.         {
    141.         }
    142.        
    143.  
    144.     }
    145. }
    146.  
    147. public enum DamageType{COLLISION,RADIAL}
    148.  
     
  2. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,062
    The exception log you got, lists the exact line of code which fails. It is important that you learn how to read those exceptions and begin debugging them, or you will be stuck endlessly.
    We don't know which line to look at and then, some of the references may be setup in game objects, etc. It's near impossible to help.
     
  3. unity_A4E6F287CE1664E193BF

    unity_A4E6F287CE1664E193BF

    Joined:
    Jun 9, 2022
    Posts:
    18
    NullReferenceException: Object reference not set to an instance of an object
    MultiplayerGamePlayController.OnEventReceive (ExitGames.Client.Photon.EventData data) (at Assets/Multiplayer/Scripts/MultiplayerGamePlayController.cs:101)
    Triggered when any player dies.
    i dont know why the sourcePlayer var is null?in this code part, should check the victim player, then check if there ar any player with the same victim's teams to show the game over panel. Team Deathmatch game.
     
  4. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,062
    Try to figure out if the source player can be read from the event. If not, try to figure out which value was sent and why it's not found on the receiving side.
    Sorry, can't check out your code in detail...