Animation speed in mecanim doubles across server

Options
jaja1
jaja1
edited September 2014 in Photon Server
Hi everyone,

I am using Photon SDK and I have created some custom code to sync the animations of different players across the network. Everything seems to work fine (in terms of position, smoothing etc) except for the animation itself. It appears as if on another client that my player has its animation being played twice in one walk cycle as opposed to one (as it should be per keystroke).

My method for syncing the animations is as follows:
1. Player presses a key and begins to walk
2. Player sends position data to the server to be stored in a database
3. The other client is constantly checking for any changes in the position of the instantiated remote player prefab by sending an oprequest to the server to "get" the position from the database
4.The server sends that data back to the client that requested it via an opresponse
5. If there is a difference(not meaning subtraction) between the last known position of the remote player and the updated position, then, based on the players current direction (as it is a 2D game), the appropriate animation is played by changing a trigger int in mecanim for the appropriate prefab.

Based on that "long" method, I would expect the animation to actually skip frames and not double them :lol:
So can anyone tell me how to fix the animation for remote players or even improve my method for updating such info in the db (if need be)?

P.S. I wont submit any code because I really don't know where I could have went wrong and there will be way too much code to post in one go. I can say however, that the request method for an updated position of the remote player was called in FIxedUpdate.

Comments

  • Tobias
    Options
    If I understand correctly, you are not sending the speed anywhere, right?
    If you determine speed based on location (or distance between current pos and target pos), then you might have a higher animation speed due to lag. It takes a bit longer to get the latest position, so on a remote machine, the character lags and might have more distance to go.

    Check your code where you calculate speed and cap it.
  • jaja1
    Options
    Thanks for the reply Tobias, and sorry for the late response on my part. The forum was giving me some issues when I tried to post. Can you clarify what you mean by "speed". Because I changed up the method of player movement a bit and a new problem came up. Now the animation speed is doubled and the movement speed is halved. Basically all I changed was the server calculates how much the player moves by in whatever direction instead of the client doing that and sending its new position to the server. The player's position is then gotten from the database upon request from the client.
    Server sided, this is called when the player sends an oprequest to the server based on its input:
    //calculates the new position of a local client's player and saves it
            public void SaveUpdateCharMapPos(string charname, byte dir)
            {
                double posx = 0.00;
                double posz = 0.00;
    
                if (dir == 0)
                {
                    posz = -0.05;
                }
                else if (dir == 1)
                {
                    posx = -0.05;
                }
                else if (dir == 2)
                {
                    posz = 0.05;
                }
                else if (dir == 3)
                {
                    posx = 0.05;
                }
                try
                {
                    using (SqlConnection myConnection = new SqlConnection(ConnectString))
                    {
                        myConnection.Open();
                        SqlCommand savePos = new SqlCommand("UPDATE characters SET position_x = position_x + @Posx, position_z = position_z + @Posz WHERE char_name=@Char_name", myConnection);
                        savePos.Parameters.AddWithValue("@Char_name", charname);
                        savePos.Parameters.AddWithValue("@Posx", posx);
                        savePos.Parameters.AddWithValue("@Posz", posz);
    
                        savePos.ExecuteNonQuery();
                    }
                }
                catch (Exception e)
                {
                    Log.Debug(e);
                    //if character position isnt saved it will remain as the last known position stored successfully
                }
            }
    

    Server sided, gets the characters position and map. This is called constantly as long as the player is requesting it in FixedUpdate:
    public double[] GetUpdateCharMapPos(string charname)
            {
                double[] pos = new double[4];
                try
                {
                    using (SqlConnection myConnection = new SqlConnection(ConnectString))
                    {
                        myConnection.Open();
                        SqlCommand getpos = new SqlCommand("SELECT current_map, position_x, position_y, position_z FROM characters WHERE char_name=@Char_name", myConnection);
                        getpos.Parameters.AddWithValue("@Char_name", charname);
    
                        using (SqlDataReader reader = getpos.ExecuteReader())
                        {
                            if (reader.Read())
                            {
                                pos[0] = Convert.ToDouble(reader["current_map"]);
                                pos[1] = Convert.ToDouble(reader["position_x"]);
                                pos[2] = Convert.ToDouble(reader["position_y"]);
                                pos[3] = Convert.ToDouble(reader["position_z"]);
                                return pos;
                            }
                            else
                            {
                                return (double[])UnityClient.AllCharMapPos[charname];//returns the last known position of the character
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Debug(e);
                    return (double[])UnityClient.AllCharMapPos[charname];//returns the last known position of the character
                }
            }
    

    Client, this method is called which sends an oprequest to get the players new position based on the method above:
    void FixedUpdate ()
    	{
    		
    _Mukizuserver.GetUpdateCharPos(OtherCharName);
    }
    

    Client, and finally the server sends this opresponse and the client updates the instantiated player who requested a position update:
    case 18:
    			//receive a characters position after requesting it
    			if(operationResponse.Parameters.ContainsKey(18))
    			{
    				PHashtable tempHash = new PHashtable();
    				tempHash = (PHashtable)operationResponse.Parameters[18];
    
    				foreach(string name in tempHash.Keys)
    				{
    					double[] tempD = new double[4];
    					tempD = (double[])tempHash[name];
    					//update player map and position cache
    					GameObject.Find(name).GetComponent<player_data>().CurrentMapPos = tempD;
    					//smooth and update player movement in game
    					Vector3 tempV = new Vector3((float)tempD[1], (float)tempD[2], (float)tempD[3]);
    					GameObject.Find(name).transform.position = Vector3.Lerp(GameObject.Find(name).transform.position, tempV, Time.deltaTime*15f);
    				}
    			}
    			break;
    

    Funny thing too, the movement of the player is only halved in the final build. In the unity editor everything runs smoothly.
  • Tobias
    Options
    By "speed" I was referring to your thread topic :)
    It seems now something else is mixed up.
    I can't really take a look at all the code (and fill in anything that might be missing), sorry.
    You might want to build some in-Editor overlay to debug the values you actually get and apply.

    I wonder why you put things like speed in a DB? Is it something that will last for a while longer? It seems like a volatile value...
  • jaja1
    Options
    Oh! Haha I see now.

    And the speed isn't stored at all in the database actually. What is stored is the exact x, y and z position of the character. What I did was this:
    1. Player presses some button to move
    2. Client sends oprequest to server and validates whether the character has permission to move or not
    3. If yes, the server adds 0.05 or -0.05 units to the x, y or z positions directly to the database.

    So the player moves by an exact amount ever key press. Time is only taken into account when lerping between the old player position on the client and the new position that was gotten in the FixedUpdate method. I just don;t understand how it could work in the editor and not the final build. There must be something that changes between two clients, I just can;t figure out what exactly. But what is this you mentioned about an overlay?
  • jaja1
    Options
    Figured out my FPS went from 60 to below 20 in the final build. I'm not sure why that happened though.