Adapting Unity Shooter example to Ready Player Me: avatar skins

Post here your questions about SFS2X. Here we discuss all server-side matters. For client API questions see the dedicated forums.

Moderators: Lapo, Bax

Post Reply
XyrisKenn
Posts: 17
Joined: 20 Nov 2022, 08:32

Adapting Unity Shooter example to Ready Player Me: avatar skins

Post by XyrisKenn »

Hello, per the title I'm working out loading RPM avatar skins in the Unity Shooter example (actually in my own project adapting Shooter Unity + Java).
I'm more familiar with Photon, so I'm working out how to do this in SF2X.

TL;DR: Can I send the RPM avatar URL from the Unity side as a network method, call to load the avatar skin, or does this need to go through the Shooter java extension?

Use Case:
1. User provides a RPM avatar ID or URL with the RPM SDK 6.0.1
2. This ID/URL is saved on the local player's computer and sent as a buffered network call to the room.
3. On Joined Room, the local and remote versions of this player load their avatar, using the ID/URL.

Question: Can I send SF2X network method calls to load the avatar skin, or, is it necessary to use User Variables and code into the java extension?

Long Description
The RPM Photon example attaches a 'network' script to load the avatar. There may be other code in their runtime dll I can't access.

RPM Photon example:
Unity game: Photon world controller:

Code: Select all

public override void OnJoinedRoom()
{
    Debug.Log("Joined room");
   
    UI.SetActive(false);
    GameObject character = PhotonNetwork.Instantiate("RPM_Photon_Test_Character", Vector3.zero, Quaternion.identity);
    character.GetComponent<NetworkPlayer>().LoadAvatar(inputField.text);
}


Unity player prefab: Network code, attached to the avatar prefab itself:

Code: Select all

public void LoadAvatar(string url)
{
    photonView.RPC(SET_PLAYER_METHOD, RpcTarget.AllBuffered, url);
}

[PunRPC]
private void SetPlayer(string incomingUrl)
{
    AvatarObjectLoader loader = new AvatarObjectLoader();
    loader.LoadAvatar(incomingUrl);
    loader.AvatarConfig = config;
    loader.OnCompleted += (sender, args) =>
    {
        leftEye.transform.localPosition = AvatarBoneHelper.GetLeftEyeBone(args.Avatar.transform, true).localPosition;
        rightEye.transform.localPosition = AvatarBoneHelper.GetRightEyeBone(args.Avatar.transform, true).localPosition;

        AvatarMeshHelper.TransferMesh(args.Avatar, gameObject);
        Destroy(args.Avatar);
    };
}


So Photon, being non-authorative, sends the load avatar command to its local and remote instances in the same room other players are in, so remote players see the new player's Ready Player Me skin. This approach appears not store the RPM ID/URL, but just passes that string value along through the network as a function.

SmartFox Server 2X
Smartfox has the User Variable. When updated, all players in the same room receive the updated value. In the Shooter example, this appears to be used for health as an example. My initial thought was to add a string variable to CombatPlayer.java and possibly a handler in World.java.

However there's no need to keep the Ready Player Me URL stored with the player on the java server side once the skin is loaded. It only needs to be stored on the local player's computer and sent when joining the room to update that player's avatar appearance in the room.

If a player disconnects and reconnects, they've rejoined the room and so the local stored RPM ID/URL would be sent again.
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Adapting Unity Shooter example to Ready Player Me: avatar skins

Post by Lapo »

TL;DR: Can I send the RPM avatar URL from the Unity side as a network method, call to load the avatar skin, or does this need to go through the Shooter java extension?

What is a "network method" exactly? I've never heard that before.

Thanks
Lapo
--
gotoAndPlay()
...addicted to flash games
XyrisKenn
Posts: 17
Joined: 20 Nov 2022, 08:32

Re: Adapting Unity Shooter example to Ready Player Me: avatar skins

Post by XyrisKenn »

What is a "network method" exactly? I've never heard that before.
Thanks[/quote]

Reading up, I'll use proper nomenclature:
1. Sending SFSObject containing the Ready Player Me URL for that user with Player (CombatPlayer).
- Appears to need also server-side code to process that variable - that variable can't currently be found client side in the data object.
Seems the most ideal because it times correctly with instantiation and is carried along with the User object, but it seems to need server Extension changes and JAR recompilation.

2. SFSRoomVariable: I think this can be sent client to client without the server. I assume the room needs to hold a list of players and ensure their RPM avatar is loaded in all the room's users' instances. IIRC changing a room variable updates automatically in all that room's users' instances.

3. SFSUserVariable: I've tried having the user itself load their own avatar after joining the room / instantiation. I have the local player save their RPM avatar in global variables (Game Creator), but this leads to all avatars in a player's room loading the same avatar they'd chosen in the earlier RPM avatar creator scene. This also updates automatically but timing the lag between joining the room / instantiation / loading the default prefab night create race conditions.

I think I'm 60% on the right path, and missing a bit of detail to do this correctly.
My dev machine has Eclipse with Java, but loading the Shooter java files has missing code references.
Visual Studio, I've looked into Java integration but it appears roundabout. My experience is with Objective-C and Swift. So adapting server code atm is just out of reach.
Smartfox extension code.jpg
(88.01 KiB) Not downloaded yet


Here's my thread on Ready Player Me trying to work out the solution from their side: https://forum.readyplayer.me/t/using-av ... -unity/183
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Adapting Unity Shooter example to Ready Player Me: avatar skins

