ExampleGameGuidePart02Interaction

Adding simple interaction to game made in part 1

So far, TransformSynchronizable2D has been syncing our movement automatically every frame.
Not every action should be synced that way though - some things should only trigger once, when a specific event happens.
In this part we will add a "blink" interaction: pressing Space turns your player red for everyone, and releasing it turns them back.
This kind of one-off, on-demand sync is called a Remote Procedure Call (RPC): instead of continuously
sending data, we send a single method call to every user telling them "blink is now on" or "blink is now off".

Update the PlayerController

To send and receive RPCs, our PlayerController needs to inherit from AttributesSync instead of CommunicationBridge.
AttributesSync includes everything CommunicationBridge did, plus the ability to broadcast methods to other users.
We will make three changes to PlayerController:
  1. Change the base class from CommunicationBridge to AttributesSync.
  2. In Update(), detect when the Jump axis (Space bar) changes and call BroadcastRemoteMethod to tell every user about it.
  3. Add a new BlinkRpc method, marked with [SynchronizableMethod], that actually changes the sprite color. This is the method that runs on every user's machine when the RPC arrives.
Here is the full, updated script:
C#
using UnityEngine;
using Alteruna.Multiplayer.Core;
using Alteruna.Multiplayer.Unity;

public class PlayerController : AttributesSync
{
    public float Speed = 10.0f;
    public float RotationSpeed = 180.0f;
    private SpriteRenderer _renderer;
    private bool _lastState = false;

    void Awake()
    {
        _renderer = GetComponent<SpriteRenderer>();
    }

    public override void Possessed(bool isMe, User user)
    {
        enabled = isMe;

        if (isMe)
        {
            // Set the color sprite representing me to be green
            _renderer.color = Color.green;
        }
    }

    // Only runs when possessed by local user (isMe == true)
    void Update()
    {
        // Get the horizontal and vertical axis.
        float _translation = Input.GetAxis("Vertical") * Speed;
        float _rotation = -Input.GetAxis("Horizontal") * RotationSpeed;

        _translation *= Time.deltaTime;
        _rotation *= Time.deltaTime;

        transform.Translate(0, _translation, 0, Space.Self);
        transform.Rotate(0, 0, _rotation);

        // Blink based on the state of Jump axis (Spacebar button)
        bool blink = Input.GetAxisRaw("Jump") >= 0.5f;
        if (blink != _lastState)
        {
            _lastState = blink;
            // Broadcasts the "BlinkRpc" method call to all users, passing the new blink state
            BroadcastRemoteMethod("BlinkRpc", blink);
        }
    }

    // [SynchronizableMethod] marks this as an RPC target: it runs on every user's machine when
    // BroadcastRemoteMethod("BlinkRpc", ...) is called, including the machine that sent it.
    // It can be called even while the component is disabled, as long as OnEnable has run at least once.
    [SynchronizableMethod]
    private void BlinkRpc(bool state)
    {
        if (state)
        {
            // Set color to red.
            _renderer.color = Color.red;
        }
        else
        {
            // Revert to green for the local user, white for everyone else.
            // (enabled is set to isMe in Possessed.)
            _renderer.color = enabled ? Color.green : Color.white;
        }
    }
}
With these changes, holding Space turns your player red for everyone in the Room, and releasing it turns them back.
Try it out with two instances running side by side, like we did in Part 1.
The same pattern (detect an event, then BroadcastRemoteMethod to a SynchronizableMethod) works for any
one-off action you want everyone to see, such as firing a weapon, playing an animation, or taking damage.
Read more about attribute sync here.

← Back | Next →

See Also