Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

What is the best way to send an animation over a network?

Discussion in 'Multiplayer' started by tinman, Apr 26, 2012.

  1. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    I mean a complex animation (not just a cube rotating) I mean like a character walking or running where multiple parts are moving.

    Thanks!
     
  2. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    You don't send animation over the network, you create a state machine for your character that is built so that you can deduce the animation on the other remote computer(s). And then you send the state of the character instead, for example current movement velocity or whatever you may use in your game.
     
  3. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    Thanks! Would this mean, for example: I would have a reference of for example '1' for a walk animation, so when the character is walking, he just sends out to the network '1', and the other players would then receive '1' and play the walking animation? Would this work also for crossfading?
     
  4. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    If you're already syncing player position/rotation over the network, that is the state that fholm is referring to. The remote computers can calculate the velocity of the prefab based on movement over time, and combined with rotation, a script can locally determine what animation should be playing based on those things. Nothing needs to be sent over the network.
     
  5. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    I see what you mean, thanks. I think though that not ALL animations can be deducted by position/rotation. What about a dancing animation for example?
     
  6. roka

    roka

    Joined:
    Sep 12, 2010
    Posts:
    589
    position is one thing , rotation an another one and animation stat is again an another thing

    you need to enum all your animations , for exemple walk = 1 , run = 2 , jump = 3 ........

    for exemple you have 2 clients playing:

    player 1 walk and send his informations to the player 2 , so your packet need to contain the player position , the player rotation and the animations stat.

    player 2 receive your packet with position , rotation and animations stat , so he make the correct position , correct rotation and play the correct animation with your animation stat

    here is my enum for my player

    enum MyAnimState {



    Idle_Grenade_Melle = 1,

    Idle_Fire_Grenade_Melle = 2,

    Idle_Jump_Grenade_Melle = 3,

    Idle_Jump_Fire_Grenade_Melle = 4,

    Idle_Crouch_Grenade_Melle = 5,

    Idle_Crouch_Fire_Grenade_Melle = 6,



    Idle_Pistol = 7,

    Idle_Fire_Pistol = 8,

    Idle_Jump_Pistol = 9,

    Idle_Jump_Fire_Pistol = 10,

    Idle_Reload_Pistol = 1010,

    Idle_Reload_Jump_Pistol = 12,

    Idle_Crouch_Pistol = 13,

    Idle_Crouch_Fire_Pistol = 14,

    Idle_Crouch_Reload_Pistol = 15,



    Idle_Pistol_Aim = 16,

    Idle_Fire_Pistol_Aim = 17,



    Idle_Rifle = 18,

    Idle_Fire_Rifle = 19,

    Idle_Jump_Rifle = 20,

    Idle_Jump_Fire_Rifle = 21,

    Idle_Reload_Rifle = 22,

    Idle_Reload_Jump_Rifle = 23,

    Idle_Crouch_Rifle = 24,

    Idle_Crouch_Fire_Rifle = 25,

    Idle_Crouch_Reload_Rifle = 2525,



    Idle_Rifle_Aim = 26,

    Idle_Fire_Rifle_Aim = 27,

    Idle_Jump_Rifle_Aim = 28,

    Idle_Jump_Fire_Rifle_Aim = 29,

    Idle_Crouch_Rifle_Aim = 30,

    Idle_Crouch_Fire_Rifle_Aim = 31,



    Idle_Snipe = 32,

    Idle_Fire_Snipe = 33,

    Idle_Jump_Snipe = 34,

    Idle_Jump_Fire_Snipe = 35,

    Idle_Reload_Snipe = 36,

    Idle_Reload_Jump_Snipe = 37,

    Idle_Crouch_Snipe = 38,

    Idle_Crouch_Fire_Snipe = 39,

    Idle_Crouch_Reload_Snipe = 3939,



    Idle_Snipe_Aim = 40,

    Idle_Fire_Snipe_Aim = 41,

    Idle_Jump_Snipe_Aim = 42,

    Idle_Jump_Fire_Snipe_Aim = 43,

    Idle_Crouch_Snipe_Aim = 44,

    Idle_Crouch_Fire_Snipe_Aim = 45,



    Walking_Grenade_Melle = 46,

    Walking_Fire_Grenade_Melle = 47,

    Walking_Jump_Grenade_Melle = 48,

    Walking_Jump_Fire_Grenade_Melle = 49,

    Walking_Crouch_Grenade_Melle = 50,

    Walking_Crouch_Fire_Grenade_Melle = 51,



    Walking_Pistol = 52,

    Walking_Fire_Pistol = 53,

    Walking_Jump_Pistol = 54,

    Walking_Jump_Fire_Pistol = 55,

    Walking_Reload_Pistol = 56,

    Walking_Reload_Jump_Pistol = 57,

    Walking_Crouch_Pistol = 58,

    Walking_Crouch_Fire_Pistol = 59,

    Walking_Crouch_Reload_Pistol = 5959,



    Walking_Pistol_Aim = 60,

    Walking_Fire_Pistol_Aim =61,



    Walking_Rifle = 62,

    Walking_Fire_Rifle = 63,

    Walking_Jump_Rifle = 64,

    Walking_Jump_Fire_Rifle = 65,

    Walking_Reload_Rifle = 66,

    Walking_Reload_Jump_Rifle = 67,

    Walking_Crouch_Rifle = 68,

    Walking_Crouch_Fire_Rifle = 69,

    Walking_Crouch_Reload_Rifle = 6969,



    Walking_Rifle_Aim = 70,

    Walking_Fire_Rifle_Aim = 71,

    Walking_Jump_Rifle_Aim = 72,

    Walking_Jump_Fire_Rifle_Aim = 73,

    Walking_Crouch_Rifle_Aim = 74,

    Walking_Crouch_Fire_Rifle_Aim = 75,



    Walking_Snipe = 76,

    Walking_Fire_Snipe = 77,

    Walking_Jump_Snipe = 78,

    Walking_Jump_Fire_Snipe = 79,

    Walking_Reload_Snipe = 80,

    Walking_Reload_Jump_Snipe = 81,

    Walking_Crouch_Snipe = 82,

    Walking_Crouch_Fire_Snipe = 83,

    Walking_Crouch_Reload_Snipe = 8383,



    Walking_Snipe_Aim = 84,

    Walking_Fire_Snipe_Aim = 85,

    Walking_Jump_Snipe_Aim = 86,

    Walking_Jump_Fire_Snipe_Aim = 87,

    Walking_Crouch_Snipe_Aim = 88,

    Walking_Crouch_Fire_Snipe_Aim = 89,



    Run_Grenade_Melle = 90,

    Run_Fire_Grenade_Melle = 91,

    Run_Jump_Grenade_Melle = 92,

    Run_Jump_Fire_Grenade_Melle = 93,



    Run_Pistol = 94,

    Run_Jump_Pistol = 95,

    Run_Reload_Pistol = 96,

    Run_Reload_Jump_Pistol = 97,



    Run_Pistol_Aim = 98,



    Run_Rifle = 99,

    Run_Jump_Rifle = 100,

    Run_Reload_Rifle = 101,

    Run_Reload_Jump_Rifle = 102,



    Run_Rifle_Aim = 103,



    Run_Snipe = 104,

    Run_Jump_Snipe = 105,

    Run_Reload_Snipe = 106,

    Run_Reload_Jump_Snipe = 107,



    Run_Snipe_Aim = 108,



    SrafLeft_Grenade_Melle= 109,

    SrafLeft_Fire_Grenade_Melle= 110,

    SrafLeft_Jump_Grenade_Melle= 111,

    SrafLeft_Jump_Fire_Grenade_Melle= 112,

    SrafLeft_Crouch_Grenade_Melle= 113,

    SrafLeft_Crouch_Fire_Grenade_Melle= 114,



    SrafLeft_Pistol= 115,

    SrafLeft_Fire_Pistol= 116,

    SrafLeft_Jump_Pistol= 117,

    SrafLeft_Jump_Fire_Pistol= 118,

    SrafLeft_Reload_Pistol= 119,

    SrafLeft_Reload_Jump_Pistol= 120,

    SrafLeft_Crouch_Pistol= 121,

    SrafLeft_Crouch_Fire_Pistol= 122,

    SrafLeft_Crouch_Reload_Pistol= 122122,





    SrafLeft_Pistol_Aim= 123,

    SrafLeft_Fire_Pistol_Aim= 124,

    SrafLeft_Jump_Pistol_Aim= 125,

    SrafLeft_Jump_Fire_Pistol_Aim= 126,



    SrafLeft_Rifle= 127,

    SrafLeft_Fire_Rifle= 128,

    SrafLeft_Jump_Rifle= 129,

    SrafLeft_Jump_Fire_Rifle= 130,

    SrafLeft_Reload_Rifle= 131,

    SrafLeft_Reload_Jump_Rifle= 132,

    SrafLeft_Crouch_Rifle= 133,

    SrafLeft_Crouch_Fire_Rifle= 134,

    SrafLeft_Crouch_Reload_Rifle= 134134,



    SrafLeft_Rifle_Aim= 135,

    SrafLeft_Fire_Rifle_Aim= 136,

    SrafLeft_Jump_Rifle_Aim= 137,

    SrafLeft_Jump_Fire_Rifle_Aim= 138,

    SrafLeft_Crouch_Rifle_Aim= 139,

    SrafLeft_Crouch_Fire_Rifle_Aim= 140,



    SrafLeft_Snipe= 141,

    SrafLeft_Fire_Snipe= 142,

    SrafLeft_Jump_Snipe= 143,

    SrafLeft_Jump_Fire_Snipe= 144,

    SrafLeft_Reload_Snipe= 145,

    SrafLeft_Reload_Jump_Snipe= 146,

    SrafLeft_Crouch_Snipe= 147,

    SrafLeft_Crouch_Fire_Snipe= 148,

    SrafLeft_Crouch_Reload_Snipe= 148148,



    SrafLeft_Snipe_Aim= 149,

    SrafLeft_Fire_Snipe_Aim= 150,

    SrafLeft_Jump_Snipe_Aim= 151,

    SrafLeft_Jump_Fire_Snipe_Aim= 152,

    SrafLeft_Crouch_Snipe_Aim= 153,

    SrafLeft_Crouch_Fire_Snipe_Aim= 154,



    SrafRight_Grenade_Melle= 155,

    SrafRight_Fire_Grenade_Melle= 156,

    SrafRight_Jump_Grenade_Melle= 157,

    SrafRight_Jump_Fire_Grenade_Melle= 158,

    SrafRight_Crouch_Grenade_Melle= 159,

    SrafRight_Crouch_Fire_Grenade_Melle= 160,



    SrafRight_Pistol= 161,

    SrafRight_Fire_Pistol= 162,

    SrafRight_Jump_Pistol= 163,

    SrafRight_Jump_Fire_Pistol= 164,

    SrafRight_Reload_Pistol= 165,

    SrafRight_Reload_Jump_Pistol= 166, //

    SrafRight_Crouch_Pistol= 167,

    SrafRight_Crouch_Fire_Pistol= 168,

    SrafRight_Crouch_Reload_Pistol= 168168,



    SrafRight_Pistol_Aim= 169,

    SrafRight_Fire_Pistol_Aim= 170,

    SrafRight_Jump_Pistol_Aim= 171,

    SrafRight_Jump_Fire_Pistol_Aim= 172,



    SrafRight_Rifle= 173,

    SrafRight_Fire_Rifle= 174,

    SrafRight_Jump_Rifle= 175,

    SrafRight_Jump_Fire_Rifle= 176,

    SrafRight_Reload_Rifle= 177,

    SrafRight_Reload_Jump_Rifle= 178,

    SrafRight_Crouch_Rifle= 179,

    SrafRight_Crouch_Fire_Rifle= 180,

    SrafRight_Crouch_Reload_Rifle= 180180,



    SrafRight_Rifle_Aim= 181,

    SrafRight_Fire_Rifle_Aim= 182,

    SrafRight_Jump_Rifle_Aim= 183,

    SrafRight_Jump_Fire_Rifle_Aim= 184,

    SrafRight_Crouch_Rifle_Aim= 185,

    SrafRight_Crouch_Fire_Rifle_Aim= 186,



    SrafRight_Snipe= 187,

    SrafRight_Fire_Snipe= 188,

    SrafRight_Jump_Snipe= 189,

    SrafRight_Jump_Fire_Snipe= 190,

    SrafRight_Reload_Snipe= 191,

    SrafRight_Reload_Jump_Snipe= 192,

    SrafRight_Crouch_Snipe= 193,

    SrafRight_Crouch_Fire_Snipe= 194,

    SrafRight_Crouch_Reload_Snipe= 194194,



    SrafRight_Snipe_Aim= 195,

    SrafRight_Fire_Snipe_Aim= 196,

    SrafRight_Jump_Snipe_Aim= 197,

    SrafRight_Jump_Fire_Snipe_Aim= 198,

    SrafRight_Crouch_Snipe_Aim= 199,

    SrafRight_Crouch_Fire_Snipe_Aim= 200,



    backward_Grenade_Melle= 201,

    backward_Fire_Grenade_Melle= 202,

    backward_Jump_Grenade_Melle= 203,

    backward_Jump_Fire_Grenade_Melle= 204,

    backward_Crouch_Grenade_Melle= 205,

    backward_Crouch_Fire_Grenade_Melle= 206,



    backward_Pistol= 207,

    backward_Fire_Pistol= 208,

    backward_Jump_Pistol= 209,

    backward_Jump_Fire_Pistol= 210,

    backward_Reload_Pistol= 211,

    backward_Reload_Jump_Pistol= 212,

    backward_Crouch_Pistol= 213,

    backward_Crouch_Fire_Pistol= 214,

    backward_Crouch_Reload_Pistol= 214214,



    backward_Pistol_Aim= 215,

    backward_Fire_Pistol_Aim= 216,

    backward_Jump_Pistol_Aim= 217,

    backward_Jump_Fire_Pistol_Aim= 218,



    backward_Rifle= 219,

    backward_Fire_Rifle= 220,

    backward_Jump_Rifle= 221,

    backward_Jump_Fire_Rifle= 222,

    backward_Reload_Rifle= 223,

    backward_Reload_Jump_Rifle= 224,

    backward_Crouch_Rifle= 225,

    backward_Crouch_Fire_Rifle= 226,

    backward_Crouch_Reload_Rifle= 226226,



    backward_Rifle_Aim= 227,

    backward_Fire_Rifle_Aim= 228,

    backward_Jump_Rifle_Aim= 229,

    backward_Jump_Fire_Rifle_Aim= 230,

    backward_Crouch_Rifle_Aim= 231,

    backward_Crouch_Fire_Rifle_Aim= 232,



    backward_Snipe= 233,

    backward_Fire_Snipe= 234,

    backward_Jump_Snipe= 235,

    backward_Jump_Fire_Snipe= 236,

    backward_Reload_Snipe= 237,

    backward_Reload_Jump_Snipe= 238,

    backward_Crouch_Snipe= 239,

    backward_Crouch_Fire_Snipe= 240,

    backward_Crouch_Reload_Snipe= 240240,



    backward_Snipe_Aim= 241,

    backward_Fire_Snipe_Aim= 242,

    backward_Jump_Snipe_Aim= 243,

    backward_Jump_Fire_Snipe_Aim= 244,

    backward_Crouch_Snipe_Aim= 245,

    backward_Crouch_Fire_Snipe_Aim= 246,



    }

    i use it like this in my player controller and send "PlayerInfoStat._myplayerinfoState" :

    if(Input.GetKey(KeyboardControl.Crouch)){

    if(Input.GetButton("Fire1")){

    PlayerInfoStat._myplayerinfoState = MyAnimState.SrafLeft_Crouch_Fire_Grenade_Melle;

    }else{

    PlayerInfoStat._myplayerinfoState = MyAnimState.SrafLeft_Crouch_Grenade_Melle;

    }

    }

    and for the player who receive the stat:

    enum CharacterState {

    Idle_Grenade_Melle = 1,
    Idle_Fire_Grenade_Melle = 2,
    Idle_Jump_Grenade_Melle = 3,
    Idle_Jump_Fire_Grenade_Melle = 4,
    Idle_Crouch_Grenade_Melle = 5,
    Idle_Crouch_Fire_Grenade_Melle = 6,

    Idle_Pistol = 7,
    Idle_Fire_Pistol = 8,
    Idle_Jump_Pistol = 9,
    Idle_Jump_Fire_Pistol = 10,
    Idle_Reload_Pistol = 1010,
    Idle_Reload_Jump_Pistol = 12,
    Idle_Crouch_Pistol = 13,
    Idle_Crouch_Fire_Pistol = 14,
    Idle_Crouch_Reload_Pistol = 15,

    Idle_Pistol_Aim = 16,
    Idle_Fire_Pistol_Aim = 17,

    Idle_Rifle = 18,
    Idle_Fire_Rifle = 19,
    Idle_Jump_Rifle = 20,
    Idle_Jump_Fire_Rifle = 21,
    Idle_Reload_Rifle = 22,
    Idle_Reload_Jump_Rifle = 23,
    Idle_Crouch_Rifle = 24,
    Idle_Crouch_Fire_Rifle = 25,
    Idle_Crouch_Reload_Rifle = 2525,

    Idle_Rifle_Aim = 26,
    Idle_Fire_Rifle_Aim = 27,
    Idle_Jump_Rifle_Aim = 28,
    Idle_Jump_Fire_Rifle_Aim = 29,
    Idle_Crouch_Rifle_Aim = 30,
    Idle_Crouch_Fire_Rifle_Aim = 31,

    Idle_Snipe = 32,
    Idle_Fire_Snipe = 33,
    Idle_Jump_Snipe = 34,
    Idle_Jump_Fire_Snipe = 35,
    Idle_Reload_Snipe = 36,
    Idle_Reload_Jump_Snipe = 37,
    Idle_Crouch_Snipe = 38,
    Idle_Crouch_Fire_Snipe = 39,
    Idle_Crouch_Reload_Snipe = 3939,

    Idle_Snipe_Aim = 40,
    Idle_Fire_Snipe_Aim = 41,
    Idle_Jump_Snipe_Aim = 42,
    Idle_Jump_Fire_Snipe_Aim = 43,
    Idle_Crouch_Snipe_Aim = 44,
    Idle_Crouch_Fire_Snipe_Aim = 45,

    Walking_Grenade_Melle = 46,
    Walking_Fire_Grenade_Melle = 47,
    Walking_Jump_Grenade_Melle = 48,
    Walking_Jump_Fire_Grenade_Melle = 49,
    Walking_Crouch_Grenade_Melle = 50,
    Walking_Crouch_Fire_Grenade_Melle = 51,

    Walking_Pistol = 52,
    Walking_Fire_Pistol = 53,
    Walking_Jump_Pistol = 54,
    Walking_Jump_Fire_Pistol = 55,
    Walking_Reload_Pistol = 56,
    Walking_Reload_Jump_Pistol = 57,
    Walking_Crouch_Pistol = 58,
    Walking_Crouch_Fire_Pistol = 59,
    Walking_Crouch_Reload_Pistol = 5959,

    Walking_Pistol_Aim = 60,
    Walking_Fire_Pistol_Aim =61,

    Walking_Rifle = 62,
    Walking_Fire_Rifle = 63,
    Walking_Jump_Rifle = 64,
    Walking_Jump_Fire_Rifle = 65,
    Walking_Reload_Rifle = 66,
    Walking_Reload_Jump_Rifle = 67,
    Walking_Crouch_Rifle = 68,
    Walking_Crouch_Fire_Rifle = 69,
    Walking_Crouch_Reload_Rifle = 6969,

    Walking_Rifle_Aim = 70,
    Walking_Fire_Rifle_Aim = 71,
    Walking_Jump_Rifle_Aim = 72,
    Walking_Jump_Fire_Rifle_Aim = 73,
    Walking_Crouch_Rifle_Aim = 74,
    Walking_Crouch_Fire_Rifle_Aim = 75,

    Walking_Snipe = 76,
    Walking_Fire_Snipe = 77,
    Walking_Jump_Snipe = 78,
    Walking_Jump_Fire_Snipe = 79,
    Walking_Reload_Snipe = 80,
    Walking_Reload_Jump_Snipe = 81,
    Walking_Crouch_Snipe = 82,
    Walking_Crouch_Fire_Snipe = 83,
    Walking_Crouch_Reload_Snipe = 8383,

    Walking_Snipe_Aim = 84,
    Walking_Fire_Snipe_Aim = 85,
    Walking_Jump_Snipe_Aim = 86,
    Walking_Jump_Fire_Snipe_Aim = 87,
    Walking_Crouch_Snipe_Aim = 88,
    Walking_Crouch_Fire_Snipe_Aim = 89,

    Run_Grenade_Melle = 90,
    Run_Fire_Grenade_Melle = 91,
    Run_Jump_Grenade_Melle = 92,
    Run_Jump_Fire_Grenade_Melle = 93,

    Run_Pistol = 94,
    Run_Jump_Pistol = 95,
    Run_Reload_Pistol = 96,
    Run_Reload_Jump_Pistol = 97,

    Run_Pistol_Aim = 98,

    Run_Rifle = 99,
    Run_Jump_Rifle = 100,
    Run_Reload_Rifle = 101,
    Run_Reload_Jump_Rifle = 102,

    Run_Rifle_Aim = 103,

    Run_Snipe = 104,
    Run_Jump_Snipe = 105,
    Run_Reload_Snipe = 106,
    Run_Reload_Jump_Snipe = 107,

    Run_Snipe_Aim = 108,

    SrafLeft_Grenade_Melle= 109,
    SrafLeft_Fire_Grenade_Melle= 110,
    SrafLeft_Jump_Grenade_Melle= 111,
    SrafLeft_Jump_Fire_Grenade_Melle= 112,
    SrafLeft_Crouch_Grenade_Melle= 113,
    SrafLeft_Crouch_Fire_Grenade_Melle= 114,

    SrafLeft_Pistol= 115,
    SrafLeft_Fire_Pistol= 116,
    SrafLeft_Jump_Pistol= 117,
    SrafLeft_Jump_Fire_Pistol= 118,
    SrafLeft_Reload_Pistol= 119,
    SrafLeft_Reload_Jump_Pistol= 120,
    SrafLeft_Crouch_Pistol= 121,
    SrafLeft_Crouch_Fire_Pistol= 122,
    SrafLeft_Crouch_Reload_Pistol= 122122,


    SrafLeft_Pistol_Aim= 123,
    SrafLeft_Fire_Pistol_Aim= 124,
    SrafLeft_Jump_Pistol_Aim= 125,
    SrafLeft_Jump_Fire_Pistol_Aim= 126,

    SrafLeft_Rifle= 127,
    SrafLeft_Fire_Rifle= 128,
    SrafLeft_Jump_Rifle= 129,
    SrafLeft_Jump_Fire_Rifle= 130,
    SrafLeft_Reload_Rifle= 131,
    SrafLeft_Reload_Jump_Rifle= 132,
    SrafLeft_Crouch_Rifle= 133,
    SrafLeft_Crouch_Fire_Rifle= 134,
    SrafLeft_Crouch_Reload_Rifle= 134134,

    SrafLeft_Rifle_Aim= 135,
    SrafLeft_Fire_Rifle_Aim= 136,
    SrafLeft_Jump_Rifle_Aim= 137,
    SrafLeft_Jump_Fire_Rifle_Aim= 138,
    SrafLeft_Crouch_Rifle_Aim= 139,
    SrafLeft_Crouch_Fire_Rifle_Aim= 140,

    SrafLeft_Snipe= 141,
    SrafLeft_Fire_Snipe= 142,
    SrafLeft_Jump_Snipe= 143,
    SrafLeft_Jump_Fire_Snipe= 144,
    SrafLeft_Reload_Snipe= 145,
    SrafLeft_Reload_Jump_Snipe= 146,
    SrafLeft_Crouch_Snipe= 147,
    SrafLeft_Crouch_Fire_Snipe= 148,
    SrafLeft_Crouch_Reload_Snipe= 148148,

    SrafLeft_Snipe_Aim= 149,
    SrafLeft_Fire_Snipe_Aim= 150,
    SrafLeft_Jump_Snipe_Aim= 151,
    SrafLeft_Jump_Fire_Snipe_Aim= 152,
    SrafLeft_Crouch_Snipe_Aim= 153,
    SrafLeft_Crouch_Fire_Snipe_Aim= 154,

    SrafRight_Grenade_Melle= 155,
    SrafRight_Fire_Grenade_Melle= 156,
    SrafRight_Jump_Grenade_Melle= 157,
    SrafRight_Jump_Fire_Grenade_Melle= 158,
    SrafRight_Crouch_Grenade_Melle= 159,
    SrafRight_Crouch_Fire_Grenade_Melle= 160,

    SrafRight_Pistol= 161,
    SrafRight_Fire_Pistol= 162,
    SrafRight_Jump_Pistol= 163,
    SrafRight_Jump_Fire_Pistol= 164,
    SrafRight_Reload_Pistol= 165,
    SrafRight_Reload_Jump_Pistol= 166, //
    SrafRight_Crouch_Pistol= 167,
    SrafRight_Crouch_Fire_Pistol= 168,
    SrafRight_Crouch_Reload_Pistol= 168168,

    SrafRight_Pistol_Aim= 169,
    SrafRight_Fire_Pistol_Aim= 170,
    SrafRight_Jump_Pistol_Aim= 171,
    SrafRight_Jump_Fire_Pistol_Aim= 172,

    SrafRight_Rifle= 173,
    SrafRight_Fire_Rifle= 174,
    SrafRight_Jump_Rifle= 175,
    SrafRight_Jump_Fire_Rifle= 176,
    SrafRight_Reload_Rifle= 177,
    SrafRight_Reload_Jump_Rifle= 178,
    SrafRight_Crouch_Rifle= 179,
    SrafRight_Crouch_Fire_Rifle= 180,
    SrafRight_Crouch_Reload_Rifle= 180180,

    SrafRight_Rifle_Aim= 181,
    SrafRight_Fire_Rifle_Aim= 182,
    SrafRight_Jump_Rifle_Aim= 183,
    SrafRight_Jump_Fire_Rifle_Aim= 184,
    SrafRight_Crouch_Rifle_Aim= 185,
    SrafRight_Crouch_Fire_Rifle_Aim= 186,

    SrafRight_Snipe= 187,
    SrafRight_Fire_Snipe= 188,
    SrafRight_Jump_Snipe= 189,
    SrafRight_Jump_Fire_Snipe= 190,
    SrafRight_Reload_Snipe= 191,
    SrafRight_Reload_Jump_Snipe= 192,
    SrafRight_Crouch_Snipe= 193,
    SrafRight_Crouch_Fire_Snipe= 194,
    SrafRight_Crouch_Reload_Snipe= 194194,

    SrafRight_Snipe_Aim= 195,
    SrafRight_Fire_Snipe_Aim= 196,
    SrafRight_Jump_Snipe_Aim= 197,
    SrafRight_Jump_Fire_Snipe_Aim= 198,
    SrafRight_Crouch_Snipe_Aim= 199,
    SrafRight_Crouch_Fire_Snipe_Aim= 200,

    backward_Grenade_Melle= 201,
    backward_Fire_Grenade_Melle= 202,
    backward_Jump_Grenade_Melle= 203,
    backward_Jump_Fire_Grenade_Melle= 204,
    backward_Crouch_Grenade_Melle= 205,
    backward_Crouch_Fire_Grenade_Melle= 206,

    backward_Pistol= 207,
    backward_Fire_Pistol= 208,
    backward_Jump_Pistol= 209,
    backward_Jump_Fire_Pistol= 210,
    backward_Reload_Pistol= 211,
    backward_Reload_Jump_Pistol= 212,
    backward_Crouch_Pistol= 213,
    backward_Crouch_Fire_Pistol= 214,
    backward_Crouch_Reload_Pistol= 214214,

    backward_Pistol_Aim= 215,
    backward_Fire_Pistol_Aim= 216,
    backward_Jump_Pistol_Aim= 217,
    backward_Jump_Fire_Pistol_Aim= 218,

    backward_Rifle= 219,
    backward_Fire_Rifle= 220,
    backward_Jump_Rifle= 221,
    backward_Jump_Fire_Rifle= 222,
    backward_Reload_Rifle= 223,
    backward_Reload_Jump_Rifle= 224,
    backward_Crouch_Rifle= 225,
    backward_Crouch_Fire_Rifle= 226,
    backward_Crouch_Reload_Rifle= 226226,

    backward_Rifle_Aim= 227,
    backward_Fire_Rifle_Aim= 228,
    backward_Jump_Rifle_Aim= 229,
    backward_Jump_Fire_Rifle_Aim= 230,
    backward_Crouch_Rifle_Aim= 231,
    backward_Crouch_Fire_Rifle_Aim= 232,

    backward_Snipe= 233,
    backward_Fire_Snipe= 234,
    backward_Jump_Snipe= 235,
    backward_Jump_Fire_Snipe= 236,
    backward_Reload_Snipe= 237,
    backward_Reload_Jump_Snipe= 238,
    backward_Crouch_Snipe= 239,
    backward_Crouch_Fire_Snipe= 240,
    backward_Crouch_Reload_Snipe= 240240,

    backward_Snipe_Aim= 241,
    backward_Fire_Snipe_Aim= 242,
    backward_Jump_Snipe_Aim= 243,
    backward_Jump_Fire_Snipe_Aim= 244,
    backward_Crouch_Snipe_Aim= 245,
    backward_Crouch_Fire_Snipe_Aim= 246,

    }


    public var _mycharacterState : CharacterState;



    and check the animation stat like that


    switch (_mycharacterState){

    case _mycharacterState.Idle_Grenade_Melle:

    if(!animation.IsPlaying("idle_grenade_melle")){

    animation["idle_grenade_melle"].wrapMode = WrapMode.Loop;
    animation["idle_grenade_melle"].speed = 0.8;
    animation.CrossFade("idle_grenade_melle");

    }

    break;

    case CharacterState.Walking_Grenade_Melle:

    if(!animation.IsPlaying("move_slow_grenade_melle")){

    animation["move_slow_grenade_melle"].wrapMode = WrapMode.Loop;

    animation.CrossFade("move_slow_grenade_melle");

    }

    break;

    case CharacterState.Run_Grenade_Melle:

    if(!animation.IsPlaying("run_grenade_melle")){

    animation["run_grenade_melle"].wrapMode = WrapMode.Loop;
    animation["run_grenade_melle"].speed = RunAnimSpeed;
    animation.CrossFade("run_grenade_melle");

    }

    break;
     
    Last edited: Apr 26, 2012
    RandomAgent and Chrispins like this.
  7. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    I see what you mean! Thanks a lot roka! and the rest of you guys too! thanks!
     
  8. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    I just wanted to add that I do not agree with what Roka posted, this is not how I would implement it and to me it's a sign of a badly designed networking protocol if you need to explicitly send the animation to play for every actor to every player. The animation(s) to play (no matter how complex they are) should be possible to deduce from the state of the actor based on it's current state + past states + future states.

    But, that said. While what Roka posted is the "naive" solution, it's also one that a lot of people find easier to grasp and implement when they first get in contact with networking (I even use the technique in the demos for my server software, SlimNet, as it's easier to demonstrate and less convoluted to implement). It's what I would call the "Brute force" way of doing it.
     
    trombonaut likes this.
  9. tinman

    tinman

    Joined:
    Jan 8, 2011
    Posts:
    229
    I see thanks fholm. What about a 'hybrid' solution? Wouldn't it be difficult to deduct any kind of animation based on position/rotation?
    how would 3rd party networking solutions do this? I am wondering because some claim they can implement it in a few min so am wondering how that work.
    Thanks
     
    Chrispins likes this.
  10. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Yeah, I'm with fholm. An example of a hybrid solution would be a multiplayer action game where players can attack with swords... all movement animation (idle, walking, running, strafing, turning in place, and jumping) could be deduced from position/rotation sync and calculated velocity. The sword attack action/state-change would be an RPC message, the animation code would deduce the appropriate animation locally. You don't want to have to send two messages every time you do something (a state-change/perform-action message, an animation-state-change message)... you'd be wasting bandwidth.
     
  11. tigeba

    tigeba

    Joined:
    Sep 11, 2008
    Posts:
    70
    In EUP, we effectively use a hybrid approach. Animation sync for movement can usually be inferred based on current + previous movement states. We also natively support the concept of player 'animations' that can be thought of as arbitrary animations that clients couldn't really infer based on movement information alone. For example, think of things like social animations: agree, applaud, etc. These are just implemented as discrete events and it is the clients job to figure out how to incorporate them into whatever else might be happening.
     
  12. Befall

    Befall

    Joined:
    Nov 20, 2009
    Posts:
    30
    Gahhh, thank you so much for the inspiration to get something like this working. I've seen so many posts talking about syncing stuff over the network by sending RPC's, and I like this far more.

    One question: Our early model animations are based on movement speed, which is deduced locally by the CharacterController component. However, when you have that across the network, it doesn't work, so I had to deduce it by checking differences in position each update cycle, etc etc. Is there a way that a CharacterController could be synced, or is it better not to since it contains tons of variables that send a S***ton over the network? Does make more sense to just deduce whatever I need to locally?

    Probably a stupid question but I'd like to make sure this is smartly designed and efficient code.
     
  13. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    As always the generic response for this is that it depends on your game, but I can explain the current solution that a game I'm working on uses:

    1) For movement-based animations, I need to send the current input state (about 12 bits) to each player anyway to do proper predictions of turns, etc. anyway so that is forwarded to all clients for all player actors (this works well up to about 32 players, after that you need to find another solution)

    2) For things like reload-animations or other "actions", separate events are sent - as these actions usually carry with them some other state change like ammo refilling to full in the current clip, etc.

    In general, syncing stuff over the networking using RPCs (especially when using the built in networking) is a "bad" idea, as much as possible should be sent in an *unreliabe* and *delta compressed* state stream. On top of this you can send events as RPCs if you want, but it's possible to pack them into the state-stream also.

    RPCs in general should be used for one-off, "big" and rare events like: Login to game, Load map, BUY item, etc. Things that have to get there, and have to get there on time.
     
    patrykszylindev likes this.
  14. DexRobinson

    DexRobinson

    Joined:
    Jul 26, 2011
    Posts:
    594
    An easy way to send the animation your character is doing is using RPC. There is some lag using it though, but it's pretty simple just make an RPC function then call it in your update and it will send the information to other computers. Hope that helps a little bit. Just make sure you have a networkView attached to your character.

    Code (csharp):
    1.  
    2. private string currentAnimation "";
    3.  
    4. [RPC]
    5. void SetAnimation(string clip)
    6. {
    7. currentAnimation = clip;
    8. animation.Play(clip);
    9. }
    10.  
    11. void Update()
    12. {
    13. currentAnimation = walking;
    14. animation.Play(currentAnimation);
    15. // broadcast what animation you currently are doing to the server
    16. networkView.RPC("SetAnimation", RPCMode.AllBuffered, currentAnimation);
    17. }
    18.  
     
    rajavamsidhar_gvs likes this.
  15. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    @DexRobinson: THIS CODE IS SICK!!! I took your suggestion and managed to get Network sync working in 5 minutes! Thank you so much!

    As for everyone else using the legacy animation API, i suggest using Dex's code for your RPC calls, it works! ;)
     
  16. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,052
    The code will also lead to huge desyncs, animations not playing, not playing long enough, etc. Yeah it works locally when you test it because you have 0 ping internally, but if you'd try to put this in a real game with real players over the internet, it would break.
     
  17. Glader

    Glader

    Joined:
    Aug 19, 2013
    Posts:
    456
    You guys should be listening to Fholm. It's a fools errand to attempt to deviate from the setup he's suggesting.

    Ask yourself how you determine what animation your client is currently playing. If it's based on an enum you arbitrarily set then you've bad design. If you're moving then base the animation around that state, and the action which is movement, and calculate the resulting animation clientside. Once you've achieved that you can do the same on every other client without networking more than the movement as the movement IS the information required to deduce the animation state.

    From there things can get more complex but, hopefully, this should be an example of better design like the one FHolm is suggesting.

    Also, no offense Dex but I disagree that a buffered RPC sending the current animation state is an appropriate solution to networked animations. While it technically is one it should be only a placeholder at best.
     
  18. MWMDragon

    MWMDragon

    Joined:
    Aug 14, 2014
    Posts:
    3
    I know this is an old post... but.. I have tried a bunch of network animation systems and Fholm has it dead on.

    Prediction Based Animation causes no network traffic at all and it works:

    Here is a simple explanation:

    The way that Prediction based Animation works is that the game will set the animation that the player should be playing based on their movement.. If the player is moving forward then the player model will show the walking animation, if they are moving up, show the jumping animation.
    There is no Network overhead (Bandwidth Use) because nothing needs to be sent to the server or the clients, because the animation as it is being predicted and shown by each client playing.
    With the animations already stored in each clients game files, no information needs to be sent. Animations being predicted by all clients playing the game.. job done!
     
  19. NikoBusiness

    NikoBusiness

    Joined:
    May 6, 2013
    Posts:
    289
    MWMDragon small example code please?
     
  20. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    it depeneds on the type of game you are making.

    Some games with simple linear animations are fine with the RPC approach, especially for stationary objects.

    Game where movement is critical to gameplay and animation is purely visual, such as an FPS, are more likely to want to derive animation state from movement state and drive action animations from game events.

    Games where movement is less twitchy and gameplay is paramount, such as MMOs, tend to drive animation from a skill system or spell system and hide latency with game design techniques like "casting animations".

    Games where animation is integral to gameplay, such as a fighting game, may require the exact same animation sequences to play on every client, and have accurate transitions and blends - so they need even more data. So these games may send the state of animation parameters on a continual basis in addition to data dumps at each transition.

    It is going to be a balance between bandwidth usage and accuracy of remote animations, and the place you end up at really depends on your requirements - probably I hybrid of these approaches in most cases. Mecanim has hooks to get at the data you need to do any of these things.
     
    chokage and nxrighthere like this.