AI坦克建模

  • 感知
    在游戏中,程序是可以获得游戏世界任意信息的,设计一个杀死玩家的算法通常是比较容易的,因此如何限制信息获取是设计不同级别 agent 的核心问题。在AI坦克大战的游戏中,AI坦克获取的信息是通过视觉(Vision)得到的。每个AI坦克获取的信息是导航信息,但是因为有障碍物的阻挡,使得AI坦克不会“一窝蜂”的同时涌向玩家。同时,AI坦克并不能实时瞄准玩家,也增加了游戏的可玩性。

  • 思考
    主要使用了Unity自带的寻路组件Navigation 进行“思考”寻路。

  • 行动
    每个AI坦克都会发射子弹,但是不能让AI坦克一直发射子弹,这样就没得玩了。所以会有一个子弹的准备时间,每间隔一段时间再发射子弹。同时地形凹凸不平,也会使得子弹的轨迹有所偏差。

游戏实现

1. 下载资源

Assets Store下载tanks tutorial资源

2.动作状态机

3. 制作地图


将想要的颜色所对应的材质拖到地图上

最终地图为

4. 制作子弹


Bullet

实现了子弹的相关设计,设置了子弹的爆炸范围,对于玩家和敌方坦克,子弹会有不同的伤害

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 子弹设置 √
public class Bullet : MonoBehaviour {// 设置爆炸范围public float range = 3.0f;private TankType tankType;// 设置坦克的类型public void setTankType (TankType type) {tankType = type;}// 设置碰撞事件private void OnCollisionEnter (Collision collision) {// 打到自己不算if (collision.transform.gameObject.tag == "Enemy" && this.tankType == TankType.ENEMY ||collision.transform.gameObject.tag == "Player" && this.tankType == TankType.PLAYER)return;Factory factory = Singleton<Factory>.Instance;ParticleSystem explosion = factory.getParticleSystem ();explosion.transform.position = gameObject.transform.position;// 爆炸范围内的所有物体都受到伤害Collider[] colliders = Physics.OverlapSphere (gameObject.transform.position, range);foreach (var collider in colliders) {// 设置范围伤害float dis = Vector3.Distance (collider.transform.position, gameObject.transform.position);float damage;// 玩家和敌人设置不同的伤害if (collider.tag == "Enemy" && this.tankType == TankType.PLAYER) {damage = 50.0f / dis;collider.GetComponent<Tank> ().setHP (collider.GetComponent<Tank> ().getHP () - damage);} else if (collider.tag == "Player" && this.tankType == TankType.ENEMY) {damage = 20.0f / dis;collider.GetComponent<Tank> ().setHP (collider.GetComponent<Tank> ().getHP () - damage);}explosion.Play ();}if (gameObject.activeSelf) factory.recycleBullet (gameObject);}
}
5.制作玩家



Player

实现了玩家的设计,设置了一个代理事件,主要控制玩家坦克被销毁;设置了玩家坦克初始的生命值,当坦克的生命值低于0则被销毁;控制坦克的移动;控制坦克的左右转向

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 玩家设置 √
public class Player : Tank {// 玩家坦克被摧毁public delegate void DestroyPlayer ();public static event DestroyPlayer destroyEvent;// 设置初始生命值void Start () { setHP (100); }void Update () {if (getHP () <= 0) {this.gameObject.SetActive (false);destroyEvent ();}}// 前后方向移动public void moveForWard () {gameObject.GetComponent<Rigidbody> ().velocity = gameObject.transform.forward * 20;}public void moveBackWard () {gameObject.GetComponent<Rigidbody> ().velocity = gameObject.transform.forward * (-20);}// 实现左右转向public void turn (float turnX) {float x = gameObject.transform.localEulerAngles.x;float y = gameObject.transform.localEulerAngles.y + turnX * 2;gameObject.transform.localEulerAngles = new Vector3 (x, y, 0);}
}
6.制作敌方坦克


Enemy

