Dom Beasley
Dom Beasley

Reputation: 55

Unity Control object with a script that is controlled with an attached script

I followed a tutorial on making the Tron game for my project and I want to add multiplayer capability. I've set up a message system where a phone sends a direction change to the computer displaying the game to then make their player change direction. Each player is controlled with an attached 'Move' script that uses references to itself and a set of methods based on key inputs. I'm trying to get my game manager to receive these messages from the phone and cause the players to switch direction - I've tried making the move script have static elements but that seems to break it.

Is there a good way of doing this or would it be preferable to write a new move script that controls all players simultaneously that is just attached elsewhere?

The current code is as follows:

switch (direction)
            {
                case "N":
                    Instance.player1.GetComponent<Rigidbody2D>().velocity = Vector2.up * Move.speed;

                    break;
                case "E":
                    Instance.player1.GetComponent<Rigidbody2D>().velocity = Vector2.right * Move.speed;

                    break;
                case "S":
                    Instance.player1.GetComponent<Rigidbody2D>().velocity = Vector2.down * Move.speed;

                    break;
                case "W":
                    Instance.player1.GetComponent<Rigidbody2D>().velocity = Vector2.left * Move.speed;

                    break;

Move is a reference to the script attached to each game, but for the script to function, a call to this method is required after each direction change:

public void spawnWall()
{
    lastWallEnd = transform.position;
    GameObject objectOfGame = (GameObject)Instantiate(wallPrefab, transform.position, Quaternion.identity);
    wall = objectOfGame.GetComponent<Collider2D>();
}

I tried to make it static but it wasn't working so I'm guessing that's not the route to take. SpawnWall is called every time an internal direction change is made.

void createConstantWall(Collider2D collision, Vector2 start, Vector2 finish)
{
    collision.transform.position = start + (finish - start) * 0.5f;
    float distance = Vector2.Distance(start, finish);
    if (start.x != finish.x)
        collision.transform.localScale = new Vector2(distance + 1, 1);
    else
        collision.transform.localScale = new Vector2(1, distance + 1);
}

This function is called in update

Losing method:

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision != wall)
    {
        //add losing stuff
        Destroy(gameObject);
    }
}

Upvotes: 1

Views: 350

Answers (1)

Erik Overflow
Erik Overflow

Reputation: 2306

There are a few ways to handle multiple user inputs from different phones (or other sources). Here is my preferred solution:

  • All input goes through a generic manager with the player's id whenever movement is sent. This input is converted to an event to simplify dependencies.

Since you have stated you already have a custom message being sent to the game manager with the player number and direction, we will work with that.

Within your GameManager.cs or an InputManager.cs

public static event Action<int, string> OnInputReceived;

void InputReceived(int playerNumber, string direction)
{
    OnInputReceived?.Invoke(playerNumber, direction);
}

Within your PlayerMovementController.cs that should be attached to each individual player in the game, you should be tracking your playerId, or be able to check another attached script for the playerId:

public int playerId;

void Awake()
{
    GameManager.OnInputReceived += MovePlayer;
}

void MovePlayer(int inputPlayerId, string direction)
{
    if(inputPlayerId != playerId)
        return;
    else
    {
        //move THIS player in the "direction" using your movement logic
    }
}

void OnDestroy()
{
    GameManager.OnInputReceived -= MovePlayer;
}

If all of your players have unique ids and have the PlayerMovementController attached, they can now all listen to the inputs but only move when their ID is tied to it. If your GameManager calls InputReceived(1,"E"), all of your PlayerMovementControllers will call MovePlayer(1, "E"), but only the one with playerId == 1 will actually move since all of the others return immediately.

-- Diclaimer: All of this code is freehanded in StackOverflow, so there may be some syntax errors I didn't catch. Please let me know or edit it directly.

Upvotes: 1

Related Questions