Unity3d实现双人网络坦克大战

效果预览

https://pan.baidu.com/s/1w3RccGs7FueDopwZTaPrpA#list/path=%2F

资源准备

所需要的资源和上周的AI自动寻路一样: 使用NavMesh实现坦克大战游戏

过程

  1. 创建一个空对象,并命名为NetworkManager, 并添加NetWorkManager组件和NetWorkManagerHUD组件这里写图片描述

  2. 给坦克,子弹添加NetWorkIdentity组件和NetWorkTransform组件
    坦克
    这里写图片描述
    子弹
    这里写图片描述

  3. 将子弹和坦克注册到NetworkManager的NetWorkManaer组件中这里写图片描述

  4. 制作血条:分别是自己的血条和敌人的血条这里写图片描述
    这里还需要给血条加上PlayerHeath和EnemyHealth tag

代码部分

有很大问题的工厂模式和单例模式:(不要问我为什么有问题还要用,因为我懒,不想再写其他的了)
Factory.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Factory : MonoBehaviour {
    public GameObject bullet;
    public ParticleSystem bulletPs;
    public ParticleSystem tankPs;
    // Use this for initialization
    private Queue<GameObject> bullets = new Queue<GameObject>();
    private List<ParticleSystem> bulletPses = new List<ParticleSystem>();
    private List<ParticleSystem> tankPses = new List<ParticleSystem>();
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
    public GameObject GetBullet()
    {
        GameObject b = null;
        Debug.Log(bullets.Count);
        if (bullets.Count == 0)
        {
            b = Instantiate<GameObject>(bullet);
            return b;
        }
        b = bullets.Dequeue();
        return b;
    }

    public void RecycleBullet(GameObject b)
    {
        b.SetActive(false);
        bullets.Enqueue(b);
    }

    public ParticleSystem GetBulletPs()
    {
        for (int i = 0; i < bulletPses.Count; ++i)
        {
            if (!bulletPses[i].isPlaying)
            {
                return bulletPses[i];
            }
        }
        ParticleSystem p = Instantiate<ParticleSystem>(bulletPs);
        bulletPses.Add(p);
        return p;
    }
    public ParticleSystem GetTankPs()
    {
        for (int i = 0; i < tankPses.Count; ++i)
        {
            if (!tankPses[i].isPlaying)
            {
                return tankPses[i];
            }
        }
        ParticleSystem p = Instantiate<ParticleSystem>(tankPs);
        tankPses.Add(p);
        return p;
    }
}

Singleton.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    protected static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = (T)FindObjectOfType(typeof(T));
                if (instance == null)
                {
                    Debug.LogError("An instance of " + typeof(T) + " is needed in the scene, but there is none.");
                }
            }
            return instance;
        }
    }
}

玩家移动和发射子弹代码
Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class Player : NetworkBehaviour {
    public float moveSpeed = 10.0f;     //玩家移动速度
    public float rotateSpeed = 60.0f;   //玩家旋转速度
    public GameObject BustedTank;
    private bool isDead = false;
    public override void OnStartLocalPlayer()
    {
        transform.position = new Vector3(Random.Range(0, 10), 0, -5);

    }
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        if(isDead)
        {
            return;
        }
        if(GetComponent<Health>().health <= 0)
        {
            ParticleSystem boom = Singleton<Factory>.Instance.GetTankPs();
            boom.transform.position = transform.position;
            boom.Play();
            this.gameObject.SetActive(false);
            GameObject b = Instantiate<GameObject>(BustedTank);
            b.transform.position = transform.position;
            isDead = true;
        }
        if (!isLocalPlayer)
        {
            return;
        }
        Camera.main.transform.position = new Vector3(transform.position.x, 15, transform.position.z);
        if(Input.GetKeyDown(KeyCode.Space))
        {
            Cmdfire();
        }
        move();
    }
    public void move()
    {
        float h = Input.GetAxisRaw("Horizontal");   //获取玩家水平轴上的输入
        float v = Input.GetAxisRaw("Vertical"); //获取玩家在垂直方向的输入
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime * v);
        //v<0表示获取玩家向后的输入,玩家以moveSpeed的速度向后运动
        transform.Rotate(Vector3.up * h * rotateSpeed * Time.deltaTime);
    }
    [Command]
    public void Cmdfire()
    {
            GameObject b = Singleton<Factory>.Instance.GetBullet();
            b.transform.position = new Vector3(transform.position.x, 1.5f, transform.position.z) + transform.forward * 1.5f;
            b.transform.forward = transform.forward;//设置子弹方向
            Rigidbody rb = b.GetComponent<Rigidbody>();
            b.GetComponent<Rigidbody>().velocity = transform.forward * 20;//发射子弹
            NetworkServer.Spawn(b);
    }
}

玩家生命值代码
Health.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;

public class Health : NetworkBehaviour {

    // Use this for initialization

    void Start () {

    }

    // Update is called once per frame

    public const int maxHealth = 100;
    [SyncVar (hook = "onHealthChange")] //检测生命值的代码,用来改变血条
    public int health = maxHealth;

    public void TakeDamage(int amount)
    {

        if(!isServer)
        {
            return;
        }

        health -= amount;

    }

    void onHealthChange(int health)
    {

        //Debug.Log("=====");
        this.health = health;
        if(isLocalPlayer)
        {

            GameObject.FindWithTag("PlayerHealth").GetComponent<Slider>().value = health;
        }
        else
        {
            GameObject.FindWithTag("EnemyHealth").GetComponent<Slider>().value = health;
        }
    }
}

Bullte.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour {
    public int type; // 0 表示player的子弹, 1 表示enemy的子弹
                     // Use this for initialization
    public int enemyHealth;
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
    void OnCollisionEnter(Collision collision)
    {


        if (collision.gameObject.tag == "Player")
        {
           collision.gameObject.GetComponent<Health>().TakeDamage(10);
        }

        ParticleSystem boom = Singleton<Factory>.Instance.GetBulletPs();
        boom.transform.position = transform.position;
        boom.Play();
        if (this.gameObject.activeSelf)
        {
            Singleton<Factory>.Instance.RecycleBullet(this.gameObject);
        }
    }

}

其实这个游戏大部分代码都是借鉴潘老师的课件的,而且还有一些Bug未解决

猜你喜欢

转载自blog.csdn.net/qq_36297981/article/details/80822299