我正在开发基于回合的多人游戏。
因此,我有一个名为gameController的脚本,该脚本具有全局计时器来更改回合,还可以选择当前回合中攻击的玩家和防御的玩家。
该脚本是一个附加到gameObject
并带有网络标识的单例(此网络标识没有复选框标记为服务器控制)。当服务器连接时,我试图将这个游戏对象生成给所有客户端,并且还试图将游戏对象放置在场景中(展位无法使用)。
好吧,主要的问题是在gameController脚本中,我在更新功能中有一个检查器来检查是否连接了任何新玩家。万一已连接,它应该调用一个名为syncEvent
的{{1}}(我尝试直接调用它,也使用[command]和[ClientRpc])来让玩家知道他们必须调用他们的名为“ OnRegisterPlayer”的函数,这是他们自己的播放器脚本中的函数,该函数在gameController脚本上调用一个函数,传递播放器对象(我也通过command和rpc尝试过),如下所示:EventOnNewPlayerAddedDelegate
任何人都知道我该如何触发此GameController.instance.RegisterPlayer(this);
来将播放器注册到服务器控制的非播放器对象?
非常感谢您。
我在此处附上简短的Boots脚本,以使其更易于理解:
GameController:
SyncEvent
PlayerScript:
public class GameController : NetworkBehaviour
{
public delegate void OnNewPlayerAddedDelegate();
[SyncEvent]
public event OnNewPlayerAddedDelegate EventOnNewPlayerAddedDelegate;
List<GamePlayerManager> players = new List<GamePlayerManager>();
public static GameController instance { get; private set; }
float timePerTorn = 30f;
bool isCountdown = false;
[System.NonSerialized]
public float countdownTime;
int roundNumber = 0;
int NumberOfPlayers;
int NumberOfPlayersChanged;
void Awake()
{
Debug.Log("Awaking ");
if (instance != null)
{
Debug.Log("Destoring ");
DestroyImmediate(this);
return;
}
instance = this;
}
// Use this for initialization
void Start()
{
if (!isServer)
{
return;
}
players = new List<GamePlayerManager>();
StartCountdown(5f);//20
}
void Update()
{
if (isServer)
{
if (isCountdown)
{
countdownTime -= Time.deltaTime;
if (countdownTime <= 0)
{
AlterGlobalTurns();
}
}
}
NumberOfPlayers = NetworkManager.singleton.numPlayers;
if (NumberOfPlayersChanged != NumberOfPlayers)
{
Debug.Log("num of players changed ---> " + NumberOfPlayers);
NumberOfPlayersChanged = NumberOfPlayers;
EventOnNewPlayerAddedDelegate();
//RpcNewPlayerAdded();
//CmdNewPlayerAdded();
}
}
[ClientRpc]
void RpcNewPlayerAdded()
{
Debug.Log("---------------- RpcNewPlayerAdded ------------");
EventOnNewPlayerAddedDelegate();
}
[Command]
void CmdNewPlayerAdded()
{
Debug.Log("---------------- CmdNewPlayerAdded ------------");
EventOnNewPlayerAddedDelegate();
}
public void RegisterPlayer(GamePlayerManager player)
{
Debug.Log("player ---> " + player.name);
if (players.Contains(player))
{
return;
}
Debug.Log("players ---> " + players);
players.Add(player);
}
}
答案 0 :(得分:0)
我想我已经在这里看到了问题。
问题在于GameController是由OnStartServer()函数中的playerScript(即使玩家也是主机)产生的。因此,第一个问题是GameController不能检测主机玩家,因为它不是新连接。第二个问题是当连接了第二个客户端时,GameController会检测到客户端连接,并比客户端唤醒更快地发送事件信号,因此当客户端已经在工作时,信号消失了。
我解决了删除此信号并直接在playerScript中检查GameController是否存在然后检查玩家是否已经注册的问题。
我现在的问题是,是否有任何实例可以在播放器(主机)之前唤醒服务器对象,我知道答案是“否”,因为作为播放器是主机,它需要运行才能拥有服务器。 第二个问题是,是否有信号或信号知道新播放器已连接,请等待它唤醒。
非常感谢。 您可以在Unity论坛上检查漏洞:https://forum.unity.com/threads/multiplayer-syncevent-problem-with-non-player-objects.589309/