private void OnPlayerRemoved(Model model, object mainModelObj)
    {
        WorldModel mainModel = mainModelObj as WorldModel;

        if (model == null || mainModel == null)
        {
            return;
        }
        uint key = 0;

        foreach (KeyValuePair <uint, ModelReference> pair in mainModel.players)
        {
            if (pair.Value == model.Index)
            {
                key = pair.Key;
                break;
            }
        }
        mainModel.players.Remove(key);

        // Remove from the team
        // TODO: remove from correct team...
        TeamsManagerModel teamsManagerModel = StateManager.state.GetModel(mainModel.teamsModelId) as TeamsManagerModel;

        teamsManagerModel.teams[0].entities.Remove(model.Index);
    }
    protected override void Update(WorldModel model)
    {
        // Get physics model. If doesn't exist, create it
        PhysicWorldModel      physicsModel;
        PhysicWorldController physicsController;
        TeamsManagerModel     teamsManagerModel;
        Model playerModel;

        if (model.physicsModelId == ModelReference.InvalidModelIndex)
        {
            // create world with map name and gravity
            physicsModel         = new PhysicWorldModel("map 1", new FixedVector3(0, gravityY, 0));
            model.physicsModelId = StateManager.state.AddModel(physicsModel);
            physicsController    = physicsModel.Controller() as PhysicWorldController;
            // populate world
            PopulatePhysicsWorld(physicsModel, physicsController);
        }
        else
        {
            physicsModel      = StateManager.state.GetModel(model.physicsModelId) as PhysicWorldModel;
            physicsController = physicsModel.Controller() as PhysicWorldController;
        }



        // Teams manager
        if (model.teamsModelId == ModelReference.InvalidModelIndex)
        {
            teamsManagerModel  = new TeamsManagerModel(3);
            model.teamsModelId = StateManager.state.AddModel(teamsManagerModel);


            // Create some dummy enemy
            FixedVector3 initialPosition = GetRandomSpawnPosition(model);
            playerModel = new GameEntityModel(
                StateManager.state,
                physicsModel,
                new PhysicPointModel(
                    null,
                    initialPosition,
                    new FixedVector3(0, 0.5, 0),
                    DefaultVCFactoryIds.PhysicPointControllerFactoryId,
                    SorVCFactories.Point2DViewFactoryId,
                    DefaultUpdateOrder.PhysicsUpdateOrder
                    ),
                new AnimationModel(
                    null,
                    "Axel",
                    "standing",
                    CharacterLoader.GetCharacterSkinName("Axel", 0)
                    ),
                null,                 // no input
                DefaultVCFactoryIds.GameEntityControllerFactoryId,
                SorVCFactories.Entity2DViewFactoryId,
                DefaultUpdateOrder.EntitiesUpdateOrder
                );
            // Model initial state
            GameEntityModel playerEntity = (GameEntityModel)playerModel;
            playerEntity.mIsFacingRight = initialPosition.X < 0;
            // hardcoded energy
            playerEntity.customVariables["energy"] = 100;
            teamsManagerModel.teams[2].entities.Add(StateManager.state.AddModel(playerModel));


//			// Create some weapon
//			initialPosition = new FixedVector3(2, 8, 3);
//			playerModel = new GameEntityModel(
//				StateManager.state,
//				physicsModel,
//				new PhysicPointModel(
//					null,
//					initialPosition,
//					new FixedVector3(0, 0.5, 0),
//					DefaultVCFactoryIds.PhysicPointControllerFactoryId,
//					SorVCFactories.Point2DViewFactoryId,
//					DefaultUpdateOrder.PhysicsUpdateOrder
//				),
//				new AnimationModel(
//					null,
//					"Bat_HD",
//					"bat_air",
//					CharacterLoader.GetCharacterSkinName("Bat_HD", 0)
//				),
//				null, // no input
//				DefaultVCFactoryIds.GameEntityControllerFactoryId,
//				SorVCFactories.Entity2DViewFactoryId,
//				DefaultUpdateOrder.EntitiesUpdateOrder
//			);

//			// Model initial state
//			playerEntity = (GameEntityModel)playerModel;
//			playerEntity.isFacingRight = initialPosition.X < 0;
//			// hardcoded energy
//			playerEntity.customVariables["energy"] = 100;
            // Goodies going on team 0
//			teamsManagerModel.teams[0].entities.Add(StateManager.state.AddModel(playerModel));
        }
        else
        {
            teamsManagerModel = StateManager.state.GetModel(model.teamsModelId) as TeamsManagerModel;
        }


        List <uint> allPlayers;

        if (StateManager.Instance.IsNetworked)
        {
            allPlayers = NetworkCenter.Instance.GetAllNumbersOfConnectedPlayers();
        }
        else
        {
            allPlayers = new List <uint>();
            allPlayers.Add(0);
        }

        // Remove characters for inactive players
        foreach (KeyValuePair <uint, ModelReference> pair in model.players)
        {
            if (!allPlayers.Exists(x => x == pair.Key))
            {
                // Doesn't exist anymore, remove ship
                playerModel = StateManager.state.GetModel(pair.Value);
                //worldController.RemovePoint(shipModel, OnShipDestroyed, model);
                StateManager.state.RemoveModel(playerModel, OnPlayerRemoved, model);
            }
        }

        // Create characters for new players
        NetworkSorPlayerData playerData;

        foreach (uint playerId in allPlayers)
        {
            if (!model.players.ContainsKey(playerId))
            {
                if (StateManager.Instance.IsNetworked)
                {
                    playerData = NetworkCenter.Instance.GetPlayerData <NetworkSorPlayerData>(playerId);
                }
                else
                {
                    playerData = NetworkCenter.Instance.GetPlayerData <NetworkSorPlayerData>();
                }
                if (playerData == null)
                {
                    RetroBread.Debug.LogWarning("Player " + playerId + " have invalid player data!");
                    continue;
                }
                RetroBread.Debug.Log("Player " + playerId + " have character " + playerData.selectedCharacter);
                Model        inputModel      = new PlayerInputModel(playerId);
                FixedVector3 initialPosition = GetRandomSpawnPosition(model);
                playerModel = new GameEntityModel(
                    StateManager.state,
                    physicsModel,
                    new PhysicPointModel(
                        null,
                        initialPosition,
                        new FixedVector3(0, 0.5, 0),
                        DefaultVCFactoryIds.PhysicPointControllerFactoryId,
                        SorVCFactories.Point2DViewFactoryId,                         // DefaultVCFactoryIds.PhysicPointViewFactoryId,
                        DefaultUpdateOrder.PhysicsUpdateOrder
                        ),
                    new AnimationModel(
                        null,
                        "Axel",
                        "standing",
                        CharacterLoader.GetCharacterSkinName("Axel", 0)
                        ),
                    inputModel,
                    DefaultVCFactoryIds.GameEntityControllerFactoryId,
                    SorVCFactories.Entity2DViewFactoryId,                     //DefaultVCFactoryIds.GameEntityViewFactoryId,
                    DefaultUpdateOrder.EntitiesUpdateOrder
                    );
                // Model initial state
                GameEntityModel playerEntity = (GameEntityModel)playerModel;
                playerEntity.mIsFacingRight = initialPosition.X < 0;
                model.players[playerId]     = StateManager.state.AddModel(playerModel);
                // hardcoded energy
                playerEntity.customVariables["energy"] = 100;
                teamsManagerModel.teams[1 + playerId % 2].entities.Add(model.players[playerId]);
            }

            GameObject obj = UnityObjectsPool.Instance.GetGameObject(model.players[playerId]);
            // using the name as a hack around having a variable in a script to tell the object is "initialized"
            // should be done in a better way.. but whatever, will do for the demo
            if (obj != null && !obj.name.EndsWith("[initiated]"))
            {
                bool isOwnPlayer;
                if (StateManager.Instance.IsNetworked)
                {
                    isOwnPlayer = playerId == NetworkCenter.Instance.GetPlayerNumber();
                }
                else
                {
                    isOwnPlayer = true;                     // warning: local multiplayer would be different, playerId == 0?, actually different camera
                }

                if (isOwnPlayer)
                {
                    // Add camera tracking to own player :)
                    obj.AddComponent <CameraTracker>();

                    // TODO: add HUD tracking to this player
                    // Note: I'm doing this here at the moment, but if I need to derive GameEntity
                    // this can go inside it's view.
                    // However I can create a new model just to keep player stats (kills, energy, etc)
                    // and use the respective view to display the stats in the HUD
                }
                obj.name += "[initiated]";
            }
        }

        // check end of the game
        if (CheckGameOver(model))
        {
            // game over
            return;
        }
    }