Trouble accessing UserVariable in Unity

Post here your questions about the Unity / .Net / Mono / Windows 8 / Windows Phone 8 API for SFS2X

Moderators: Lapo, Bax

Post Reply
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Trouble accessing UserVariable in Unity

Post by specterdragon »

I'm hoping someone out there might know the answer to this one. It seems simple enough, but for some reason I'm missing something. I'm having trouble accessing user variables. I can get the user (that was no problem) but accessing the variables seems to be an issue.

Server side (in a room extension handler):

Code: Select all

UserVariable na = new SFSUserVariable("na", "My Character Name");
getApi().setUserVariables(user, Arrays.asList(na));

try {
    Room room = getParentExtension().getParentZone().getRoomByName(room_name);
    if (room == null) {
        throw new SFSException("Room ("+room_name+") is unavailable/not created");
    }
    getApi().joinRoom(user, room);
    SFSMMOApi mmoApi = (SFSMMOApi)SmartFoxServer.getInstance().getAPIManager().getMMOApi();
    mmoApi.setUserPosition(user, new Vec3D(0.0f, 0.0f, 0.0f), room);
    
} catch (SFSException e) {
    trace("CharacterManagerEventHandler.EnterWorld exception: "+e.getMessage());
}
When the above code runs, I can look in the admin tool and see the variable created and the user in the MMO room.

Client side: (Note: this_user is set as a class variable in the handler and outputs the user info without any problem.)

Code: Select all

	void OnRoomJoin(BaseEvent e){
		Debug.Log ("Successfully joined room: "+e.Params["room"]+ " as: " +this_user);
		sfs.RemoveAllEventListeners();

		List<User> users = sfs.UserManager.GetUserList();
		foreach (User user in users){
			Debug.Log (user);
			List<UserVariable> vars = user.GetVariables();
			foreach (UserVariable var in vars){
				Debug.Log(var.Name + ":"+var.Type);
			}
		}

		Debug.Log(this_user.GetVariable("na").GetStringValue());
	}
Unity's debug log gives the following:

Code: Select all

Successfully joined room: [Room: Playground, Id: 1, GroupId: default] as: [User: testuser, Id: 3, isMe: True]
UnityEngine.Debug:Log(Object)

[User: testuser, Id: 3, isMe: True]
UnityEngine.Debug:Log(Object)

NullReferenceException: Object reference not set to an instance of an object
CharacterManager.OnRoomJoin (Sfs2X.Core.BaseEvent e)
Notice that it "appears" to skip over the foreach loop for user variables but it does see the user list, implying that GetVariables() is returning null - same with GetUserVariable("na"), which is evident in the null reference.

This seems to follow the pattern in the docs unless I'm missing something. Any ideas where I've gone astray? Could the room join be happening before the vars are set on the server (and thus creating an async issue)?

Any help is appreciated at this point.
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Re: Trouble accessing UserVariable in Unity

Post by specterdragon »

