Photon 4人房间满足触发条件时展示玩家字符串及PlayerPrefs使用问题
核心问题澄清
PlayerPrefs是单设备本地存储组件,仅会将数据保存在当前运行游戏的设备本地,完全不具备跨设备、跨玩家同步能力,不可能让房间内其他玩家读取到你本地PlayerPrefs存储的内容,这是你目前只能捕获本地玩家输入的根本原因。
你已经接入了Photon网络框架,所有需要跨玩家同步的内容、全局触发的逻辑,都应该通过Photon提供的同步能力实现,不要依赖本地存储。
修正方案
1. 字符串输入逻辑修正
废弃用PlayerPrefs存储待同步字符串的逻辑,改用Photon玩家自定义属性存储每个玩家的输入内容,Photon会自动将属性同步给房间内所有玩家:
[SerializeField] WordInfo wordInfo; public TMPro.TMP_InputField InputWord; private string StringWord; // 输入完成后点击按钮调用 public void SetString() { StringWord = InputWord.text; // 将输入内容存入本地玩家的Photon自定义属性,自动同步全房间 ExitGames.Client.Photon.Hashtable playerProps = new ExitGames.Client.Photon.Hashtable(); playerProps.Add("PlayerWord", StringWord); PhotonNetwork.LocalPlayer.SetCustomProperties(playerProps); // 本地同步到WordInfo单例 wordInfo.word = StringWord; } // 读取任意玩家的输入内容 public string GetPlayerWord(Photon.Realtime.Player targetPlayer) { if(targetPlayer.CustomProperties.TryGetValue("PlayerWord", out object wordObj)) { return wordObj.ToString(); } return "no word"; }
2. WordInfo单例逻辑修正
你原有单例的销毁逻辑写反了,重复生成时应该销毁新对象而非替换原有单例,避免跨场景时数据丢失:
public class WordInfo: MonoBehaviour { public string word; public static WordInfo wordInfo; private void Awake() { if (wordInfo == null) { wordInfo = this; DontDestroyOnLoad(gameObject); } else if(wordInfo != this) { // 已存在单例时直接销毁当前新生成的对象 Destroy(gameObject); } } }
3. 全局展示+游戏结束逻辑修正
触发展示和游戏结束的逻辑需要通过Photon RPC全房间同步调用,保证所有玩家同时触发对应逻辑:
public string TheSavedWord; private const string DISPLAY_MY_STRING_PLAYER = "{0} Your Word is displayed to others!"; private const string DISPLAY_OTHER_STRING_PLAYER = "{0}'s word has been Displayed!"; private const string MY_WORD = "{0} your word is: "; public Photon.Realtime.Player activePlayer; public TMPro.TMP_Text Player_Notification; public TMPro.TMP_Text WordToDisplay; public bool iAmActive; // 全房间同步执行的展示+结束逻辑,通过RPC触发 [PunRPC] public void ShowPlayerString(int activePlayerActorNr) { // 获取当前活跃玩家对象 activePlayer = PhotonNetwork.CurrentRoom.GetPlayer(activePlayerActorNr); // 读取该玩家同步的输入内容 TheSavedWord = activePlayer.CustomProperties.TryGetValue("PlayerWord", out object wordObj) ? wordObj.ToString() : "no word"; iAmActive = activePlayer == PhotonNetwork.LocalPlayer; // 界面展示 Player_Notification.text = string.Format(iAmActive ? DISPLAY_MY_STRING_PLAYER : DISPLAY_OTHER_STRING_PLAYER, activePlayer.NickName); WordToDisplay.text = string.Format(MY_WORD + " " + TheSavedWord, activePlayer.NickName); // 调用本地游戏终止逻辑 EndGame(); } // 触发同步的入口,满足bool条件时调用即可 public void TriggerShowAndEnd() { // 仅房主或当前活跃玩家可触发,避免重复调用 if(PhotonNetwork.IsMasterClient || activePlayer == PhotonNetwork.LocalPlayer) { PhotonView.Get(this).RPC(nameof(ShowPlayerString), RpcTarget.All, activePlayer.ActorNumber); } } private void EndGame() { // 此处补充你的游戏终止逻辑,如锁定输入、展示结算页等 }
注意事项
- PlayerPrefs仅适合存储本地玩家的单机配置(如音效开关、操作设置等不需要同步给其他玩家的内容),不要用它存储任何需要跨玩家同步的数据
- 所有全局生效的逻辑都要通过Photon RPC或者房间自定义属性同步触发,不要仅在本地单独执行,避免不同玩家的游戏进度不一致
- 挂载第三个脚本的对象需要添加PhotonView组件,才能正常发送/接收RPC调用
内容的提问来源于stack exchange,提问作者Shem Tom
相关产品推荐
相关产品推荐

