No announcement yet.

More replication questions...

  • Filter
  • Time
  • Show
Clear All
new posts

    More replication questions...

    Looking for feedback on my logic and rough implementation. Any and all comments are appreciated!

    // VERSION 3.0
    // Greg Wilson -

    // Concept: Multiplayer gametype, similar to BF:1942 in that players can jump into 'tanks' and then enter 'turrets'. Once a player is in the turret
    // his mouse movements control the turret's yaw and pitch.
    // The turretPawn extends from Pawn and the turretController extends from PlayerController.

    // Problem: We need clients to see other clients correct turret rotations. This logic doesn't appear to solve the problem when implemented. The clients still
    // cannot see any server or other client turret rotations. Any suggestions or improvements are greatly appreciated.

    // Logic:
    // Every tick, the PlayerTick() function is called. It calls the PlayerMove() function ( which is implemented in various states).
    // PlayerMove() figures out the rotation changes the player has requested and then calls turretServerOnlyProcessMove()
    // for single player or server Player and turretReplicateMove() if it’s a network client player.

    // Server initiated moves: (by player on the server box)
    // turretServerOnlyProcessMove() calls turretProcessMove() which updates the servers rotation and then calls
    // turretClientAdjustPosition() on the clients to do the same.
    // turretProcessMove() updates the bone rotation of the turret based on the players input. Both client & server run this
    // independently.
    // turretClientAdjustPosition() is executed on the client. The client sets its rotation to the servers version.
    // Client initiated moves: (by the player on a client box)
    // turretReplicateMove() calls turretProcessMove() and then executes the move on the server by calling the replicated
    // function turretServerMove() and passing in the new rotation value.
    // turretServerMove() is executed on the server only. It calls turretProcessMove() which updates the server to the clients
    // rotation
    // Client Client Updates: ??
    // the controller populates each 'player initiated move' into 'theRotation' variable of the pawn - mid tick(). Because variables are
    // replicated at the end of the tick(), it will be a tick behind, but should theoretically cause all clients have their 'theRotation'
    // variables synced with the server values and at the start of the next tick, the pawn's themselves will update their bone rotations
    // using 'theRotation' value and a SetBoneRotation() call in their tick() function.
    // A Local function means a function that is only changing data on its own box. They can be run on client or server boxes by themselves.
    // Some local functions may call client or server specific functions in addition to performing a duty on its own box.
    // From Unreal Networking Architecture Page:
    // Variable replication occurs only after a tick completes. Therefore, if in the duration of a tick, a variable changes to a new value,
    // and then it changes back to its original value, then that variable will not be replicated. Thus, clients only hear about the state of
    // the server's actor's variables after its tick completes; the state of the variables during the tick is invisible to the client.

    // There is some confusion as to what the simulated keyword does. One document says it needs to be used in order for any function to be run on the client,
    // others say it needs to be used if the server wants to call a client only function on a client.
    // When you take a look at 'UnrealWiki: Simulated Functions' you will see that functions don't need to be simulated if the actor's Role is
    // ROLE_AutonomousProxy or ROLE_Authority.
    // Based on this, it leads me to believe that any function called by a client on the server, needs to be simulated?? (to be safe)

    // Uncertainties:
    // can clients run non simulated functions on themeselves? i.e.: is my explanation of 'a local function' correct.
    // do client only functions, called BY the server (via replication statement) need to be simulated? // if we're dealing with a playercontroller and Pawn
    // do server only functions, called BY the client (via replication statement) need to be simulated? // if we're dealing with a playercontroller and Pawn
    // what keywords does the TurretPawn need to have set?
    // bAlwaysRelevant=true, bGameRelevant=true, bStatic=false, bNoDelete=true, bNetRelevant=true, bReplicateMovement=true
    // NetUpdateFrequency=1.0, NetPriority=3.0, RemoteRole=ROLE_SimulatedProxy, bReplicateAnimations=true, ??

    // example:
    // contains some pseudo code.
    class TurretController extends PlayerController;
        if role < role_authority 		// sync the servers version of client initiated moves.
        if role == role_authority 		// sync clients version of server initiated moves.
    // PlayerMove() is called via playerTick() a local, non simulated, non replicated function
    // Both clients and server call this themselves.
    // at this point, all the possesing etc... is done and the player is controlling the bone rotation of a turret with his mouse.
    state controlTurret 				// does this state need to be simulated?
        function playerMove()  			// does this function need to be simulated?
            newRotation =  player input; 		// psuedo code.
            if ( Role < ROLE_Authority )   		
                    turretReplicateMove(newRotation);        // a player has initiated a move on a client. execute this move and replicate it
    	{    					 	 // a player has initiated a move from the server, move him.
    		turretServerOnlyProcessMove(newRotation);// this function calls another function on the client, updating it to the servers 'state'     
    // local, non simulated function. It updates the actual values from playerMove
    function turretProcessMove(newRotation)
        // this function can run on any box, it simply updates the rotation on itself.
        pawn.SetBoneRotation( newRotation );  // rotate bones here. this is psuedo code.
    // local, non simulated function. a client only function.
    function turretReplicateMove(newRotation)  // a local function, dont let the name fool you. its not really replicated
    (                                          // but it's calling turretServerMove, which IS replicated.
        turretProcessMove(newRotation)         // carry out the move from input by player on a client.
        turretServerMove(newRotation);         // carry out this move on the server too
    // this function is called on the server, by a client. using the < role_authority in replication statement.
    function turretServerMove(newRotation)     // replicated, non simulated function
        turretProcessMove(newRotation);  	   //  sync's up the server to the clients move.
                                               //  v3.0 additions
        TurretPawn(pawn).theRotation = newRotation;             // for use in pawns tick(), each clients rotation is saved on the pawn, mid tick()
    // simulated function. this server only function calls a client only function. Simulated functions can only be called by
    // other simulated functions
    simulated function turretServerOnlyProcessMove(newRotation)
        turretProcessMove(newRotation);            	   // carry out the move from input player on server.
        turretClientAdjustPosition(newRotation);   	   // do same move on client version of the server player.
        TurretPawn(pawn).theRotation = newRotation;    // v3.0 additions. makes sure the server updates too
    // simulated function so it can be called on a client, by the server.
    simulated function turretClientAdjustPosition(newRotation)
        pawn.SetBoneRotation( newRotation );        // same as turretProcessMove, but client specific. this is psuedo code.
    //v3.0 additions
    //this is the pawn class that's controlled by the turretController.
    class turretPawn extends Pawn;
    var rotator theRotation;
        if(role == role_authority ) 	// broadcast servers versions of rotations a the end of each tick.
             theRotation;			// would eventually incorporate bNetDirty into this to improve performance.
    // at the start of each tick, every box will update its bone rotations from the last ticks data.
    function Tick(float deltaTime)
        SetBoneRotation(theRotation); // this is psuedo code.
        bAlwaysRelevant = true
        bGameRelevant = true

    less lurking, more responding! :P