网络游戏制作---坦克大战(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;
        }
    }
}

每次写点游戏都的偷偷摸摸,结果还是被老板逮住了,那个勉强的笑不知道意味着什么,就希望他能让我顺利毕业,别为难我,我没什么信仰,论文实在看不下去,唉,开组会又要被骂了,每次针对我,我就是个废铁,非要让我做王者的任务,我该怎么办,小伙子,要抗住啊!

原文地址:https://www.cnblogs.com/Optimism/p/11099263.html