实现了敌人坦克的设置。由于用到了工厂模式,所以在坦克被销毁的时候需要进行回收;并且实现了 AI 功能,启动了协程,控制坦克的运动和射击操作;在坦克看到玩家的时候会进行跟踪移动,然后在射程范围内进行攻击。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;// 敌人坦克设置 √
public class Enemy : Tank {// 敌人坦克被摧毁,进行回收public delegate void RecycleEnemy (GameObject enemy);public static event RecycleEnemy recycleEnemy;// 玩家位置private Vector3 playerPos;// 游戏是否结束private bool gameover;private void Start () {playerPos = GameDirector.getInstance ().currentSceneController.getPlayer ().transform.position;// 启动协程StartCoroutine (shoot ());}void Update () {playerPos = GameDirector.getInstance ().currentSceneController.getPlayer ().transform.position;gameover = GameDirector.getInstance ().currentSceneController.GameOver ();if (!gameover) {if (getHP () <= 0 && recycleEnemy != null) recycleEnemy (this.gameObject);else {// 向玩家移动NavMeshAgent agent = gameObject.GetComponent<NavMeshAgent> ();agent.SetDestination (playerPos);}} else {// 游戏结束后停止运动NavMeshAgent agent = gameObject.GetComponent<NavMeshAgent> ();agent.velocity = Vector3.zero;agent.ResetPath ();}}// 控制射击IEnumerator shoot () {while (!gameover) {for (float i = 1; i > 0; i -= Time.deltaTime) yield return 0;// 射程if (Vector3.Distance (playerPos, gameObject.transform.position) < 10) shoot (TankType.ENEMY);}}
}
7. Factory

实现了工厂模式,来生产和销毁坦克和子弹;主要设计了初始化游戏物体;生产坦克,生产子弹;回收坦克,回收子弹

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public enum TankType { PLAYER, ENEMY }// 工厂模式
public class Factory : MonoBehaviour {public GameObject player;public GameObject enemy;public GameObject bullet;public ParticleSystem explosion;private List<GameObject> usedTanks;private List<GameObject> freeTanks;private List<GameObject> usedBullets;private List<GameObject> freeBullets;private GameObject player_t;private List<ParticleSystem> particles;// 初始化private void Awake () {usedTanks = new List<GameObject> ();freeTanks = new List<GameObject> ();usedBullets = new List<GameObject> ();freeBullets = new List<GameObject> ();particles = new List<ParticleSystem> ();player_t = GameObject.Instantiate<GameObject> (player) as GameObject;player_t.SetActive (true);player_t.transform.position = Vector3.zero;}void Start () { Enemy.recycleEnemy += recycleEnemy; }// 获取玩家public GameObject getPlayer () {return player_t;}// 获取敌人public GameObject getEnemys () {GameObject newT = null;if (freeTanks.Count <= 0) {newT = GameObject.Instantiate<GameObject> (enemy) as GameObject;usedTanks.Add (newT);newT.transform.position = new Vector3 (Random.Range (-100, 100), 0, Random.Range (-100, 100));} else {newT = freeTanks[0];freeTanks.RemoveAt (0);usedTanks.Add (newT);}newT.SetActive (true);return newT;}// 获取子弹public GameObject getBullets (TankType type) {GameObject newBullet;if (freeBullets.Count <= 0) {newBullet = GameObject.Instantiate<GameObject> (bullet) as GameObject;usedBullets.Add (newBullet);newBullet.transform.position = new Vector3 (Random.Range (-100, 100), 0, Random.Range (-100, 100));} else {newBullet = freeBullets[0];freeBullets.RemoveAt (0);usedBullets.Add (newBullet);}newBullet.GetComponent<Bullet> ().setTankType (type);newBullet.SetActive (true);return newBullet;}// 获取粒子系统public ParticleSystem getParticleSystem () {foreach (var particle in particles){if (!particle.isPlaying) return particle;}ParticleSystem newT = GameObject.Instantiate<ParticleSystem> (explosion);particles.Add (newT);return newT;}// 回收坦克public void recycleEnemy (GameObject enemyTank) {usedTanks.Remove (enemyTank);freeTanks.Add (enemyTank);enemyTank.GetComponent<Rigidbody> ().velocity = Vector3.zero;enemyTank.SetActive (false);}// 回收子弹public void recycleBullet (GameObject Bullet) {usedBullets.Remove (Bullet);freeBullets.Add (Bullet);Bullet.GetComponent<Rigidbody> ().velocity = Vector3.zero;Bullet.SetActive (false);}
}
GameDirector

实现了总导演的设计,主要是得到实例化

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 总导演 √
public class GameDirector : System.Object {private static GameDirector _instance;public SceneController currentSceneController { get; set; }private GameDirector () { }public static GameDirector getInstance () {if (_instance == null) _instance = new GameDirector ();return _instance;}
}
IUserAction

实现了动作的接口;主要有控制玩家坦克的转动以及行进;控制射击;控制游戏是否结束

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 动作接口 √
public interface IUserAction {// 控制转动和行进void moveForWard ();void moveBackWard ();void turn (float turnX);// 控制射击void shoot ();// 控制游戏结束bool GameOver ();
}
IUserGUI

