Remote Function
Remote functions enable clients to call server-side functions while handling reliability and rate limiting. They are essential for both guaranteed execution and high-frequency updates where immediate response isn’t critical.
Understanding Remote Functions
Remote functions are the primary way to communicate between client and server in Agent8. They allow you to call server-side methods from your client application with various options for reliability and performance.
Standard remote function calls are limited to ~10 calls/second. Exceeding this will throw errors. Use throttling for high-frequency updates like position tracking.
Client API
There are three main ways to call remote functions, each suited for different scenarios:
1. Standard Calls with Return Values
Use this approach when you need to wait for the server’s computation result:
const { connected, server } = useGameServer();
if (!connected) return "Connecting...";
const handleCalculate = async () => {
const result = await server.remoteFunction("add", [1, 2]);
console.log(result); // Expected: 3
};2. Non-Response Required Calls
When you need reliability but don’t need a return value, use the needResponse: false option to improve performance:
const { server } = useGameServer();
const updateNickname = () => {
server.remoteFunction("updateMyNickname", [{ nick: "karl" }], {
needResponse: false,
});
};3. Throttled High-Frequency Calls
For real-time updates where intermediate values can be skipped (e.g., position updates), use throttling:
const { server } = useGameServer();
const handleMouseMove = (e) => {
server
.remoteFunction("updateMyPosition", [{ x: e.clientX, y: e.clientY }], {
throttle: 50,
})
.catch(() => {});
};3.1 Throttling Multiple Entities
When updating multiple entities with the same function, use throttleKey to differentiate throttling targets:
const { server } = useGameServer();
// Update ball 1
server
.remoteFunction("updateBall", [{ ballId: 1, position: { x, y } }], {
throttle: 50,
throttleKey: "1",
})
.catch(() => {});
// Update ball 2 (separate throttling)
server
.remoteFunction("updateBall", [{ ballId: 2, position: { x, y } }], {
throttle: 50,
throttleKey: "2",
})
.catch(() => {});Without specifying a throttleKey, the function name is used as the default throttle identifier.
Key Characteristics
-
Standard Calls (await)
- Guaranteed execution order
- Returns server response
- Rate limited (~10 calls/sec)
-
Non-Response Calls
- Guaranteed execution
- No return value needed
- Slightly better performance
- Still rate limited
-
Throttled Calls
- Skips intermediate calls during throttle window
- No return value needed
- Error handling optional
- Ideal for real-time updates
Example: Player Movement System
class Server {
// Standard call with return value
getPlayerPosition(playerId) {
// Get position from database or state
return { x: 100, y: 200 };
}
// Call without needing response
updatePlayerName(playerId, name) {
// Update player name in database
console.log(`Player ${playerId} name updated to ${name}`);
}
// Throttled high-frequency call
updatePlayerPosition(position) {
// Update player position in real-time
// This might be called many times per second
console.log(`Position updated to ${JSON.stringify(position)}`);
}
}Best Practices
-
Choose the Right Call Type
- Use standard calls for critical operations requiring confirmation
- Use non-response calls for operations where you don’t need the result
- Use throttled calls for frequent, transient updates
-
Error Handling
- Always use try/catch or .catch() for standard calls
- For throttled calls, you can often ignore errors with .catch(() => )
-
Performance Optimization
- Use throttling for mouse/touch movement and other high-frequency events
- Use throttleKey when updating multiple entities with the same function
- Consider using needResponse: false when you don’t need return values
Remember that throttled calls don’t return values and intermediate calls during the throttle window are ignored. Only use throttling for updates where missing intermediate states is acceptable.
Conclusion
Remote functions are the backbone of client-server communication in Agent8. By choosing the appropriate call type for each scenario, you can build responsive, real-time applications while maintaining server performance and reliability.
Use standard calls for critical operations, non-response calls for fire-and-forget updates, and throttled calls for high-frequency real-time interactions. This pattern is particularly useful for multiplayer games needing smooth position synchronization while maintaining reliability for important transactions.