cancel
Showing results for 
Search instead for 
Did you mean: 

Meta avatar 2 multiplayer

fredoculuss
Honored Guest

Hello everyone. 

I'm trying to use the new meta avatars in multiplayer but I struggle with implementation. I tried with Photon Pun 2 and the sample scene "network loopback" but I'm unable to achieve proper networking. 

Has anyone achieved multiplayer with the new avatar sdk or know a documentation or tutorial I can use to make it work?

Thanks a lot.

42 REPLIES 42

I'm having exactly the same problem.  Did you ever figure out how to solve this?

olaysia
Expert Protege

Yes, read through the replies.

Hi Olaysia - thanks for sharing this super useful code. I was trying to reply to Evans_Taylor_Digital as I'm having the same problem - using your code like-for-like but no game objects instantiating inside the remote avatar.  Everything looks like it's happening as it should - ConfigureAvatarEntity() is setting the isLocal flag and the creation info is being properly set to the remote preset before Awake in the base class runs, but nothing is created inside the OtherAvatar game object.  I had partial success using ForceEnableFeatures() to set UseDefaultAnimHierarchy - doing that fixed the spawning of the children inside the OtherAvatar game object and I could see them moving around over the network, but no meshes were visible. I'll continue trying things and add this to the thread if I get it working. It sounds like most people got this working with the code you posted so it's obviously something I'm doing wrong.

 

 

olaysia
Expert Protege

Oh, my bad. I thought this was a reply to one of my earlier posts.

It sounds like your other avatar prefab is instantiating but its failing to load its meta avatar. How are you instantiating the other avatar? Are you passing it a user id to load? Because if it doesn't have a user id it won't be able to load its avatar.

I think you're right. I am using your code:

Int64 userId = Convert.ToInt64(m_userId);
        object[] objects = new object[1] { userId };
        GameObject myAvatar = PhotonNetwork.Instantiate("NetworkAvatar", spawnPos, Quaternion.identity, 0, objects);

 

But I think m_userId is null because I'm not getting the value properly from the other script.  It's really helpful to know that if I'm not passing the value it won't spawn any mesh. Kind of obvious now you pointed it out - thank you!

Yes! You're going to need to fetch a user id before you photon instantiate that avatar: Here's how I did it:

public class LogInManager : MonoBehaviourPunCallbacks
{
    const string ROOM_NAME = "Meta Avatar Sdk Test Room";
    const float SPAWN_POS_Z = 1f;
    const string AVATAR_PREFAB_NAME = "GGMetaAvatarEntity";

    [SerializeField] Text m_screenText;
    [SerializeField] Camera m_camera;
    [SerializeField] float m_minSpawnPos_x = -5f;
    [SerializeField] float m_maxSpawnPos_x = 5f;
    [SerializeField] float m_minSpawnPos_z = -5f;
    [SerializeField] float m_maxSpawnPos_z = 5f;
    [SerializeField] ulong m_userId;

    //Singleton implementation
    private static LogInManager m_instance;
    public static LogInManager Instance
    {
        get
        {
            return m_instance;
        }
    }
    private void Awake()
    {
        if (m_instance == null)
        {
            m_instance = this;
        }
        else
        {
            Destroy(this.gameObject);
        }
    }

    void Start()
    {
        StartCoroutine(SetUserIdFromLoggedInUser());
        StartCoroutine(ConnectToPhotonRoomOnceUserIdIsFound());
        StartCoroutine(InstantiateNetworkedAvatarOnceInRoom());
    }

    IEnumerator SetUserIdFromLoggedInUser()
    {
        if (OvrPlatformInit.status == OvrPlatformInitStatus.NotStarted)
        {
            OvrPlatformInit.InitializeOvrPlatform();
        }

        while (OvrPlatformInit.status != OvrPlatformInitStatus.Succeeded)
        {
            if (OvrPlatformInit.status == OvrPlatformInitStatus.Failed)
            {
                Debug.LogError("OVR Platform failed to initialise");
                m_screenText.text = "OVR Platform failed to initialise";
                yield break;
            }
            yield return null;
        }

        Users.GetLoggedInUser().OnComplete(message =>
        {
            if (message.IsError)
            {
                Debug.LogError("Getting Logged in user error " + message.GetError());
            }
            else
            {
                m_userId = message.Data.ID;
            }
        });
    }

    IEnumerator ConnectToPhotonRoomOnceUserIdIsFound()
    {
        while (m_userId == 0)
        {
            Debug.Log("Waiting for User id to be set before connecting to room");  
            yield return null;
        }
        ConnectToPhotonRoom();
    }

    void ConnectToPhotonRoom()
    {
        PhotonNetwork.ConnectUsingSettings();
        m_screenText.text = "Connecting to Server";
    }

    public override void OnConnectedToMaster()
    {
        PhotonNetwork.JoinLobby();
        m_screenText.text = "Connecting to Lobby";
    }

    public override void OnJoinedLobby()
    {
        m_screenText.text = "Creating Room";
        PhotonNetwork.JoinOrCreateRoom(ROOM_NAME, null, null);
    }

    public override void OnJoinedRoom()
    {
        string roomName = PhotonNetwork.CurrentRoom.Name;
        m_screenText.text = "Joined room with name " + roomName;
    }

    IEnumerator InstantiateNetworkedAvatarOnceInRoom()
    {
        while (PhotonNetwork.InRoom == false)
        {
            Debug.Log("Waiting to be in room before intantiating avatar");
            yield return null;
        }
        InstantiateNetworkedAvatar();
    }

    void InstantiateNetworkedAvatar()
    {
        float rand_x = UnityEngine.Random.Range(m_minSpawnPos_x, m_maxSpawnPos_x);
        float rand_z = UnityEngine.Random.Range(m_minSpawnPos_z, m_maxSpawnPos_z);
        Vector3 spawnPos = new Vector3(rand_x, SPAWN_POS_Z, rand_z);
        Int64 userId = Convert.ToInt64(m_userId);
        object[] objects = new object[1] { userId };
        GameObject myAvatar = PhotonNetwork.Instantiate(AVATAR_PREFAB_NAME, spawnPos, Quaternion.identity, 0, objects);
        m_camera.transform.SetParent(myAvatar.transform);
        m_camera.transform.localPosition = Vector3.zero;
        m_camera.transform.localRotation = Quaternion.identity;
    }

}

owain_rich
Honored Guest

Thanks Olaysia - this worked perfectly - remote and local avatars showing up with the correct users. By looking through the code I now understand how this is working too. This whole thread is fantastic and will help a lot of people figure this out!

I use Normcore. It seems easier than PUN, but meta avatar usage is difficult no matter how you slice it.

Hi, can you please tell what is m_userId here.

It's the local variable that holds the result of the message requested.

m_userId = message.Data.ID;