实现了游戏界面的设置;主要是设计了监听键盘的输入,来控制坦克的行进以及攻击的操作;并且在游戏结束后显示 Game Over!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 设置界面 √
public class IUserGUI : MonoBehaviour {IUserAction action;void Start () {action = GameDirector.getInstance ().currentSceneController as IUserAction;}void Update () {if (!action.GameOver ()) {// 监听键盘if (Input.GetKey (KeyCode.W)) action.moveForWard ();if (Input.GetKey (KeyCode.S)) action.moveBackWard ();if (Input.GetKeyDown (KeyCode.Space)) action.shoot ();float turnX = Input.GetAxis ("Horizontal");action.turn (turnX);}}void OnGUI () {// 游戏结束if (action.GameOver ()) {GUIStyle font = new GUIStyle ();font.fontSize = 50;font.normal.textColor = Color.red;GUI.Label (new Rect (Screen.width / 2 - 100, Screen.height / 2 - 50, 200, 50), "Game Over!", font);}}
}
SceneController

实现了场景控制器。用来生产玩家和敌人;并且实现了第一视角的设置,将相机的位置始终跟随玩家;可以获取玩家的物体;控制玩家进行移动;控制玩家进行设计;返回游戏的状态并且可以设置游戏的状态

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 场景控制器 √
public class SceneController : MonoBehaviour, IUserAction {public GameDirector director;public GameObject player;private Factory myFactory;private GameObject[] enemies;private int enemyCount = 5;private bool gameOver = false;// 初始化private void Awake () {director = GameDirector.getInstance ();director.currentSceneController = this;myFactory = Singleton<Factory>.Instance;enemies = new GameObject[enemyCount];gameOver = false;}// 生产玩家和敌人 void Start () {player = myFactory.getPlayer ();for (int i = 0; i < enemyCount; ++i) enemies[i] = myFactory.getEnemys ();Player.destroyEvent += setGameOver;}// 设置相机的位置void Update () {Camera.main.transform.position = new Vector3 (player.transform.position.x, 20, player.transform.position.z);}// 获取玩家游戏物体public GameObject getPlayer () { return player; }// 控制玩家移动public void moveForWard () { player.GetComponent<Player> ().moveForWard (); }public void moveBackWard () { player.GetComponent<Player> ().moveBackWard (); }public void turn (float turnX) { player.GetComponent<Player> ().turn (turnX); }// 控制玩家射击public void shoot () { player.GetComponent<Player> ().shoot (TankType.PLAYER); }// 返回游戏状态public bool GameOver () { return gameOver; }// 游戏结束public void setGameOver () { gameOver = true; }
}

IUserGUISceneControllerFactory挂载到相机上

Singleton

实现了单实例模式

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));return instance;}}
}
Tank

实现了坦克的相关属性;主要设置了坦克初始的生命值为100;并且设置了 get/set 方法。以及设置被攻击后生命值的减少;射击子弹射击的方向以及力度

using System.Collections;
using System.Collections.Generic;
using UnityEngine;// 设置坦克相关属性 √
public class Tank : MonoBehaviour {private float health = 100.0f;// 初始化生命值public Tank () { health = 100.0f; }// 设置/获取生命值public void setHP (float health) { this.health = health; }public float getHP () { return health; }// 被攻击public void Attacked () { health -= 20; }// 设置子弹射击public void shoot (TankType type) {GameObject bullet = Singleton<Factory>.Instance.getBullets (type);// 设置子弹射的方向bullet.transform.position = new Vector3 (transform.position.x, 1.5f, transform.position.z) + transform.forward * 1.5f;bullet.transform.forward = transform.forward;bullet.GetComponent<Rigidbody> ().AddForce (bullet.transform.forward * 20, ForceMode.Impulse);}
}
8. 导航

之前已经给玩家和敌方坦克添加了Nav Mesh Agent组件,在菜单栏点击窗口-AI-导航,在右侧窗口点击烘培,点击下方Bake按钮,生成导航网格图

游戏说明

玩家通过键盘上的wsad按键控制坦克的移动,玩家是蓝色坦克,敌人是绿色坦克,当玩家暴露在敌人的视野中,敌人就会跟踪玩家,并向玩家发送子弹,玩家要尽可能躲避子弹,按空格键可以向敌人发射子弹。每个坦克都有自己的生命值,当生命值小于零时会被销毁,当玩家坦克被销毁时,游戏结束。

实现效果

  • 游戏地图
  • 游戏进行中
  • 游戏结束
视频效果

视频效果

项目地址

项目地址

Assets文件夹下载到本地,然后直接通过unity打开即可成功运行,或者新建一个项目,用Assets覆盖原来的文件夹,打开后即可正常运行。

