我有两个脚本一个管理PhotonNetwork,负责用昵称登录,创建和加入房间和其他实例化玩家,我有两个场景,一旦场景包含PhotonNetwork_Manager,其中有网络管理器场景如下所示。
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
public class Photon_Manager : MonoBehaviourPunCallbacks
{
[SerializeField] TMP_InputField nameField;
[SerializeField] TMP_InputField roomNameField;
[SerializeField] TMP_InputField joinRoomField;
[SerializeField] GameObject createJoinCanvas;
[SerializeField] GameObject logInCanvas;
[SerializeField] GameObject createCanvas;
[SerializeField] GameObject joinCanvas;
[SerializeField] string sceneToLoad;
[SerializeField] public bool createRoomStatus = false;
[SerializeField] public bool joinRoomStatus = false;
[SerializeField] public bool logInStatus = false;
public override void OnConnectedToMaster()
{
Debug.Log("Connected to master server");
PhotonNetwork.JoinLobby();
}
public override void OnCreatedRoom()
{
Debug.Log("Created room: " + PhotonNetwork.CurrentRoom.Name);
}
void Start()
{
Debug.Log(" started");
}
public void LogIn()
{
StartCoroutine(waitSeconds());
string temp = nameField.text;
PhotonNetwork.LocalPlayer.NickName = temp;
PhotonNetwork.ConnectUsingSettings();
logInCanvas.SetActive(false);
createJoinCanvas.SetActive(true);
logInStatus = true;
Debug.Log("LogIn Done");
}
public void CreateRoom()
{
StartCoroutine(waitSeconds());
string roomName = roomNameField.text;
PhotonNetwork.CreateRoom(roomName);
createCanvas.SetActive(false);
ChangeScene(sceneToLoad);
createRoomStatus = true;
Debug.Log(PhotonNetwork.LocalPlayer.NickName + " joined " + roomName);
}
public void JoinRoom()
{
StartCoroutine(waitSeconds());
string tempRoomName = joinRoomField.text;
PhotonNetwork.JoinRoom(tempRoomName);
joinCanvas.SetActive(false);
ChangeScene(sceneToLoad);
joinRoomStatus = true;
Debug.Log(PhotonNetwork.LocalPlayer.NickName + " joined " + tempRoomName);
}
public void ChangeScene(string sceneName)
{
StartCoroutine(waitSeconds());
PhotonNetwork.LoadLevel(sceneName);
}
public IEnumerator waitSeconds()
{
yield return new WaitForSeconds(2.5f);
}
}
其他场景有Instantiate player实例化球员,但每当我运行应用程序的球员没有产生,即使它有光子视图组件附加到它。下面是实例化player的脚本。
using UnityEngine;
using Photon.Pun;
using System.Collections;
public class Instantiate_Player : MonoBehaviour
{
[SerializeField] GameObject playerPrefab;
[SerializeField] float xMin;
[SerializeField] float zMin;
[SerializeField] float xMax;
[SerializeField] float zMax;
void Start()
{
StartCoroutine(waitSeconds());
if (PhotonNetwork.IsConnectedAndReady)
{
Vector3 playerPos = new Vector3(Random.Range(xMin, xMax), 0.0f, Random.Range(zMin, zMax));
GameObject obj = PhotonNetwork.Instantiate(playerPrefab.name, playerPos, Quaternion.identity, 1, null);
obj.SetActive(true);
}
}
public IEnumerator waitSeconds()
{
yield return new WaitForSeconds(1.5f);
}
}
有什么问题吗??,玩家有附属于它的移动脚本,相机是它的子元素。
注意你的协程waitSeconds
做…绝对没有!
使用StartCoroutine
时不延迟调用它的代码!
你可以在时间过去后给它一个回调,例如
public class Photon_Manager : MonoBehaviourPunCallbacks
{
...
public void LogIn()
{
// You can directly pass in a lambda expression
StartCoroutine(waitSeconds(() =>
{
string temp = nameField.text;
PhotonNetwork.LocalPlayer.NickName = temp;
PhotonNetwork.ConnectUsingSettings();
logInCanvas.SetActive(false);
createJoinCanvas.SetActive(true);
logInStatus = true;
Debug.Log("LogIn Done");
});
}
public void CreateRoom()
{
// or as demo pass in an explicit method
StartCoroutine(waitSeconds(CreateRoomDelayed);
}
private void CreateRoomDelayed()
{
string roomName = roomNameField.text;
PhotonNetwork.CreateRoom(roomName);
createCanvas.SetActive(false);
ChangeScene(sceneToLoad);
createRoomStatus = true;
Debug.Log(PhotonNetwork.LocalPlayer.NickName + " joined " + roomName);
}
...
private IEnumerator waitSeconds(Action whenDone)
{
yield return new WaitForSeconds(2.5f);
whenDone?.Invoke();
}
}
虽然从用户的角度来看,这似乎很奇怪,我必须等待2.5秒(这很长),以获得一个反应,例如点击登录。
也可以使Start
返回IEnumerator
本身。在这种情况下,Unity会自动将其作为协程运行:
public class Instantiate_Player : MonoBehaviour
{
...
IEnumerator Start()
{
yield return new WaitForSeconds(1.5f);
if (PhotonNetwork.IsConnectedAndReady)
{
Vector3 playerPos = new Vector3(Random.Range(xMin, xMax), 0.0f, Random.Range(zMin, zMax));
GameObject obj = PhotonNetwork.Instantiate(playerPrefab.name, playerPos, Quaternion.identity, 1, null);
obj.SetActive(true);
}
}
}
一般来说:
基于固定时间的等待总是肮脏且容易出错。可以等到你真正连接上了:
IEnumerator Start()
{
yield return new WaitUntil(() => PhotonNetwork.IsConnectedAndReady);
Vector3 playerPos = new Vector3(Random.Range(xMin, xMax), 0.0f, Random.Range(zMin, zMax));
GameObject obj = PhotonNetwork.Instantiate(playerPrefab.name, playerPos, Quaternion.identity, 1, null);
obj.SetActive(true);
}