首页 > 解决方案 > 带有脚本的 Unity 控制对象,该脚本由附加的脚本控制

问题描述

我遵循了为我的项目制作 Tron 游戏的教程,我想添加多人游戏功能。我已经建立了一个消息系统,其中手机向显示游戏的计算机发送方向变化,然后让他们的玩家改变方向。每个玩家都由一个附加的“移动”脚本控制,该脚本使用对自身的引用和一组基于关键输入的方法。我试图让我的游戏经理从手机接收这些消息并导致玩家切换方向 - 我尝试让移动脚本具有静态元素,但这似乎破坏了它。

是否有这样做的好方法,或者最好编写一个新的移动脚本来同时控制所有玩家,这些玩家只是附加在其他地方?

当前代码如下:

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 是对附加到每个游戏的脚本的引用,但要使脚本发挥作用,每次方向更改后都需要调用此方法:

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

我试图让它成为静态的,但它没有工作,所以我猜这不是要走的路。每次进行内部方向更改时都会调用 SpawnWall。

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);
}

此函数在更新中调用

输法:

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

标签: c#unity3d

解决方案


有几种方法可以处理来自不同手机(或其他来源)的多个用户输入。这是我的首选解决方案:

  • 每当发送移动时,所有输入都会通过带有玩家 ID 的通用管理器。此输入被转换为事件以简化依赖关系。

由于您已经声明您已经向游戏经理发送了一条包含玩家编号和方向的自定义消息,因此我们将对此进行处理。

在您的 GameManager.cs 或 InputManager.cs 中

public static event Action<int, string> OnInputReceived;

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

在应该附加到游戏中每个单独玩家的 PlayerMovementController.cs 中,您应该跟踪您的 playerId,或者能够检查另一个附加脚本的 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;
}

如果您的所有玩家都有唯一的 id 并附加了 PlayerMovementController,那么他们现在都可以监听输入,但只有在他们的 ID 绑定时才移动。如果你的 GameManager 调用 InputReceived(1,"E"),你所有的 PlayerMovementControllers 都会调用 MovePlayer(1, "E"),但是只有 playerId == 1 的那个会真正移动,因为所有其他的都会立即返回。

-- 免责声明:所有这些代码在 StackOverflow 中都是徒手编写的,因此可能存在一些我没有发现的语法错误。请让我知道或直接编辑。


推荐阅读