简而言之,我有一个非常简单的多人游戏。它是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;
}
}
我觉得非常奇怪,因为你可以清楚地看到,NetworkManager对象上没有NetworkIdentity组件。我现在在过去的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;
}
非常感谢大家帮助我!这对我来说已经过了一天。