网络游戏制作---坦克大战(3)
一、发射子弹
这一部分实现玩家控制自己坦克发射子弹,而其他玩家保持不动。
主要的思想使用RPC:
1、首先为发射炮弹脚本添加PhotonView组件
2、如果是本地组件,直接调用Fire()函数
3、调用远程玩家的RPC的Fire()函数,来实现远程玩家的设计效果,进而实现同步。
代码如下:
//初始化PhotonView组件变量 private PhotonView pv = null; //向pv变量分配PhotonView组件 pv = GetComponent<PhotonView>(); void Update() { //如果PhotonView是自己本地的组件,则点击鼠标左键时执行发射逻辑 if (pv.isMine&&Input.GetMouseButtonDown(0)) { //如果是自己本地的坦克,则调用本地函数并发射炮弹 Fire(); //调用远程玩家客户端的RPC函数Fire函数 pv.RPC("Fire", PhotonTargets.Others, null); } } [PunRPC] void Fire() { //播放炮弹发射的声音 sfx.PlayOneShot(fireSfx, 1.0f); Instantiate(cannon, firePos.position, firePos.rotation); }
完整的FireCannon代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FireCannon : MonoBehaviour { //炮弹预设 private GameObject cannon = null; //炮弹发射声音 private AudioClip fireSfx = null; //AudioSource组件 private AudioSource sfx = null; //炮弹发射初始点 public Transform firePos; //初始化PhotonView组件变量 private PhotonView pv = null; void Awake() { //加载Resources文件夹中的Cannon预设 cannon = (GameObject)Resources.Load("Cannon"); //从Resources文件夹中加载炮弹声音文件 fireSfx = Resources.Load<AudioClip>("CannonFire"); //声明AudioSource变量 sfx = GetComponent<AudioSource>(); //向pv变量分配PhotonView组件 pv = GetComponent<PhotonView>(); } // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { //如果PhotonView是自己本地的组件,则点击鼠标左键时执行发射逻辑 if (pv.isMine&&Input.GetMouseButtonDown(0)) { //如果是自己本地的坦克,则调用本地函数并发射炮弹 Fire(); //调用远程玩家客户端的RPC函数Fire函数 pv.RPC("Fire", PhotonTargets.Others, null); } } [PunRPC] void Fire() { //播放炮弹发射的声音 sfx.PlayOneShot(fireSfx, 1.0f); Instantiate(cannon, firePos.position, firePos.rotation); } }
二、坦克被击中时的处理及复活
1、设置坦克MeshRenderer组件变量、爆炸预设、生命值变量
//为实现坦克爆炸后的透明处理,声明MeshRenderer组件数组变量 private MeshRenderer[] renderers; //坦克爆炸效果预设 private GameObject expEffect = null; //坦克初始生命值 private int initHp = 100; private int currHp = 0;
2、获取MeshRenderer组件、加载爆炸效果
void Awake() { //获取坦克的MeshRenderer组件 renderers = GetComponentsInChildren<MeshRenderer>(); //将当前生命值更改为初始生命值 currHp = initHp; //加载坦克爆炸时需要生成的爆炸效果 expEffect = Resources.Load<GameObject>("Med Explosion"); }
3、检测碰撞
void OnTriggerEnter(Collider coll) { //根据tag判断碰撞的是否为炮弹 if (currHp > 0 && coll.GetComponent<Collider>().tag == "CANNON") { currHp -= 20; } if (currHp <= 0) { StartCoroutine(this.ExplosionTank()); } }
4、使用协程函数实现生成爆炸效果
//生成爆炸效果并处理坦克的复活 IEnumerator ExplosionTank() { //生成爆炸效果 Object effect = GameObject.Instantiate(expEffect, transform.position, Quaternion.identity); Destroy(effect, 3.0f); //透明处理坦克 SetTankVisible(false); //等待3秒 yield return new WaitForSeconds(3.0f); //复活时设置初始生命值 currHp = initHp; //使坦克再次可见 SetTankVisible(true); }
完整代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TankDamage : MonoBehaviour { //为实现坦克爆炸后的透明处理,声明MeshRenderer组件数组变量 private MeshRenderer[] renderers; //坦克爆炸效果预设 private GameObject expEffect = null; //坦克初始生命值 private int initHp = 100; private int currHp = 0; void Awake() { //获取坦克的MeshRenderer组件 renderers = GetComponentsInChildren<MeshRenderer>(); //将当前生命值更改为初始生命值 currHp = initHp; //加载坦克爆炸时需要生成的爆炸效果 expEffect = Resources.Load<GameObject>("Med Explosion"); } void OnTriggerEnter(Collider coll) { //根据tag判断碰撞的是否为炮弹 if (currHp > 0 && coll.GetComponent<Collider>().tag == "CANNON") { currHp -= 20; } if (currHp <= 0) { StartCoroutine(this.ExplosionTank()); } } //生成爆炸效果并处理坦克的复活 IEnumerator ExplosionTank() { //生成爆炸效果 Object effect = GameObject.Instantiate(expEffect, transform.position, Quaternion.identity); Destroy(effect, 3.0f); //透明处理坦克 SetTankVisible(false); //等待3秒 yield return new WaitForSeconds(3.0f); //复活时设置初始生命值 currHp = initHp; //使坦克再次可见 SetTankVisible(true); } //激活/禁用MeshRenderer函数 void SetTankVisible(bool isVisible) { foreach (MeshRenderer _renderer in renderers) { _renderer.enabled = isVisible; } } }
每次写点游戏都的偷偷摸摸,结果还是被老板逮住了,那个勉强的笑不知道意味着什么,就希望他能让我顺利毕业,别为难我,我没什么信仰,论文实在看不下去,唉,开组会又要被骂了,每次针对我,我就是个废铁,非要让我做王者的任务,我该怎么办,小伙子,要抗住啊!