接着上一篇博客,继续讲解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里的一个方法,表示服务器把生成的子弹同步到全部客户端。否则此处,客户端是看不到有子弹生成的。
这样就完成了所有的功能了。运行效果如下(一个客户端,一个服务器端):