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

基于Photon PUN 2实现多人游戏本地启用死亡玩家Up Camera

问题:Photon PUN2中仅让本地死亡玩家切换到 spectator camera

在基于Photon PUN 2开发的多人游戏中,目标是实现玩家死亡时启用名为“Up Camera”的 spectator camera,但当前存在问题:玩家死亡时该相机会对所有玩家全局启用,未死亡玩家也会强制切换到该相机。伤害数据由包含射击者ID与被击中玩家ID的projectile传递,当前使用的damageMenager脚本如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;

public class damageMenager : MonoBehaviour
{
    public int hp;
    public GameObject player;
    public Image hpBar;
    public PlayerSpawner playerSpawner;

    public void Update()
    {
        if(this.gameObject == player)
        {
            hpBar.fillAmount = hp / 100f ;
        }
    }

    private void Awake()
    {
        playerSpawner = FindObjectOfType<PlayerSpawner>();
    }

    public void takeDamage(int damage, GameObject otherPlayer, int shooterId)
    {
        if (otherPlayer.GetPhotonView() != null)
        {
            if (otherPlayer.GetPhotonView().ViewID != shooterId)
            {
                if (hp <= 0)
                {
                    foreach (Transform tm in otherPlayer.transform)
                    {
                        if (tm.GetComponent<wheelController>() != null)
                        {
                            tm.GetComponent<wheelController>().enabled = false;
                        }
                    }

                    otherPlayer.transform.Find("Camera").gameObject.SetActive(false);
                    otherPlayer.transform.Find("CM FreeLook1").gameObject.SetActive(false);
                    otherPlayer.transform.Find("Canvas").gameObject.SetActive(false);
                    otherPlayer.GetComponent<tuttiPU>().enabled = false;
                    otherPlayer.GetComponent<mina>().enabled = false;
                    otherPlayer.GetComponent<Inpiedi>().enabled = false;
                    otherPlayer.GetComponent<cannoniDavanti>().enabled = false;
                    otherPlayer.GetComponent<localPlayerManager>().enabled = false;
                    otherPlayer.GetComponent<damageMenager>().enabled = false;
                    otherPlayer.transform.Find("Up Camera").gameObject.SetActive(true);
                }
                else
                {
                    hp -= damage;
                }
            }
        }
    }
}

解决方案

核心问题在于当前代码在所有客户端执行了相机切换逻辑,而相机切换是本地客户端专属操作,不该全局同步执行。只需通过Photon的IsMine属性判断操作对象是否为本地玩家,即可实现仅在死亡玩家的本地设备启用 spectator camera。

修改后的代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;

public class damageMenager : MonoBehaviour
{
    [SyncVar(hook = nameof(OnHpChanged))] // 同步生命值,确保客户端状态一致
    public int hp = 100;
    public GameObject player;
    public Image hpBar;
    public PlayerSpawner playerSpawner;

    public void Update()
    {
        if(this.gameObject == player)
        {
            hpBar.fillAmount = hp / 100f ;
        }
    }

    private void Awake()
    {
        playerSpawner = FindObjectOfType<PlayerSpawner>();
    }

    // SyncVar钩子:生命值变化时自动更新UI(优化体验)
    private void OnHpChanged(int oldHp, int newHp)
    {
        if(this.gameObject == player)
        {
            hpBar.fillAmount = newHp / 100f;
        }
    }

    public void takeDamage(int damage, GameObject otherPlayer, int shooterId)
    {
        var photonView = otherPlayer.GetPhotonView();
        if (photonView == null) return;
        if (photonView.ViewID == shooterId) return;

        if (hp <= 0)
        {
            // 所有客户端通用的死亡逻辑(禁用非本地控制组件)
            foreach (Transform tm in otherPlayer.transform)
            {
                var wheelCtrl = tm.GetComponent<wheelController>();
                if (wheelCtrl != null)
                {
                    wheelCtrl.enabled = false;
                }
            }

            otherPlayer.GetComponent<tuttiPU>().enabled = false;
            otherPlayer.GetComponent<mina>().enabled = false;
            otherPlayer.GetComponent<Inpiedi>().enabled = false;
            otherPlayer.GetComponent<cannoniDavanti>().enabled = false;
            otherPlayer.GetComponent<damageMenager>().enabled = false;

            // 仅在本地玩家的客户端执行相机/UI切换
            if (photonView.IsMine)
            {
                otherPlayer.transform.Find("Camera").gameObject.SetActive(false);
                otherPlayer.transform.Find("CM FreeLook1").gameObject.SetActive(false);
                otherPlayer.transform.Find("Canvas").gameObject.SetActive(false);
                otherPlayer.GetComponent<localPlayerManager>().enabled = false;
                otherPlayer.transform.Find("Up Camera").gameObject.SetActive(true);
            }
        }
        else
        {
            // 仅服务器端修改生命值,防止客户端恶意篡改
            if (PhotonNetwork.IsMasterClient)
            {
                hp -= damage;
            }
        }
    }
}

关键改动说明

  1. 同步生命值:给hp添加[SyncVar]属性,确保所有客户端的生命值状态一致,避免逻辑冲突。
  2. 本地玩家判断:将相机切换、UI隐藏、本地控制组件禁用等操作放在photonView.IsMine判断内,仅让死亡玩家的本地设备执行这些操作。
  3. 服务器端控血:生命值修改由MasterClient(服务器)执行,杜绝客户端篡改数据的可能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:28:22