You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity 3D用PUN2开发VR多人Demo实例化Avatar遇阻求助

我明白你的困惑——很多教程会默认你已经掌握了Photon的基础网络配置逻辑,所以跳过了创建核心网络管理脚本的关键步骤。别担心,我帮你一步步梳理清楚,从搭建基础网络框架到成功实例化Avatar:

解决步骤:从创建基础网络管理脚本到实例化Avatar

1. 自定义Photon网络管理脚本(替代缺失的Network Manager)

你需要自己写一个基础的网络管理脚本,它负责连接Photon服务器、加入房间,以及触发Avatar实例化的逻辑。

创建一个新的C#脚本,命名为PhotonNetworkManager,替换里面的代码为:

using Photon.Pun;
using Photon.Realtime;
using UnityEngine;

public class PhotonNetworkManager : MonoBehaviourPunCallbacks
{
    // 自定义房间名称,确保两名玩家加入同一个房间
    [SerializeField] private string _roomName = "VRDemoRoom";
    // Resources文件夹下LocalAvatar预制体的相对路径(比如直接在Resources根目录的话就是"LocalAvatar")
    [SerializeField] private string _localAvatarPath = "LocalAvatar";
    // 可选:设置Avatar的出生点(没有的话就用默认位置)
    [SerializeField] private Transform _avatarSpawnPoint;

    void Start()
    {
        // 初始化Photon连接,使用你配置的ServerSettings
        PhotonNetwork.ConnectUsingSettings();
    }

    // 成功连接到Photon主服务器后的回调
    public override void OnConnectedToMaster()
    {
        Debug.Log("已连接到Photon主服务器,尝试加入房间...");
        // 加入现有房间,没有则创建新房间,限制最大玩家数为2
        PhotonNetwork.JoinOrCreateRoom(_roomName, new RoomOptions { MaxPlayers = 2 }, null);
    }

    // **关键:成功加入房间后的回调,就是教程提到的实例化Avatar的地方**
    public override void OnJoinedRoom()
    {
        Debug.Log("成功加入房间,开始实例化本地Avatar...");
        
        // 获取出生位置(如果没设置Spawn点,就用Vector3.zero)
        Vector3 spawnPos = _avatarSpawnPoint != null ? _avatarSpawnPoint.position : Vector3.zero;
        Quaternion spawnRot = _avatarSpawnPoint != null ? _avatarSpawnPoint.rotation : Quaternion.identity;

        // 必须用PhotonNetwork.Instantiate而非普通Instantiate!
        // 这个方法会自动将Avatar同步给房间内的其他玩家,远程玩家会自动创建对应的RemoteAvatar实例
        GameObject localAvatar = PhotonNetwork.Instantiate(
            _localAvatarPath,
            spawnPos,
            spawnRot
        );

        // 可选:将VR相机绑定到Avatar的头部节点(根据你的Avatar结构调整路径)
        // Camera.main.transform.SetParent(localAvatar.transform.Find("Head"));
        // Camera.main.transform.localPosition = Vector3.zero;
        // Camera.main.transform.localRotation = Quaternion.identity;
    }

    // 可选:调试用,监听其他玩家加入事件
    public override void OnPlayerEnteredRoom(Player newPlayer)
    {
        Debug.Log($"玩家 {newPlayer.NickName} 加入了房间");
    }
}

2. 场景与组件配置

  • 在场景中创建一个空物体,命名为NetworkManager,将上面的PhotonNetworkManager脚本挂载到它上面。
  • 检查PhotonServerSettings:确保已填入从Photon Dashboard获取的App ID,设置合适的Region(比如亚洲选"asia"),并勾选AutoSyncScene
  • 确认LocalAvatarRemoteAvatar预制体都在Resources文件夹下,且:
    • 都挂载了PhotonView组件(View ID保持默认的0,Photon会自动分配唯一ID)
    • 都挂载了你之前创建的PhotonAvatarView组件,并且配置好同步属性(比如位置、旋转、VR控制器输入等)

3. 你可能遗漏的关键细节

  • 必须用PhotonNetwork.Instantiate:普通的Instantiate只会在本地创建物体,其他玩家完全看不到。PhotonNetwork.Instantiate会自动处理网络同步,远程玩家的客户端会自动生成对应的RemoteAvatar实例,不需要你手动写代码实例化远程Avatar。
  • PhotonAvatarView的权限区分:在这个脚本里要明确区分本地和远程玩家的逻辑,比如:
    // 在PhotonAvatarView的Update方法中
    void Update()
    {
        if (photonView.IsMine)
        {
            // 本地玩家:读取VR输入,更新Avatar的位置/旋转
            UpdateLocalAvatar();
        }
        else
        {
            // 远程玩家:同步Photon传来的位置/旋转数据
            SyncRemoteAvatar();
        }
    }
    
  • 测试方式:需要同时运行两个客户端(比如Unity编辑器运行一个,Build出EXE运行另一个),确保两者都连接到同一个房间,这样才能看到彼此的Avatar。

4. 常见问题排查

  • 如果连接失败:检查PhotonServerSettings的App ID是否正确,网络是否正常,Region是否选对。
  • 如果Avatar没实例化:查看Console报错信息,比如是否找不到预制体(检查_localAvatarPath是否和Resources下的路径一致),或者OnJoinedRoom回调没触发(确认脚本继承了MonoBehaviourPunCallbacks,且PhotonNetwork.ConnectUsingSettings()已执行)。
  • 如果远程玩家看不到Avatar:确保PhotonView组件已正确挂载,且PhotonNetwork.Instantiate使用的是正确的预制体路径。

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

火山引擎 最新活动