You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取其他玩家PhotonView调用RPC实现多人抓人游戏重置

多人抓人游戏全员重置逻辑实现问题

问题背景

一周前才开始学习C#编程,若问题较为基础还请谅解。
我正在开发多人抓人(Tag)游戏,目前抓人标记功能已正常运行,当前需要实现游戏重置重启逻辑:我通过玩家PhotonView的Tag.Length统计已被标记的玩家数量。

已定义变量

  • private GameObject[] UnTaggedPlayers;
  • public PhotonView Player;

现有功能代码

public void OnTagged()
{
    //Flag as tagged
    _isTagged = true;
    //Touchbacks countdown
    _touchbackCountDown = _touchBackDuration;
   
    GetComponentInChildren<SkinnedMeshRenderer>().material = _InfectionMat;
   
    tagged.Play();

    Player.tag = "Tagged";
}

[PunRPC]
public void OnUnTagged()
{
    //Flag as tagged
    _isTagged = false;
    //Change the color of player
    GetComponentInChildren<SkinnedMeshRenderer>().material = _initialMat;
    GetComponentInChildren<SkinnedMeshRenderer>().material.color = _initialColor;

    Player.tag = "NotTagged";
}

public void Update()
{
    UnTaggedPlayers = GameObject.FindGameObjectsWithTag("NotTagged");

    if (photonView.IsMine)
    {
        if (_touchbackCountDown > 0f)
        {
            _touchbackCountDown -= Time.deltaTime;
        }
    }
}

private void OnTriggerEnter(Collider other)
{
    var otherPlayer = other.GetComponentInParent<TagManager>();
    if (otherPlayer != null)
        if (_isTagged && _touchbackCountDown <= 0f)
        {
            if(UnTaggedPlayers.Length <= 0)
            {
                //Untag Everyone
            }
            else
            {
                otherPlayer.photonView.RPC("OnTagged", RpcTarget.AllBufferedViaServer);
            }
        }
    }
}

待实现需求

需要实现代码中//Untag Everyone注释对应的全员取消标记逻辑,找到获取所有玩家PhotonView并向其发送Untag对应RPC的方法。


实现方案

核心逻辑说明

Photon PUN开发多人同步逻辑时,状态修改类逻辑统一由房主(MasterClient)作为权威端触发,可以避免多客户端重复调用导致的状态错乱。不需要手动遍历PhotonView列表,直接查找场景中所有挂载了TagManager组件的玩家对象,逐个发送OnUnTagged的RPC即可完成全员同步重置。

另外现有代码里每帧在Update中调用GameObject.FindGameObjectsWithTag是全场景遍历操作,性能开销很高,建议后续移到玩家标记状态变化的回调中执行计数更新,不要每帧查询。

替换//Untag Everyone位置的代码

if (UnTaggedPlayers.Length <= 0)
{
    // 仅房主触发重置,避免多端重复执行
    if (PhotonNetwork.IsMasterClient)
    {
        // 拉取所有挂载TagManager的玩家实例
        TagManager[] allPlayerScripts = FindObjectsOfType<TagManager>();
        // 遍历给所有玩家发送取消标记的RPC,全客户端同步状态
        foreach (TagManager player in allPlayerScripts)
        {
            player.photonView.RPC(nameof(OnUnTagged), RpcTarget.AllBufferedViaServer);
        }

        // 可选:重置后随机指定下一局的初始抓人者
        int newSeekerIndex = Random.Range(0, allPlayerScripts.Length);
        allPlayerScripts[newSeekerIndex].photonView.RPC(nameof(OnTagged), RpcTarget.AllBufferedViaServer);
    }
}

方案优势

  • 用FindObjectsOfType<TagManager>()查找玩家比通过Tag查找更准确,不会把场景内其他带同名Tag的无关对象计入统计
  • 用nameof(OnUnTagged)代替硬编码方法名字符串,后续修改方法名时不会出现RPC匹配失败的问题
  • 房主权威触发逻辑,同步稳定性更高,不会出现多客户端同时重置的冲突问题

内容的提问来源于stack exchange,提问作者CorMemory

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:57:22