Code differences between Unity Editor and real iPhone ; a String.Split or IndexOf problem.

Dear all,

I have several major problems when exporting a working application from Unity (iPhone Advanced) to the real iPhone.

One of these major problems seems to be a Split issue.

iPhone is 4.2.

Deploying from XCode works just fine, the application launches. At some point I check a PHP with a new WWW( myLink ) code in Update. Here is this sample of code :

if (registerRoomWWW == null) {
    myGlobalString = "";
    registerRoomWWW = new WWW( myLink);
} else if (registerRoomWWW.isDone) {
    myGlobalString = registerRoomWWW.text;
    if (stringResult.IndexOf("|") >= 0) {
        registerInRoom(stringResult);
        currentStep = 31;
    } else {
        messageAlert = "Server connection error.";
        currentStep = 2;
    }
}

This seems to work fine, I have a stringResult with everything I should expect in it. However the currentStep is never switched to 2 or 31 ; it remains at the same value as before.

Either my IndexOf doesn't work, or registerInRoom doesn't room. Things work just fine in Unity Editor, though.

Here is the registerInRoom code snippet (sorry for some french named variables); all variables not preceded with "var" are already declared as global variables:

function registerInRoom( stringResult ) {
    tableauResultat = stringResult.Split("@"[0]);
    elementGauche = tableauResultat[0];

    if(elementGauche.IndexOf("PROFIL") >= 0) {
        tableauProfil = elementGauche.Split("|"[0]); 
        PlayerPrefs.SetString("profileID", tableauProfil[1]);
        profileID = tableauProfil[1];           
        PlayerPrefs.SetString("myFormerProfile", profileID);
    }

    var indiceRoom = 0;
    var nbPresents = 0;
    var nbConnectes = 0;
    roomNbMale = 0;
    roomNbMaleOnline = 0;
    roomNbFemale = 0;
    roomNbFemaleOnline = 0;

    for(i = 1; i < (tableauResultat.length - 1);i++) {
        element = tableauResultat*;*
 *if(element.IndexOf("|") >= 0) {*
 *tableauRoom = element.Split("|"[0]);*
 *if (tableauRoom.length > 1) {*
 *indiceRoom = int.Parse(tableauRoom[0]);*
 *indiceRoom = indiceRoom - 1;*
 *roomPeople[indiceRoom] = int.Parse("" + tableauRoom[1]);*
 *roomOnline[indiceRoom] = int.Parse("" + tableauRoom[2]);*
 *if(i < 5) {*
 *roomNbMale += int.Parse(""  + tableauRoom[1]);*
 *roomNbMaleOnline += int.Parse("" + tableauRoom[2]);*
 *} else {*
 *roomNbFemale += int.Parse("" + tableauRoom[1]);*
 *roomNbFemaleOnline += int.Parse("" + tableauRoom[2]);*
 *}* 
 *}* 
 *}*
 *}* 
 *if(playerMyGenderTarget == 0) {*
 *if(playerMyGender == 1) {*
 *targetGender = 2;* 
 *playerMyGenderTarget = 2;*
 *} else if (playerMyGender == 2) {*
 *targetGender = 1;*
 *playerMyGenderTarget = 1;*
 *}* 
 *}*
 _myRoomID = playerMyAgeId + ((playerMyGender * 4) - 4);_
 *if (languageID > 0) myRoomID += 10;*
 *roomOnline[myRoomID-1]= roomOnline[myRoomID-1] - 1;* 
 *currentStep = 31; // added just to make sure*
*}*
*```*
*<p>I'm afraid I cannot single out the line that doesn't work, because no error is logged.</p>*
*<p>It's just that with Unity Editor, roomPeople and roomOnline receive values (with the same stringResult string) and in real iPhone testing, they stay at 0 value.</p>*
*<p>The string is a simple string with blocks separated with "@".*
*Each individual block is made of individual elements separated with "|".*
*The string looks fine, as I said, same as the one in Unity Editor.</p>*
*<p>Maybe the real iPhone doesn't stand this character?</p>*

No need to apologize for the variable names. They could be foo and bar for all that it matters.

How can your "registerInRoom" not "room"? I'm literate in French, but I don't recognize room as a verb in French or English. Did you mean registerInRoom is not being called or something?

From your code, we can glean that you assume your stringResult to look like:

[["POFIL"|profileID|...]@[indiceRoom|roomPeople[indiceRoom-1]|roomOnline[indiceRoom-1]|...@]]somethingElse

If it doesn't look like this, then you won't get what you expect.

If registerRoomWWW.isDone is never true, then currentStep will not be set, registerInRoom will not be called, nor will messageAlert be set to "ServerConnectionError". You may want to add in some logging to see if registerRoomWWW.isDone is ever true. I suspect that this is most likely your issue.

If the stringResult contains a '|', it will not change currentStep to 2 or set messageAlert and if your stringResult is not treated exactly as you expect, you will not get the results you expect and currentStep will stay at 31 if registerRoomWWW.isDone. This would indicate that you may be correct that the iOS does not like your check for '@', but since it is a standard ASCII character and it is supported in other contexts within the iOS, I find this unlikely. Perhaps you should try logging the string that registerInRoom gets to confirm that it is what you believe it to be as it is possible that somewhere along the way your string may have been mangled.

If you distrust String.Split, you might write a small test function and deploy to your iOS device to confirm, but I trust that you will likely find it works exactly as it should.

In the worst case, you say that no error is logged. Have you tried adding additional logging to your function in general just to print where you are and what values you have at a given point in execution?

Some considerations:

  • Do you really need to check if tableauRoom.length is greater than 1? Since you already know element contains '|', tableauRoom.length will only ever be less than 2 when it starts or ends with '|'.
  • tableauResultat is a String[] and therefore element is a String and therefore tableauRoom is a String[], so why are you adding a "" to the values of tableauRoom when you parse them to int since tableauRoom is already a string? You didn't do that a few lines before when you parsed tableauRoom[0].
  • You use String.IndexOf to check if the string contains something. Why not just use String.Contains? It's far more readable and shortens your code.
  • If you are passing in indiceRoom, only to subtract from it, have you considered passing in the value already subtracted?
  • This one isn't serious, but you parse the same integers more than once. The question is: Which is more costly, parsing two strings twice or indexing the 2 arrays where you stored the already parsed values? Depending how you write this, you could even have the arrays paged for indexing and everything, so is this the best approach?
  • You do a lot of string parsing, etc. Maybe not for this exact case, but have you considered using regular expressions?

Solution found!

It seems to have traced some sort of "Unity deployment to Xcode" bug.

The logs mentioned that the string was OK, and when entering registerInRoom(), the system does not even enter (no log there can be displayed). However the Xcode console log was mentioning some sort of oddity with symbols. I eventually saw the name "ligneResultat" in the mess. I unfortunately no longer have this log in the console and so cannot paste it.

The variable "ligneResultat" is the parameter of the registerInRoom() function (the one I renamed stringResult when pasting the code in Unity Answers). This name was also used somewhere else in the code ; not as a global variable, and not in this active part though.

I removed the parameter and used a global string instead ; one with a fixed and defined String type right from the start.

This fixed all the mess.

So, the problem was: --> Xcode wasn't recognizing the type of stringResult and somewhere couldn't even treat it as a String. Xcode failed to launch the registerInRoom function and wasn't logging anything from there.

The solution was : --> Remove the parameter from the function, use a global string instead to receive the WWW text and be managed inside the function.

Yes, I know, odd solution indeed. Looks like shamanism :)

I don't know if String.Contains() was part of the solution, but I'll credit you skovacs with the answer, as your reply was very helpful in clearing out the mess and avoiding side issues.