Lobby Voice Chat

Options
So I have a system that works perfect for displaying players and showing what teams they're on. However, if I try to allocate a view id for voice chat that's when the troubles start. The initial spawning of the child objects that represent the player works great. However, if I ever update for any reason I get a duplicate view id error and voice chat no longer works. Please help!

Here is what I'm doing.

Here are all the methods that I use to detect when this list needs to be updated.
private void OnEnable()
        {
            logic = FindObjectOfType<UICoreLogic>();
            logic.teamsUpdated += WaitRefresh;
            logic.voiceViewUpdated += WaitRefresh;
        }
        private void OnDisable()
        {
            logic.teamsUpdated -= WaitRefresh;
            logic.voiceViewUpdated -= WaitRefresh;
        }
void Update()
        {
            if (PhotonNetwork.IsConnected && PhotonNetwork.InRoom && _prevPlayerCount != PhotonNetwork.CurrentRoom.PlayerCount)
            {
                _prevPlayerCount = PhotonNetwork.CurrentRoom.PlayerCount;
                if (autoSetTeamIfNotSet == true)
                {
                    AutoSelectTeam();
                }
                WaitRefresh();
            }
        }

Here is the refresh logic:
public void WaitRefresh()
        {
            StartCoroutine(WaitToRefresh());
        }
        System.Collections.IEnumerator WaitToRefresh()
        {
            yield return new WaitForEndOfFrame();
            RefreshList();
        }
void RefreshList()
        {
           DestroyChildObjects();
           SpawnChildObjects();
        }
void SpawnChildObjects()
        {
            if (debugging == true) Debug.Log("Current Player Count: " + PhotonNetwork.CurrentRoom.Players.Count);
            foreach (KeyValuePair<int, Photon.Realtime.Player> target_player in PhotonNetwork.CurrentRoom.Players)
            { 
                SpawnChild(target_player);
            }
        }
void DestroyChildObjects()
        {
            if (debugging == true) Debug.Log("Destroy child objects...");
            foreach (Transform child in parentObj)
            {
                if (allocateViewIds == true)
                {
                    if (child.GetComponent<PhotonView>())
                    {
                        PhotonNetwork.LocalCleanPhotonView(child.GetComponent<PhotonView>());
                    }
                }
                Destroy(child.gameObject);
            }
        }
void SpawnChild(KeyValuePair<int, Photon.Realtime.Player> target_player)
        {
            if (string.IsNullOrEmpty(teamName) || teamName == logic.GetUserTeamName(target_player.Value.UserId))
            {
                ... <logic for setting images, names, etc.>...
                if (allocateViewIds == true)
                {
                    if (newChild.GetComponent<PhotonView>())
                    {
                        if (logic.GetPlayerVoiceView(target_player.Value.UserId) == 9999 && PhotonNetwork.IsMasterClient == true)
                        {
                            logic.SendUpdateVoiceView(target_player.Value.UserId, PhotonNetwork.AllocateViewID(target_player.Value.ActorNumber));
                        }
                        else if (logic.GetPlayerVoiceView(target_player.Value.UserId) != 9999)
                        {
                            newChild.GetComponent<PhotonView>().ViewID = logic.GetPlayerVoiceView(target_player.Value.UserId);
                            newChild.GetComponent<PhotonView>().OwnershipTransfer = OwnershipOption.Takeover;
                            newChild.GetComponent<PhotonView>().TransferOwnership(target_player.Value);
                        }
                    }
                }
            }
        }

Here is the logic for sending updated view ids and getting the current set view ids:
public void SendUpdateVoiceView(string UserId, int ViewId)
        {
            object[] data = new object[] { UserId, ViewId };
            RaiseEventOptions options = new RaiseEventOptions
            {
                CachingOption = EventCaching.AddToRoomCacheGlobal,
                Receivers = ReceiverGroup.All
            };
            if (debugging == true) Debug.Log("Raising CB_EVENT_VOICEVIEW photon event with data { "+UserId+", "+ViewId+" }...");
            PhotonNetwork.RaiseEvent(PhotonEventCodes.CB_EVENT_VOICEVIEW, data, options, SendOptions.SendReliable);
        }
public int GetPlayerVoiceView(string UserId)
        {
            return (_playerVoiceChatViews.ContainsKey(UserId)) ? _playerVoiceChatViews[UserId] : 9999;
        }

The objects get destroyed and created correctly, the view ids are getting duplicated and not connecting correctly. To be honest I don't know what I'm missing here. I think I need to somehow purge all the active view ids or something locally when I delete the objects but that's a guess.

Comments

  • wesleywh
    Options
    Oh I forgot to post this. This is the logic for when you receive the raised event to set a new id:
    void PhotonEvent_VOICEVIEW(object[] data)
            {
                string UserId = (string)data[0];
                int ViewId = (int)data[1];
                if (debugging == true) Debug.Log("Recieved new VOICEVIEW, UserId: " + UserId + ", ViewID: " + ViewId);
                if (_playerVoiceChatViews.ContainsKey(UserId))
                {
                    if (debugging == true) Debug.Log("Updating, UserId: " + UserId + ", To ViewID: " + ViewId);
                    _playerVoiceChatViews[UserId] = ViewId;
                }
                else
                {
                    if (debugging == true) Debug.Log("Adding new UserId: "+UserId+", With ViewID: "+ViewId);
                    _playerVoiceChatViews.Add(UserId, ViewId);
                }
                if (voiceViewUpdated != null) voiceViewUpdated.Invoke();
            }
    
  • wesleywh
    Options
    PhotonView ID duplicate found: 1002. New: View 1002 on PropHuntOtherPlayer(Clone)  old: View 1002 on PropHuntOtherPlayer(Clone) . Maybe one wasn't destroyed on scene load?! Check for 'DontDestroyOnLoad'. Destroying old entry, adding new.
    UnityEngine.Debug:LogError(Object)
    
    That's the error for context
  • wesleywh
    Options
    Okay! Simple. I figured it out.

    It boils down to the fact that I was creating my child objects too fast after calling the destroy function. So it still had child objects sitting the in game when it tried to create new ones, which resulted in a PhotonView id clash. To get round this error I did the following:

    I deleted this function:
    void RefreshList()
            {
               DestroyChildObjects();
               SpawnChildObjects();
            }
    

    and modified my WaitToRefresh function to look like the following:
    System.Collections.IEnumerator WaitToRefresh()
    {
       yield return new WaitForEndOfFrame();
       DestroyChildObjects();
       yield return new WaitForEndOfFrame();
       SpawnChildObjects();
    }
    

    Now it assigns photon view ids correctly as well as keeps a list of disconnected players and reassigns that view id back correctly on reconnects.
  • wesleywh
    wesleywh
    edited April 2020
    Options
    Nevermind. I'm back.

    After playing a game I rejoin the lobby and it duplicates everything twice. Not sure why. It seems like it might have something to do with it remembering those photon views and re instantiating them.

    I must need to clean my cache or something. Not sure what the right thing to do here is....
  • wesleywh
    Options
    Ugh, kicking myself again. I figured it out. All the code above works perfect. I had a delegate that I was assigning:
    PhotonNetwork.NetworkingClient.EventReceived += RecievedPhotonEvent;
    
    When I ran the reset code I wasn't doing:
    PhotonNetwork.NetworkingClient.EventReceived -= RecievedPhotonEvent;
    
    So it would basically double up each time because it would register itself twice (or however many times I tried this until I gave up).
  • wesleywh
    Options
    So if nothing else that's a perfect example for people to look at on how to manage your own PhotonView Ids and put it into a lobby system.