效果预览
https://pan.baidu.com/s/1w3RccGs7FueDopwZTaPrpA#list/path=%2F
资源准备
所需要的资源和上周的AI自动寻路一样: 使用NavMesh实现坦克大战游戏
过程
创建一个空对象,并命名为NetworkManager, 并添加NetWorkManager组件和NetWorkManagerHUD组件
给坦克,子弹添加NetWorkIdentity组件和NetWorkTransform组件
坦克
子弹
将子弹和坦克注册到NetworkManager的NetWorkManaer组件中
- 制作血条:分别是自己的血条和敌人的血条
这里还需要给血条加上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未解决