接着上一篇博客,继续讲解Network的功能。本节讲,如何发射子弹,并且同步到各个客户端。
下来我们先做第一步,单机版如何生成子弹发射。
首先把在主角下制作一个Spawn用来做生成点。
然后做一个子弹命名为bullet,要给子弹加个Rigidbody组件,因为我们要使用这个方法让子弹飞。
接下开始写代码,如下:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class playernetwork : NetworkBehaviour
{
[SerializeField]
public Camera fpscamera;
public GameObject CUBE;
public GameObject Bulletprefab,Spawn;
// Use this for initialization
void Start()
{
if (isLocalPlayer)//只有本客户端的角色才会执行
{
GetComponent<CharacterController>().enabled = true;
GetComponent<UnityStandardAssets.Characters.FirstPerson.FirstPersonController>().enabled = true;
fpscamera.enabled = true;
}
}
void Update()
{
//不是本地角色就返回
if (isLocalPlayer == false)
{
return;
}
if (Input.GetKeyDown(KeyCode.K))
{
Debug.Log("FIRE");
Fire();
}
}
//生成子弹方法
void Fire()
{
GameObject bullets = Instantiate(Bulletprefab,Spawn.transform.position, Spawn.transform.rotation)as GameObject;
bullets.GetComponent<Rigidbody>().velocity=bullets.transform.forward*30f;
//两秒后销毁
Destroy(bullets,2);
}
/// <summary>
/// 这个方法只会在本地角色那里调用,当角色被创建的时候就被调用
/// </summary>
public override void OnStartLocalPlayer()
{
CUBE.GetComponent<MeshRenderer>().material.color = Color.blue;
}
}
接下来把对应的东西放到代码里对应的位置,如图:
这样按键盘K键就可以生成子弹,并且子弹向前飞走,在2秒后自动销毁。
--------------------------------------上面是单机版生成子弹方法,下面讲如何在network里实现同步功能----------------------------------------------------------------------------------------------------------------------------------------------------
首先要明白,生成子弹的地方肯定是服务器,而客户端只是去看到。
子弹要同步飞行,那必须要添加上network Identity 和 network Transform组件,同时设置如下图:
这里解释一下设置:sync Rigidbody 3D是为了同步刚体进行子弹飞行。network send rate 是指要同步的频率,这里子弹只要同步一次能够飞行就可以了所以设置为0,表示同步速率就一次。
既然要在服务器生成,那必然要在networkmanager里添加上子弹的prefab,如图:
注意:要在networkmanager里添加的物体身上必须有network Identity组件(此处bullet已经添加过)。
接下来就是对代码的改动了,如下:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class playernetwork : NetworkBehaviour
{
[SerializeField]
public Camera fpscamera;
public GameObject CUBE;
public GameObject Bulletprefab, Spawns;
// Use this for initialization
void Start()
{
if (isLocalPlayer)//只有本客户端的角色才会执行
{
GetComponent<CharacterController>().enabled = true;
GetComponent<UnityStandardAssets.Characters.FirstPerson.FirstPersonController>().enabled = true;
fpscamera.enabled = true;
}
}
void Update()
{
//不是本地角色就返回
if (isLocalPlayer == false)
{
return;
}
if (Input.GetKeyDown(KeyCode.K))
{
Debug.Log("FIRE");
CmdFire();
}
}
//生成子弹方法 ---加上了command后,此方法虽然写在了客户端代码里,但在服务端运行;而且方法名必须以Cmd开头!!!
[Command]
void CmdFire()
{
GameObject bullets = Instantiate(Bulletprefab, Spawns.transform.position, Spawns.transform.rotation) as GameObject;
bullets.GetComponent<Rigidbody>().velocity = bullets.transform.forward * 30f;
//两秒后销毁
Destroy(bullets, 2);
//服务器把生成的子弹同步到全部客户端
NetworkServer.Spawn(bullets);
}
/// <summary>
/// 这个方法只会在本地角色那里调用,当角色被创建的时候就被调用
/// </summary>
public override void OnStartLocalPlayer()
{
CUBE.GetComponent<MeshRenderer>().material.color = Color.blue;
}
}
这里来解释一下command 方法。在一个方法上面加上了[command]后,表示此方法虽然写在了客户端代码里,但会在服务端运行而不是在客户端运行;而且方法名必须以Cmd开头,所以把之前的Fire修改为了CmdFire。
NetworkServer.Spawn(bullets);这个是network里的一个方法,表示服务器把生成的子弹同步到全部客户端。否则此处,客户端是看不到有子弹生成的。
这样就完成了所有的功能了。运行效果如下(一个客户端,一个服务器端):