【问题标题】:Unity3D strange behavior of cameras in multiplayerUnity3D多人游戏中相机的奇怪行为
【发布时间】:2020-01-22 23:32:42
【问题描述】:

我刚接触统一,正在为我的相机的奇怪行为而苦苦挣扎。 我正在使用 Photon 插件编写在线多人游戏。

奇怪的行为:

  • Player1 登录

    --> 一切顺利

  • Player2 登录

    --> Player1 的 Camera 切换到 Player2 角色

    --> Player2的Camera切换到Player1角色​

  • Player3 登录

    --> Player 1 和 Player2 的相机切换到 Player3 角色

    --> Player3的Camera切换到Player2角色。​

(但移动控制对每个玩家都有效)

我有一个角色的预制件,它在检查器中安装了一个摄像头。

这是我的初始化代码:

public class NetworkPlayer  : Photon.Pun.MonoBehaviourPun, Photon.Pun.IPunObservable
{
    public Animator anim;
    private Vector3 correctPlayerPos;
    private Quaternion correctPlayerRot;
    public GameObject myCam;
    // Start is called before the first frame update
    void Start()
    {
        if(photonView.IsMine)
        {
            Debug.Log("PhotonView.IsMine == true");
            //Kamera und Steuerung aktivieren
            myCam = GameObject.Find("Camera");
            myCam.SetActive(true);
            GetComponent<PlayerMovement>().enabled = true;
            Debug.Log("Steuerung und Cam aktiviert...");
        }
    }

    // Update is called once per frame
    void Update()
    {
        if(!photonView.IsMine)
        {
            transform.position = Vector3.Lerp(transform.position, this.correctPlayerPos, Time.deltaTime*5);
            transform.rotation = Quaternion.Lerp(transform.rotation, this.correctPlayerRot, Time.deltaTime * 5);
        }
    }

    //Exchange Position data
    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info){
        if(stream.IsWriting)
        {
            //Send data to others
            stream.SendNext(transform.position);
            stream.SendNext(transform.rotation);
            stream.SendNext(anim.GetBool("Run"));
        } 
        else 
        {
            //Receive data from others
            this.correctPlayerPos = (Vector3) stream.ReceiveNext();
            this.correctPlayerRot = (Quaternion) stream.ReceiveNext();
            anim.SetBool("Run", (bool) stream.ReceiveNext());
        }
    }
}

我还尝试通过检查器而不是搜索它来连接相机,就像上面的代码示例一样。 希望任何人都可以帮助我:(

感谢您的宝贵时间!

【问题讨论】:

  • GameObject.Find 将在当前运行的场景中搜索与给定字符串匹配的名称。如果有多个同名的游戏对象,则它不是查找特定游戏对象的可靠方法。您可能想看看这是否是问题所在,在这种情况下,请以不同的方式找到您的相机。
  • 嗨,西蒙,感谢您的快速回答!我还尝试直接在 Inspector 中分​​配相机。但这并没有解决问题。
  • 在inspector中赋值是什么意思?
  • 我将变量 GameObject myCam 声明为 public 并将相机(附加到播放器预制件)拉到脚本(也附加到预制件)中。我还删除了 start 方法中的 GameObject.find 命令。

标签: unity3d camera multiplayer photon


【解决方案1】:

我的猜测是您在播放器上执行SetAtive(true),但从您的图片来看,无论如何相机似乎默认处于活动状态!因此,每个新相机都添加到 Hierachy 中先前相机的下方,这使其成为顶部渲染的相机。

您可以简单地在播放器预制件中禁用Camera

无论如何,您还应该在脚本中主动为其他玩家禁用相机,这样您就不会忘记/不必依赖将您的预制件设置为特定状态

public class NetworkPlayer  : Photon.Pun.MonoBehaviourPun, Photon.Pun.IPunObservable
{
    public Animator anim;
    // you are referncing this for the prefab via the inspector
    // I would also use the proper type as a safety
    // this way you can't by accident reference something else here but a Camera
    public Camera myCam;

    // you should also this already via the inspector
    public PlayerMovement playerMovement;

    private Vector3 correctPlayerPos;
    private Quaternion correctPlayerRot;

    // Use Awake to gather components and references as fallback
    // if they where not referenced via the Inspector
    private void Awake()
    {
        FetchComponents();
    } 

    // Fetches components only if they where not referenced via the Inspector
    // this saves unnecessary GetComponent calls which are quite expensive
    //
    // + personal pro tip: By using the context menu you can now also in the Inspector simply click on FetchComponents
    // This way you 
    //   a) don't have to search and drag them in manually
    //   b) can already see if it would also work later on runtime 
    [ContextMenu(nameof(FetchComponents))]
    private void FetchComponents()
    {
        if(!playerMovement) playerMovement = GetComponent<PlayerMovement>();
        if(!anim) anim = GetComponent<Animator>();
        // Use GetComponnetInChildren to retrieve the component on yourself
        // or recursive any of your children!
        // Pass true in order to also get disabled or inactive ones
        if(!myCam) myCam = GetComponentInChildren<Camera>(true);
    }       

    // Now do your thing not only for the player but also actively disable the stuff
    // on all other players
    private void Start()
    {
        var isMine = photonView.IsMine;
        Debug.Log($"PhotonView.IsMine == {isMine}");
        // enable the cam for you, disable them for others!
        myCam.gameObject.SetActive(isMine);
        // enable controls for you, disable them for others
        playerMovement.enabled = isMine;

        Debug.Log($"Steuerung und Cam {isMine ? "" : "de"}aktiviert...");
    }

    ...
}

【讨论】:

  • 嘿derHugo!这解决了我的问题!我忘了禁用预制件中的相机!非常感谢!
  • @Sagíchdirnet 很高兴为您提供帮助!请随时将答案标记为例外。我仍然建议在这里也使用该脚本,这样您就不必依赖您的预制设置,而是在运行时通过脚本主动应用一个。这将避免将来出现此类“错误”;)
猜你喜欢
  • 2016-07-20
  • 2012-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多