Post by Lapo »

Reading up, I'll use proper nomenclature:
1. Sending SFSObject containing the Ready Player Me URL for that user with Player (CombatPlayer).
- Appears to need also server-side code to process that variable - that variable can't currently be found client side in the data object.
Seems the most ideal because it times correctly with instantiation and is carried along with the User object, but it seems to need server Extension changes and JAR recompilation.

I get that you're trying to send an URL but it's not clear from where and to whom...
1) from server side to a client?
2) from client to other clients?
3) from client to server only?

2. SFSRoomVariable: I think this can be sent client to client without the server. I assume the room needs to hold a list of players and ensure their RPM avatar is loaded in all the room's users' instances. IIRC changing a room variable updates automatically in all that room's users' instances.

That's correct.

3. SFSUserVariable: I've tried having the user itself load their own avatar after joining the room / instantiation. I have the local player save their RPM avatar in global variables (Game Creator), but this leads to all avatars in a player's room loading the same avatar they'd chosen in the earlier RPM avatar creator scene. This also updates automatically but timing the lag between joining the room / instantiation / loading the default prefab night create race conditions.

You can customize User variables at login time so that every player that logs in will have their own values.
On the server side you can listen for the USER_JOIN_ZONE event, which triggers after a successful login and set the User's variable accordingly.

I think I'm 60% on the right path, and missing a bit of detail to do this correctly.
My dev machine has Eclipse with Java, but loading the Shooter java files has missing code references.
Visual Studio, I've looked into Java integration but it appears roundabout. My experience is with Objective-C and Swift. So adapting server code atm is just out of reach.
Smartfox extension code.jpg

Java Extension depend on a few jar files (typically sfs2x.jar, sfs2x-core.jar). You can add them to your Eclipse project to resolve those errors. Check the docs here for the details --> https://docs2x.smartfoxserver.com/Exten ... extensions

Cheers
Lapo
--
gotoAndPlay()
...addicted to flash games
XyrisKenn
Posts: 17
Joined: 20 Nov 2022, 08:32

Re: Adapting Unity Shooter example to Ready Player Me: avatar skins

Post by XyrisKenn »

Hi Lapo, thank you. I' don't know which approach is the best/most reliable, and gradually learning how SF2X best works in this situation.

I'm trying to get all players in a room to load their Ready player Me avatar once their default avatar mesh is instantiated.
The Ready Player Me avatar is loaded from a URL via their SDK. I capture the URL in a preceeding scene, and am figuring out how best to have that URL travel along with the user data. It's just a multiplayer scenario with custom avatars loaded as needed.

Local Client: user chooses their avatar and gets the RPM url.
Local Client: user enters lobby then a room.
Remote Client: remote use sees the new user in the room. A moment later their default avatar skin is updated with the RPM avatar skin the (to them, remote) user chose.
XyrisKenn
Posts: 17
Joined: 20 Nov 2022, 08:32

Re: Adapting Unity Shooter example to Ready Player Me: avatar skins

Post by XyrisKenn »

Respawning my thread :)
Now I'm clearer on SF2x vs Photon, as mentioned I have an example working, except for remote avatar skins not loading, instead, remote avatars look like the local player's avatar, because I'm using a global variable.

Use case
SO to recap: basic idea is to ensure the local player has their avatar URL stored in a user variable after login but before entering a room.
Once in a room, update the Room variable of users with this new person. The change should propagate to all users' local Room instances and load this new player's avatar skin.

Architecture
SFSUserVariable avatarURL: my unskinned avatar prefab should have this variable associated with it in some way. In Photon I used a Unity component with a LocalVariable script attached to it.

SFSRoomVariable: when a user joins the room, there must be a list of Users logged into the room; when the new user loads, this changes the room list, which should update all users. I must iterate through this room list for each user and check if each remote user has loaded their avatar skin. If not, then load the skin using the avatarURL user variable stored there.

I'm not 100% on the exact logic flow and code, but this appears to be the way, and does not need any coding on the server side, only code on the client side.

I'm figuring out UserVariables notifying other players in a room by adapting my Room - instantiate player script.
If the player is 'Mine', I've added:

Code: Select all

 List<UserVariable> userVariables = new List<UserVariable>();
 userVariables.Add(new SFSUserVariable("event", (string)"hundo CareerCon22"));
 userVariables.Add(new SFSUserVariable("rpm_url", (string)"https://models.readyplayer.me/6607aa671791600d6e6c08e4.glb"));
 userVariables.Add(new SFSUserVariable("rpm_id", (string)"6607aa671791600d6e6c08e4"));
 smartFox.Send(new SetUserVariablesRequest(userVariables));


Progress:
In the Room, after player instantiation, I can access and list these variables as such:

Code: Select all

List<UserVariable> vars = user.GetVariables();
foreach(UserVariable var in vars)
{
    Debug.Log(var.Name + ":" + var.Value);
}


Super simple. Next, is ensuring the local player can load their RPM avatar. Next, remote players' avatars load if a check ensures a remote player avatar skink is not yet loaded.

Update:
This works for the local player: :)

Code: Select all

String rpmid = user.GetVariable("rpm_id").Value.ToString();
 if (rpmid.Length > 0)
 {
     Debug.Log("Getting player RPM within player is null function: " + rpmid);
     playerObj.GetComponent<SF2XCharacterController.NetworkPlayer>().LoadAvatar(rpmid);
 };
Post Reply