如何将相机连接到HLAPI网络管理器实例化的播放器对象?

时间:2016-03-28 12:00:18

标签: c# unity3d

简而言之,我有一个非常简单的多人游戏。它是Roll A Ball游戏(Unity3D教程)。所以现在我让球员等完美地产生,每个人都能完美控制自己的球。

但问题是:我有一个默认的主摄像头。由于它只是本地玩家本身需要看到它,我认为在服务器上为每个玩家生成一个单独的摄像头没有意义。

然而,为了使相机跟随播放器,我需要将它附加到播放器游戏对象。显然我无法将它附加到播放器预制件上,因为它是相机需要遵循的克隆。但是,由于播放器是由网络管理器组件生成的,我不知道如何引用此克隆。

我自己尝试过的事情:

public class CameraController : NetworkManager
{

    public GameObject playerPrefab;
    public Transform target;

    private Vector3 offset;

    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
        GameObject player = (GameObject)Instantiate(playerPrefab, new Vector3(0, 0.5f, 0), Quaternion.identity);
        target = player.transform;
        NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    }

    void Start()
    {
        offset = transform.position - target.position;
    }

    void LateUpdate()
    {
        transform.position = transform.position + offset;
    }
}

但这导致: Screenshot of Error

我觉得非常奇怪,因为你可以清楚地看到,NetworkManager对象上没有NetworkIdentity组件。我现在在过去的4个小时里一直在尝试很多事情而且我无法做到。所以现在我希望你们可以帮助我。

编辑:这就是网络管理器正常生成播放器的方式。正如您所看到的,它没有代码:

Network manager player spawn

4 个答案:

答案 0 :(得分:7)

我有同样的问题,并找出了followig解决方案。好像你已经有了一个解决方案,但也许有趣的是,在同样的情况下为其他人分享一些可能的方法。

这是一种没有将相机连接到预制件上的方法。

我正在使用NetworkManager来实例化Player-prefabs。 (和你一样)

通过让克隆告诉摄像机,他们是谁(或者哪个变换属于他们),我解决了找到克隆对象引用的问题。

播放器具有以下脚本:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class PlayerController : NetworkBehaviour {



public override void OnStartLocalPlayer()
{
    GetComponent<MeshRenderer>().material.color = Color.blue;
    Camera.main.GetComponent<CameraFollow>().target=transform; //Fix camera on "me"

}

void Update ()
{
    if (!isLocalPlayer) 
    {
        return;
    }
    var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
    var z = Input.GetAxis ("Vertical") * Time.deltaTime * 3.0f;

    transform.Rotate (0, x, 0);
    transform.Translate (0,0,z);

}
}

在我的默认主摄像头上(没有摄像头连接到播放器预制件,只有默认摄像头)我将以下脚本打开。它需要一个目标,我使用检查员使用预制件初始化。

using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour {

public Transform target; //what to follow
public float smoothing = 5f; //camera speed

Vector3 offset;

void Start()
{
    offset = transform.position - target.position;
}

void FixedUpdate()
{
    Vector3 targetCamPos = target.position + offset;
    transform.position = Vector3.Lerp (transform.position,  targetCamPos,smoothing * Time.deltaTime);
}
}

在开始游戏后,每个克隆都告诉摄像机他是谁,所以目标会通过播放器脚本中的这一行更改为各个客户克隆:

Camera.main.GetComponent<CameraFollow>().target=transform; //Fix camera on "me"

这样您就不需要为每个播放器预制件实例创建一个摄像头(我不确定这是否会在性能上产生很大差异)并且您不必停用所有不属于的摄像头你的客户。

如果你在编辑器中托管游戏,你可以看到每个连接的客户端只有一个摄像头而不是一个摄像头(比如当你将它连接到预制件上时)。

我认为这是一个很好的使用这个方法,你可以使用它来放置它,它应该只应用于本地播放器。

public override void OnStartLocalPlayer()
{ 
}

我尝试在编辑器和构建中启动游戏,但它似乎运行良好。

答案 1 :(得分:3)

我会在预制件上添加一个摄像头,然后编写一个像这样的播放器脚本:

using UnityEngine.Networking;

public class Player : NetworkBehaviour
{
    public Camera camera;

    void Awake()
    {
        if(!isLocalPlayer)
        {
            camera.enabled = false;
        }
    }
}

答案 2 :(得分:2)

我并没有真正使用过网络,但是如果你在产生本地播放器后这样做会怎样呢

Camera.main.transfor.SetParent(the transform of the local player here);

据我所知,每个单独的游戏实例都有一个主摄像头。

答案 3 :(得分:2)

感谢Rafiwui指出正确的方向,我终于设法让它发挥作用。我所要做的就是熟练掌握他的代码。最终结果是:

public Camera camera;

void Awake()
{
    camera.enabled = false;
}

public override void OnStartLocalPlayer()
{
    camera.enabled = true;
}

非常感谢大家帮助我!这对我来说已经过了一天。