【问题标题】:Unity Control object with a script that is controlled with an attached script带有脚本的 Unity 控制对象,该脚本由附加的脚本控制
【发布时间】:2020-01-09 02:28:49
【问题描述】:

我遵循了为我的项目制作 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);
    }
}

【问题讨论】:

  • 你在哪里使用静力学,为什么?如果有不同的玩家使用相同的移动脚本,则在这些脚本中使用静态值将不起作用。
  • @ErikOverflow 是的,我想到了,所以我已经删除了几乎所有与之相关的静态内容。
  • 所以你的问题是“如果输入来自手机,我如何分别控制不同的玩家?”​​span>
  • 我的问题是:有没有一种方法可以访问附加到将玩家与另一个脚本分开的脚本,并使其使用各自的脚本对各个玩家执行操作,如果有这样的事情,最好是使用它还是只是在一个更通用的地方重新创建移动脚本来控制所有玩家,一个脚本不附加到任何单个玩家。
  • 你可以有一个脚本来访问不同的播放器,有几种方法可以做到这一点。您可以将输入管理器配置为从指定的控制器获取输入,但如果手机是您的“控制器”,那么您可能需要创建一个输入管理器。我会简单地写一些东西。

标签: c# unity3d


【解决方案1】:

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

  • 无论何时发送移动,所有输入都会通过带有玩家 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 中写意的,所以可能有一些我没有发现的语法错误。请让我知道或直接编辑。

【讨论】:

  • 只是在第一个管理器代码位中检查 InputReceived 方法中显示“OnMovementInput?”的行。意味着 OnInputReceived 还是引用其他内容?
  • 你是对的!我会解决的。我改变主意了:)
  • 嗯,该控件似乎正在工作,但它与我之前在测试静态时遇到的问题相同。根据 Tron 负责在玩家身后建造墙的方法没有发挥应有的作用。我制作了问题的 gif 图像:gyazo.com/cda97076ce87491537d5a0d2e3a20f44
  • 这个问题与我所看到的静力学或你的运动逻辑无关。您能否在问题中包含有关您的墙逻辑的更多信息?当方向改变时,您的代码似乎没有创建新墙。
  • 将您链接到我使用的教程可能更容易:noobtuts.com/unity/2d-tron-lightcycles-game 我并没有真正偏离它太多
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 2018-02-13
  • 1970-01-01
  • 1970-01-01
  • 2015-05-08
相关资源
最近更新 更多