星际之旅 2019-06-27
视频地址
GITHUB地址


第一步是在项目中创建 NetworkManager 对象:
将场记挂载到网络空对象上创建游戏场景:
public class FirstSceneController : MonoBehaviour {
// Use this for initialization
void Start () {
Instantiate(Resources.Load<GameObject>("Prefabs/Plane"), new Vector3(0, -0.5f, 0), Quaternion.identity);
}
// Update is called once per frame
void Update()
{
}
}设置玩家对象预制

联网玩家对象的运动

* 编写 PlayerMove 脚本,使玩家的移动被联网同步:
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class PlayerMove : NetworkBehaviour
{
public GameObject bulletPrefab;
private Camera myCamera;
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer>().material.color = Color.red;
GetComponent<Rigidbody>().freezeRotation = true;
myCamera = Camera.main;
}
void Update()
{
if (!isLocalPlayer)
return;
var x = Input.GetAxis("Horizontal");
var z = Input.GetAxis("Vertical") * 0.1f;
//移动和旋转
transform.Translate(0, 0, z * 0.7f);
transform.Rotate(0, x, 0);
myCamera.transform.position = transform.position + transform.forward * -3 + new Vector3(0, 4, 0);
myCamera.transform.forward = transform.forward + new Vector3(0, -0.5f, 0);
if (Input.GetKeyDown(KeyCode.Space))
{
CmdFire();
}
//防止碰撞发生后的旋转
if (this.gameObject.transform.localEulerAngles.x != 0 || gameObject.transform.localEulerAngles.z != 0)
{
gameObject.transform.localEulerAngles = new Vector3(0, gameObject.transform.localEulerAngles.y, 0);
}
if (gameObject.transform.position.y != 0)
{
gameObject.transform.position = new Vector3(gameObject.transform.position.x, 0, gameObject.transform.position.z);
}
}
[Command]
void CmdFire()
{
// This [Command] code is run on the server!
// create the bullet object locally
var bullet = (GameObject)Instantiate(
bulletPrefab,
new Vector3((transform.position + transform.forward).x,0.2f,(transform.position + transform.forward).z),
Quaternion.identity);
bullet.GetComponent<Rigidbody>().velocity = transform.forward * 4;
// spawn the bullet on the clients
NetworkServer.Spawn(bullet);
// when the bullet is destroyed on the server it will automaticaly be destroyed on clients
Destroy(bullet, 3.0f);
}
}
```联网子弹。创建一个球体的子弹元素,添加rigibody和球状碰撞组件添加进Spawn Info中的注册预制目录中:

public class Bullet : MonoBehaviour {
void OnCollisionEnter(Collision collision)
{
var hit = collision.gameObject;
var hitCombat = hit.GetComponent<Combat>();
if (hitCombat != null)
{
hitCombat.TakeDamage(10);
Destroy(gameObject);
}
else
{
Destroy(gameObject);
}
}
}实现第三人称视角时,一开始想的办法是将摄像机绑定为游戏对象的子元素。但是在联机时,由于摄像机优先级相同优先渲染后加载的,所有视角会切换到后进入的人身上。所有只能采用移动摄像机,使摄像机永远在第三人称的固定位置跟随的方式解决。
//添加到PlayerMove脚本中的相应部分
public override void OnStartLocalPlayer(){
private Camera myCamera;
public override void OnStartLocalPlayer()
{
myCamera = Camera.main;
}
void Update()
{
myCamera.transform.position = transform.position + transform.forward * -3 + new Vector3(0, 4, 0);
myCamera.transform.forward = transform.forward + new Vector3(0, -0.5f, 0);
}
}