unity实现坦克对战相关推荐

  1. unity实现简单坦克对战

    unity实现简单坦克对战 游戏要求 使用"感知-思考-行为"模型,建模 AI 坦克 场景中要放置一些障碍阻挡对手视线 坦克需要放置一个矩阵包围盒触发器,以保证 AI 坦克能使用射 ...

  2. unity实现AI对战坦克

    unity实现AI对战坦克 游戏要求 使用"感知-思考-行为"模型,建模 AI 坦克 场景中要放置一些障碍阻挡对手视线 坦克需要放置一个矩阵包围盒触发器,以保证 AI 坦克能使用射 ...

  3. 作业十: 坦克对战游戏 AI 设计

    坦克对战游戏 AI 设计 从商店下载游戏:"Kawaii" Tank 或 其他坦克模型,构建 AI 对战坦克.具体要求 使用"感知-思考-行为"模型,建模 AI ...

  4. 3D游戏制作——AI坦克对战

    3D游戏制作--AI坦克对战 github地址(码云) https://gitee.com/jenny_s/AITank-3Dgame 游戏视频 https://www.bilibili.com/vi ...

  5. 手把手教你用Java实现一个简易联网坦克对战小游戏

    作者:炭烧生蚝 cnblogs.com/tanshaoshenghao/p/10708586.html 介绍 通过本项目能够更直观地理解应用层和运输层网络协议, 以及继承封装多态的运用. 网络部分是本 ...

  6. Java实现简易联网坦克对战小游戏(内涵源码)//Java+Java游戏+拓展学习+资源分享

    介绍 通过本项目能够更直观地理解应用层和运输层网络协议, 以及继承封装多态的运用. 网络部分是本文叙述的重点, 你将看到如何使用Java建立TCP和UDP连接并交换报文, 你还将看到如何自己定义一个简 ...

  7. Unity编写冰球对战游戏 2D版

    Unity编写冰球对战游戏 2D版 Unity是一款非常方便.简洁.低成本的一款游戏引擎.在这里,向大家介绍这样用Unity这个引擎编写冰球对战游戏 因为Unity这个引擎可以编写3D游戏 ,同样的也 ...

  8. java怎么实现网络对战平台_手把手教你用Java实现一个简易联网坦克对战小游戏...

    介绍 通过本项目能够更直观地理解应用层和运输层网络协议, 以及继承封装多态的运用. 网络部分是本文叙述的重点, 你将看到如何使用Java建立TCP和UDP连接并交换报文, 你还将看到如何自己定义一个简 ...

  9. 坦克对战游戏 AI 设计

    坦克对战游戏 AI 设计 从商店下载游戏:"Kawaii" Tank 或 其他坦克模型,构建 AI 对战坦克.具体要求 使用"感知-思考-行为"模型,建模 AI ...

最新文章

  1. 别说,Cerebro还真好用!老板再也不用担心ES集群了
  2. All-in-One 模式安装 KubeSphere 异常问题记录
  3. 机器学习-情感分析-入门实战案例
  4. 安卓能帮你检查密码泄露了!还有Messages定时发送等多项功能优化
  5. 将DataTable中的数据导入到数据库中
  6. View-webui controller 功能流程
  7. 【常见Web应用安全问题】
  8. 线性代数拾遗(一):线性方程组、向量方程和矩阵方程
  9. 华为鸿蒙网络,这回真翻脸了?被谷歌“除名”,官宣鸿蒙手机版,华为:走着瞧...
  10. Amazon S3数据一致性模型
  11. ORACLE监听器TNS服务不能启动的问题解决(转自:http://www.cnweblog.com/sunGIS/archive/2006/08/21/124117.html)...
  12. 递归法:财务金额漏掉1笔或者几笔(排列组合)
  13. 次氯酸:利用先天反应
  14. 五分钟带你了解什么是PID模糊算法
  15. 2022年全国大学生电子设计大赛省赛A题
  16. 规范-阿里代码规范设置
  17. treetable php,jQuery树型表格插件jQuery treetable
  18. oracle中常使用到的函数,Oracle经常使用到的函数
  19. javascript 模拟退格键_js按钮模拟键盘退格键定位删除问题
  20. WPF 制作带TreeView的ComBox

热门文章

  1. 动态规划法求最优分配方案(空间优化)
  2. 从0开始写一个小程序
  3. ModemManager 1.10发布
  4. 智慧全媒体 5G新视听,共探新时代广播电视!
  5. python导入安装包
  6. KubeFATE 部署多集群联邦学习平台 FATE
  7. jQuery-Ajax请求Json数据并加载在前端页面,附视频教程讲解!
  8. Python绘制类激活图曲线(热力曲线)
  9. springboot异步和切面_SpringBoot强化篇(八)-- Spring AOP
  10. win7 ie10代理设置不能用 设置完代理后点确定 回头再打开代理设置对钩并没有选上