On an interesting side note, if I change the room to a regular game room (non-MMO room) then I can access the variables. It's only when I set the room to an MMO that it fails. I've set the position and can see the user in the list, so my assumption (since I'm looking for "this" user) is that it should be accessible. Maybe if this is done in a different order?
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Trouble accessing UserVariable in Unity

Post by Lapo »

Hi,
your client side code is a little strange.

Why removing all listeners in the JoinRoom event? Might not be relevant but I'd comment that out.

Also it's not clear whose variables you're trying to access. The OnJoin event is fired in response to the client's join request (be it server side or client side), so I take it that you want to access the player's variable?

If that's the case the User object is passed in the event parameters.
What you're doing is looping through all Users in the local client trying to access their variables. I guess it's possible some of them don't have variables?

If you could clarify that... thanks
Lapo
--
gotoAndPlay()
...addicted to flash games
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Re: Trouble accessing UserVariable in Unity

Post by specterdragon »

Sorry for the confusion, that's the trouble with knowing ones own code and leaving out the important details. :lol: This is slightly modified code that was intended to make things more clear - obviously that didn't work LOL

At the end of the SFSEvent.ROOM_JOIN handler in this scene (lobby), I have Unity load a new scene (game level). When it changes scenes, we need to remove the registered listeners before loading the next scene and it's scripts because the listener callbacks are no longer in scope when the scene changes - then they have to be re-registered with new callbacks. For this illustration, that line should make no difference. I tried commenting it out just to make sure.

Here's basically what is supposed to happen:
1. The player logs in, joins a specific zone and a specific lobby room. (successful)
2. When the lobby is joined, I get the player's user object and store it as this_user. (successful - or so it seems)
3. Since SFSEvent.ROOM_JOIN doesn't pass a user in the params (http://docs2x.smartfoxserver.com/api-do ... .ROOM_JOIN), I used the following code to get a reference to the current player's user object:

Code: Select all

		List<User> users = sfs.UserManager.GetUserList();
		foreach (User user in users){
			if (user.IsItMe){
				this_user = user;
				return;
			}
		}
4. Before the server joins the user to the game room, it sets some variables for that user (I picked "name" for illustration, but it doesn't seem to matter which variables I try to get. In reality, I'm looking for a string that represents the next Unity scene file - but it's just a string).
5. The client fires the ROOM_JOIN callback (which includes the above client code from the original post) and gets the string variable for the previously stored this_user. (this fails in an MMO room but works in non-MMO rooms).

The loop code was added as a test to see what users were visible to the client and what variables are visible on those users. When that piece of code runs, it shows the player's user object (which matches this_user), but appears to have no variables.

Since this is only happening in an MMO Room and not a normal game room, it seems like I'm missing something obvious - that the user isn't visible in the AOI and the variables cannot be accessed for that reason. The part I don't get is that this is the player's user object (the only user in the game) and it should always be able to see it's own variables shouldn't it?
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Trouble accessing UserVariable in Unity

Post by Lapo »

specterdragon wrote: At the end of the SFSEvent.ROOM_JOIN handler in this scene (lobby), I have Unity load a new scene (game level). When it changes scenes, we need to remove the registered listeners before loading the next scene and it's scripts because the listener callbacks are no longer in scope when the scene changes - then they have to be re-registered with new callbacks.
I hope this doesn't cause some events to be lost in the transition between levels... ? But let's look for simpler explanations first...

1. The player logs in, joins a specific zone and a specific lobby room. (successful)
2. When the lobby is joined, I get the player's user object and store it as this_user. (successful - or so it seems)
3. Since SFSEvent.ROOM_JOIN doesn't pass a user in the params (http://docs2x.smartfoxserver.com/api-do ... .ROOM_JOIN), I used the following code to get a reference to the current player's user object:
Oh but there's a much easier way. :)

Code: Select all

User me = sfs.MySelf;
The MySelf object is populated after the login and always available, that's why the User object is not passed in the join event. Sorry for not having mentioned this in the previous post.
4. Before the server joins the user to the game room, it sets some variables for that user (I picked "name" for illustration, but it doesn't seem to matter which variables I try to get. In reality, I'm looking for a string that represents the next Unity scene file - but it's just a string).

5. The client fires the ROOM_JOIN callback (which includes the above client code from the original post) and gets the string variable for the previously stored this_user. (this fails in an MMO room but works in non-MMO rooms).
Yeah this is the weird part. Can you take a look at the debug logs in the editor and see in which order you're getting the events?
I'd expect a USER_VARIABLE_UPDATE to arrive before the JOIN_ROOM. Even if you don't listen to the client event, you can still see the data in the debug.
Maybe you can copy/paste it here?
Lapo
--
gotoAndPlay()
...addicted to flash games
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Re: Trouble accessing UserVariable in Unity

Post by specterdragon »

Forgot to add this: I'm using server v2.10.0 and C# client v 1.6.0 (debug)
Oh but there's a much easier way. :)

Code: Select all

User me = sfs.MySelf;
Nice :D I knew there had to be an easier way.
Yeah this is the weird part. Can you take a look at the debug logs in the editor and see in which order you're getting the events?
I'd expect a USER_VARIABLE_UPDATE to arrive before the JOIN_ROOM. Even if you don't listen to the client event, you can still see the data in the debug.
Maybe you can copy/paste it here?
I have a trace on the extension handler so that I can see which MultiHandler request is processed. That's the first entry below. From there, it goes to the room join but there's no user variable update in the log. That seems really odd since I can see the variables in the admin tool. :( I also tried both overloads of setUserVariables to force an event and still nothing in the log.

Code: Select all

SFSWorker:Ext:4 Extensions -- {MyZoneExtension}: handling character.* request: enter_world 
SFSWorker:Ext:4 v2.api.SFSApi -- Room joined: [ MMORoom: Playground, Id: 1, Group: default, AOI: (100.0, 100.0, 100.0) ], { Zone: MyZone}, ( User Name: testuser, Id: 3, Priv: 0, Sess: 127.0.0.1:51219 ) , asSpect: false
For what it's worth, I traced the variable immediately after setting it and got back the following: { N: na, T: STRING, V: My Test Character, H: false } So, that seems right.

I thought it might be the room join, so switched it to an MMORoom - but that didn't seem to help either.

Code: Select all

            MMORoom room = (MMORoom)getParentExtension().getParentZone().getRoomByName(room_name);
            if (room == null) {
                throw new SFSException("Room ("+room_name+") is unavailable/not created");
            }
            getApi().joinRoom(user, room);
Is there some special way to set variables in MMO rooms? (I tried getting the user with sfs.MySelf too, just to be sure and still can't see them.)
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Trouble accessing UserVariable in Unity

Post by Lapo »

Hi,
I am not able to reproduce the problem.

I have tried your steps:

1- connect and login into Zone
2- Join a regular "Lobby" room
3- call Extension
....a) set two user variables (rank, level)
....b) join an MMORoom

4- on ROOM_JOIN (client side) event I print out:
Debug.Log("Level: " + smartFox.MySelf.GetVariable("level"));
Debug.Log("Rank: " + smartFox.MySelf.GetVariable("rank"));

Perfect. Everything works as expected.
I am not sure what else might be going on, on your side.

Are you sure you don't have any server or client side exceptions during the flow?
Is it possible you're using and old version of SFS2X? I don't think I've ever seen this problem in older versions, but stil...

thanks
Lapo
--
gotoAndPlay()
...addicted to flash games
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Trouble accessing UserVariable in Unity

Post by Lapo »

The Extension code I tested with is this:

Code: Select all

		# Set User Vars
		uVars = [SFSUserVariable("level", 100), SFSUserVariable("rank", 50)]
		_sfsApi.setUserVariables(sender, uVars)
		
		print "---> Variables set"
		
		# Join in MMORoom
		targetRoom = sender.getZone().getRoomByName("M1")
		_sfsApi.joinRoom(sender, targetRoom)
		
		print "---> MMO Room Joined: ", targetRoom
I used Python for convenience, but it's calling the same API you'd call in Java.
Lapo
--
gotoAndPlay()
...addicted to flash games
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Re: Trouble accessing UserVariable in Unity

Post by specterdragon »

I appreciate all your help - just wish we could get over this hump because I'm really liking SmartFox for the backend :(

Tried your code (ported to java) just to make sure there isn't something else interfering and still have the same error: vars set on server, room joined, vars not available on client.

Server:

Code: Select all

    private void RoomTest(User sender, ISFSObject objIn){
        // Set User Vars
        UserVariable level = new SFSUserVariable("level", 100);
        UserVariable rank = new SFSUserVariable("rank", 50);
        List<UserVariable> uVars = Arrays.asList(level, rank);
        getApi().setUserVariables(sender, uVars);

        trace("---> Variables set");

        // Join in MMORoom
        Room targetRoom = sender.getZone().getRoomByName("TestRoom");
        try{
            getApi().joinRoom(sender, targetRoom);
        }
        catch (SFSException e) {
            trace("CharacterManagerEventHandler.RoomTest exception: "+e.getMessage());
        }
        trace("---> MMO Room Joined: ", targetRoom);
    }
Client:

Code: Select all

	void OnRoomJoin(BaseEvent e){
		Debug.Log ("Successfully joined room: " + e.Params["room"]+" as: " + sfs.MySelf);

		Debug.Log("Level: " + sfs.MySelf.GetVariable("level").GetIntValue());
		Debug.Log("Rank: " + sfs.MySelf.GetVariable("rank").GetIntValue());
	}
Could there be something in the way the room is set up? You said that a USER_VARIABLE_UPDATE should be in the log, even if I'm not listening for it on the client. I'm not seeing an event entry. I'm wondering if the event is never updating the client (or there's no event at all). In other words, the variable is set on the server side, but it's not sent to the client (so it's null and inaccessible).

I'm using server 2.10.0 and C# client 1.6.0 (debug). Haven't tried any older versions yet.

Seems like there was a similar issue reported in http://forums.smartfoxserver.com/viewto ... 20&t=17695 - although that wasn't the original intent of the thread. Unfortunately, no solution was reported for that issue in the thread.
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Trouble accessing UserVariable in Unity

Post by Lapo »

2.10 is what I used to test too.

A couple of things:
1- Try adding a listener in the client for the USER_VARIABLES_UPDATE and print something to the console, just to see that the update is arriving at the client.

I want to see if the client gets the update and if it's in the right order, which is really expected considering that the server code runs in the same method, ergo in the same thread! :)

Out of curiosity can you show the MMO Room setup? You can copy/past the relevant block from the zone file under SFS2X/zones/ or you can take a snapshot of the settings in the AdminTool.

If none of this works you could zip the client and send it our support@... email. (with a reference to this thread)

Thanks
Lapo
--
gotoAndPlay()
...addicted to flash games
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Re: Trouble accessing UserVariable in Unity

Post by specterdragon »

Had done that already :( Just simple callbacks, but neither one outputs to the log. (proximity list shouldn't fire with this new code but should have with the original code/room and never did)

Code: Select all

sfs.AddEventListener(SFSEvent.USER_VARIABLES_UPDATE, OnUserVarsUpdate);
sfs.AddEventListener(SFSEvent.PROXIMITY_LIST_UPDATE, OnProximityListUpdate);
...
void OnUserVarsUpdate(BaseEvent e){
	User user = (User)e.Params["user"];
	Debug.Log("User vars updated for: "+user);
}

void OnProximityListUpdate(BaseEvent e){
	Debug.Log("prox event fired");
}
Here's the XML for the rooms (first one's from the original code, second one is a new room I tested with the new code - main difference is limits and AOI settings):

Code: Select all

    <room>
      <name>Playground</name>
      <groupId>default</groupId>
      <password></password>
      <maxUsers>100</maxUsers>
      <maxSpectators>0</maxSpectators>
      <isDynamic>false</isDynamic>
      <isGame>true</isGame>
      <isHidden>false</isHidden>
      <autoRemoveMode>DEFAULT</autoRemoveMode>
      <permissions>
        <flags>PASSWORD_STATE_CHANGE,PUBLIC_MESSAGES</flags>
        <maxRoomVariablesAllowed>10</maxRoomVariablesAllowed>
      </permissions>
      <events>USER_ENTER_EVENT,USER_EXIT_EVENT,USER_COUNT_CHANGE_EVENT,USER_VARIABLES_UPDATE_EVENT</events>
      <badWordsFilter isActive="false"/>
      <roomVariables/>
      <extension>
        <name></name>
        <type>JAVA</type>
        <file></file>
        <propertiesFile></propertiesFile>
        <reloadMode>AUTO</reloadMode>
      </extension>
      <mmoSettings>
        <isActive>true</isActive>
        <defaultAOI>100,100,100</defaultAOI>
        <lowerMapLimit>-1000,-1000,-1000</lowerMapLimit>
        <higherMapLimit>1000,1000,1000</higherMapLimit>
        <forceFloats>true</forceFloats>
        <userMaxLimboSeconds>50</userMaxLimboSeconds>
        <proximityListUpdateMillis>500</proximityListUpdateMillis>
        <sendAOIEntryPoint>true</sendAOIEntryPoint>
      </mmoSettings>
    </room>

    <room>
      <name>TestRoom</name>
      <groupId>default</groupId>
      <password></password>
      <maxUsers>20</maxUsers>
      <maxSpectators>0</maxSpectators>
      <isDynamic>false</isDynamic>
      <isGame>true</isGame>
      <isHidden>false</isHidden>
      <autoRemoveMode>DEFAULT</autoRemoveMode>
      <permissions>
        <flags>PASSWORD_STATE_CHANGE,PUBLIC_MESSAGES</flags>
        <maxRoomVariablesAllowed>10</maxRoomVariablesAllowed>
      </permissions>
      <events>USER_ENTER_EVENT,USER_EXIT_EVENT,USER_COUNT_CHANGE_EVENT,USER_VARIABLES_UPDATE_EVENT</events>
      <badWordsFilter isActive="false"/>
      <roomVariables/>
      <extension>
        <name></name>
        <type>JAVA</type>
        <file></file>
        <propertiesFile></propertiesFile>
        <reloadMode>AUTO</reloadMode>
      </extension>
      <mmoSettings>
        <isActive>true</isActive>
        <defaultAOI>100,100,0</defaultAOI>
        <lowerMapLimit></lowerMapLimit>
        <higherMapLimit></higherMapLimit>
        <forceFloats>false</forceFloats>
        <userMaxLimboSeconds>50</userMaxLimboSeconds>
        <proximityListUpdateMillis>500</proximityListUpdateMillis>
        <sendAOIEntryPoint>true</sendAOIEntryPoint>
      </mmoSettings>
    </room>
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Re: Trouble accessing UserVariable in Unity

Post by specterdragon »

Holy crap - I think I finally found it!!

The problem was the configuration of the lobby room, not the MMO room. USER_VARIABLE_UPDATE_EVENT was set to "available" in the config and therefore not in the events list. The user is in the lobby when the variables are set. For whatever reason, the variables are not visible in the MMO room but are available in a standard game room under those conditions. Weird.

In the MMO scene's script I put a listener for PROXIMITY_LIST_UPDATE which should fire when the position is set, but I'm not seeing it. That may be a topic for a different thread once I get this code cleaned up again to see what I actually have to work with.

HUGE thanks, Lapo. You at least got me thinking in the right direction until we found a fix. Will post here again if this didn't actually fix the problem. 8)
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Trouble accessing UserVariable in Unity

Post by Lapo »

specterdragon wrote:Holy crap - I think I finally found it!!

The problem was the configuration of the lobby room, not the MMO room. USER_VARIABLE_UPDATE_EVENT was set to "available" in the config and therefore not in the events list.
Ok, that explains it :)
The user is in the lobby when the variables are set. For whatever reason, the variables are not visible in the MMO room but are available in a standard game room under those conditions. Weird.
This is not clear.
Are you talking the user itself or other players?

For the User itself the Room is not relevant, in fact the variables are obtained by calling methods on the "MySelf" object. For other clients it's a matter of visibility, Users must be in the same Room to see each other's variable.

In MMORooms they also need to be in each other's AoI.
In the MMO scene's script I put a listener for PROXIMITY_LIST_UPDATE which should fire when the position is set, but I'm not seeing it. That may be a topic for a different thread once I get this code cleaned up again to see what I actually have to work with.
I would recommend to dissect the MMORoom Demo we provide in the Unity Examples package, which is a super simple demonstration of the basic usage.
http://docs2x.smartfoxserver.com/ExamplesUnity/mmo-demo

cheers
Lapo
--
gotoAndPlay()
...addicted to flash games
specterdragon
Posts: 9
Joined: 31 Jan 2015, 17:21

Re: Trouble accessing UserVariable in Unity

Post by specterdragon »

The user is in the lobby when the variables are set. For whatever reason, the variables are not visible in the MMO room but are available in a standard game room under those conditions. Weird.
This is not clear.
Are you talking the user itself or other players?

For the User itself the Room is not relevant, in fact the variables are obtained by calling methods on the "MySelf" object.
That's the strange part. This has always been only the single user. And, I could get the variables when I joined a non-mmo room even without the USER_VARIABLE_UPDATE_EVENT event in the lobby. Odd, right?
I would recommend to dissect the MMORoom Demo we provide in the Unity Examples package, which is a super simple demonstration of the basic usage.
http://docs2x.smartfoxserver.com/ExamplesUnity/mmo-demo
Looking at that now, as a matter of fact. Had to modify the zone's XML from this post: http://forums.smartfoxserver.com/viewto ... emo#p76856 to get proximity updates to work. Dissecting it now.
User avatar
Lapo
Site Admin
Posts: 23438
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Trouble accessing UserVariable in Unity

Post by Lapo »

specterdragon wrote: That's the strange part. This has always been only the single user. And, I could get the variables when I joined a non-mmo room even without the USER_VARIABLE_UPDATE_EVENT event in the lobby. Odd, right?
You can decide not to listen to the event but behind the scenes it is transmitted anyways, otherwise you're use would not be kept in synch.
Regardless of the Room, MMO or not MMO, what you're doing is happening before you join the MMO Room, ergo you must receive the USER_VARIABLE_UPDATE_EVENT before you join the Room.

Please add the event from client side and see if it fires. If not, something very basic is missing, somewhere.

thanks
Lapo
--
gotoAndPlay()
...addicted to flash games
Post Reply