PUN and Oculus Avatars crash

Hello, i have a problem with my app that uses Oculus Avatars with PUN. Problem is that i have a Oculus GO headset that crashes after a few runnigs of the app.

https://pastebin.com/0m6RHW1b - avatar serialization code

https://i.imgur.com/rJkt45r.png
https://i.imgur.com/Y0QlHyD.png
logs of the crash.

Thank you in advance.

Comments

  • tavilad
    tavilad
    edited December 2018
    Forgot to mention, i also get InvalidCastException on this line
    byte[] data = (byte[]) stream.ReceiveNext();
    from OnPhotonSerializeView.

    I am using the latest version of Oculus Integration.
  • bump :(
  • Hi @tavilad,

    Forgot to mention, i also get InvalidCastException on this line
    byte[] data = (byte[]) stream.ReceiveNext();
    from OnPhotonSerializeView.


    Which transport protocol do you currently use? If it is UDP, the data might be corrupted. Does this happen in every OnPhotonSerializeView call or just from time to time? If you use UDP, please try enabling CRC check. You can do this by using PhotonNetwork.CrcCheckEnabled = true; before connecting to Photon. If this doesn't solve the issue, please try changing the transport protocol to TCP and check if it is different afterwards. Before calling stream.ReceiveNext(), you can also check if there is a next element in the stream. This can be done by adding the following code snippet for example:
    if (stream.PeekNext() == null)
        continue;
    Please let me know if any of these tips help you solving this problem.

    In terms of crashing of the app: I sadly can't test on an actual Oculus GO device. I have tried to run this on an Android device and an Android emulator, but didn't get it working. The code snippet you provided for the Avatar Synchronization looks fine so far.
  • Thank you @Christian_Simon for the tips. Currently testing the changes you suggested, will come back with a conclusion.
  • The problem still ocurs. It happens 100% of the time when i disconnect from the room, create another, and join with a new client that restarted the application. The invalid cast exception has been fixed, but the app still crashes.
  • Can you take a look at the logs of the crashed application? Are those different compared to the screenshots you have posted above? If you have the chance, can you please post them in text form again? It's much easier looking at text than at the screenshots.

    I'm currently not sure, if this is a problem with PUN, the Oculus tools or a combination of both of them.
  • tavilad
    tavilad
    edited December 2018
    I think i managed to fix this, i had some objects that were not destroyed when moving between scenes. Still, my suspicion is that the avatar serialization is causing some kind of memory leak.
    edit:nevermind, still crashes.
  • cloud_canvas
    edited November 2021
    Hey @tavilad, I think I've managed to come up with a sensible hack for this issue. You need to modify OvrAvatar.cs a little bit for this fix.

    First, in OvrAvatar.cs, add a bool called Initialized and set it to false. I put it at line 71, at the end of all of the public field definitions.

    Then, at the end of CombinedMeshLoadedCallback(), set Initialized to true. In my script, that's line 205.

    This, and a check-in with the Oculus Platform, are the additional pieces of what you need to build a boolean check that rejects incoming and outgoing packets in PhotonAvatarView.cs if your app is somehow not ready to send or receive Avatar poses.

    In the documentation for Photon and Oculus Avatars (now deleted) they put one check on the serialization process, and that's at the top of OnLocalAvatarPacketRecorded().

    public void OnLocalAvatarPacketRecorded(object sender, OvrAvatar.PacketEventArgs args) { if (!PhotonNetwork.InRoom || (PhotonNetwork.CurrentRoom.PlayerCount < 2)) { return; } ... }

    I've broken this out into its own bool called NotReadyForSerialization and it's defined (in PhotonAvatarView.cs) as:

    private bool notReadyForSerialization { get { return (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom.PlayerCount < 2 || !Oculus.Platform.Core.IsInitialized() || !ovrAvatar.Initialized); } }

    So, in addition to making sure you're in a room and that there's more than one person in the room, it checks if the Oculus Platform is initialized and also our new boolean that we put into OvrAvatar.cs.

    I've placed this bool check at the top of not only OnLocalAvatarPacketRecorded() but also DeserializeAndQueuePacketData() and OnPhotonSerializeView().

    (if (notReadyForSerialization) { return; }

    This has given me a solution that doesn't crash, or create any errors in logcat.

    Hope that helps.
  • Hi @cloud_canvas,

    thank you for sharing your findings. I have added those to a 'Known Issues' section on the related documentation page.
  • cloud_canvas
    edited January 2019
    I just discovered something else quite useful related to this. I noticed that when a player enters or exits the room, PhotonAvatarView tends to spit out a handful of InvalidCastException errors. This happens at the deserialization stage of OnPhotonSerializeView, usually at the first call to (int)stream.RecieveNext().
    Maybe it's a race condition between PhotonNetwork delisting that PhotonView and OvrAvatar recording and delivering serialized packets or something. Regardless, I found a trick for suppressing this.

    Before you do any kind of stream.ReceiveNext() call in a stream.IsReading pass, encapsulate it inside a check like this:
    if (stream.PeekNext() is int nextVal) { int num = (int)stream.RecieveNext(); ... }

    The is keyword is a type-check, so it will reject malformed deserialized packets.

    In this case, the type is int, but I'm using this same trick elsewhere for other types. The use of PeekNext() specifically is important so that you do not consume the next piece of data while checking its type.
    Hope that helps someone else!
  • if((bool)stream.PeekNext()){ .......}

    If this is correct syntax before int num = (int)stream.RecieveNext(); in PUN2 dcumentation