Unity3D实现坦克大战

一、效果图演示

二、逻辑剖析

从界面上:

  • 需要一个Canvas满屏对着用户,该Canvas上展示用户的游戏数据,比如血条。
  • 需要一个Canvas放在蓝色坦克上方,也需要实时对着用户,显示敌人的血条信息
  • 两个坦克
  • 一个平面Plane放草地的纹理

从逻辑上:

  • 前后箭头键控制玩家前进或后退
  • 左右箭头键控制玩家左右转向
  • 鼠标左键或空格键控制玩家发射炮弹
  • 玩家血条希纳是在屏幕左上角
  • 相机在玩家后上方的位置,始终跟随玩家,朝玩家正前方看
  • 玩家移动时,敌人转向玩家,当偏离玩家的角度小于5度时,发射炮弹
  • 敌人血条显示在其上方,并且始终看向相机

三、界面组件信息

(1)游戏对象层级结构

(2)组件参数信息

1.玩家Player组件参数

NameTypePositionRotationScaleColor
PlayerEmpty(0, 0.25, -5)(0, 0, 0)(1, 1, 1)#228439
ButtonCube(0, 0, 0)(0, 0, 0)(2, 0.5, 2)#228439
TopCube(0, 0.5, 0)(0, 0, 0)(1, 0.5, 1)#228439
GunCylinder(0, 0, 1.5)(90, 0, 0)(0.2, 1, 0.4)#228439
FirePointEmpty(0, 1.15, 0)(0, 0, 0)(1, 1, 1)--

Player 游戏对象添加了刚体组件,并修改 Mass = 100,Drag = 1,AngularDrag = 0.1,Freeze Rotation 中勾选 X 和 Z。 

2.玩家HP组件参数

NameTypePositionWidth/HeightColor
PlayerHPCanvas(960, 540, 0)1920/1080--
Panel     Panel位置信息全是0#FFFFFF
HealthBGImage(-809,464,0)200/20#FFFFFF
HealthImage(-809,464,0)200/20#FF2230

玩家 PlayerHP 的 Canvas 渲染模式是 Screen Space - Overlay。

制作一个红色的图片放入Health的Source Image中,Health 的 ImageType 设置为 Filled,Fill Method 设置为 Horizontal。

3.敌人组件参数

NameTypePositionRotationScaleColor
EnemyEmpty(0, 0.25, 5)(0, 180, 0)(1, 1, 1)#15D3F9
ButtonCube(0, 0, 0)(0, 0, 0)(2, 0.5, 2)#15D3F9
TopCube(0, 0.5, 0)(0, 0, 0)(1, 0.5, 1)#15D3F9
GunCylinder(0, 0, 1.5)(90, 0, 0)(0.2, 1, 0.4)#15D3F9
FirePointEmpty(0, 1.15, 0)(0, 0, 0)(1, 1, 1)--

Enemy 游戏对象添加了刚体组件,并修改 Mass = 100,Drag = 0.5,AngularDrag = 0.1,Freeze Rotation 中勾选 X 和 Z。  

4.敌人HP组件参数

NameTypePositionWidth/HeightColor
HPCanvas(0, 0.85, 0)2/0.2--
HealthBGImage(0,0,0)2/0.2#FFFFFF
HealthImage(0,0,0)2/0.2#FF2230

敌人 HP 的 Canvas 渲染模式是 World Space,将刚才的红色底图也放入Health的Source Image中,Health 的 ImageType 设置为 Filled,Fill Method 设置为 Horizontal。

5.地面和炮弹的组件参数

NameTypePositionRotationScaleColor
PlanePlane(0, 0, 0)(0, 0, 0)(10, 10, 10)GrassRockyAlbedo
BulletSphere(0, 0.5, -5)(0, 0, 0)(0.3, 0.3, 0.3)#228439

炮弹作为预设体拖拽到 Assets/Resources/Prefabs 目录下,并且添加了刚体组件。

四、脚本代码:

1.CameraController

 CameraController 脚本组件挂在 MainCamera 游戏对象上。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CameraController : MonoBehaviour
{// Start is called before the first frame updateprivate Transform player; // 玩家private Vector3 relaPlayerPos; // 相机在玩家坐标系中的位置private float targetDistance = 15f; // 相机看向玩家前方的位置void Start(){relaPlayerPos = new Vector3(0, 4, -8);player = GameObject.Find("Player/Top").transform; // 世界坐标系位置}private void LateUpdate(){ComCameraPos();}// 计算相机坐标private void ComCameraPos(){Vector3 target = player.position + player.forward * targetDistance;transform.position = transformVecter(relaPlayerPos, player.position, player.right, player.up, player.forward);transform.rotation = Quaternion.LookRotation(target - transform.position);}// 以origin为原点,已知vec在坐标轴locX/locY/locZ中的位置,将vec转为世界坐标系的位置private Vector3 transformVecter(Vector3 vec, Vector3 origin, Vector3 locX, Vector3 locY, Vector3 locZ) { return vec.x * locX + vec.y * locY + vec.z * locZ + origin;}
}

2.BulletInfo

using UnityEngine;public class BulletInfo
{public string name; // 炮弹名public Color color; // 炮弹颜色public Vector3 flyDir; // 炮弹飞出方向public float speed; // 炮弹飞行速度public float fireRange; // 炮弹射程public BulletInfo(string name, Color color, Vector3 flyDir, float speed, float fireRange){this.name = name;this.color = color;this.flyDir = flyDir;this.speed = speed;this.fireRange = fireRange;}
}

3.BulletController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class BulletController : MonoBehaviour
{private BulletInfo bulletInfo; // 炮弹信息private volatile bool isDying = false;// Start is called before the first frame updatevoid Start(){gameObject.name = bulletInfo.name;GetComponent<MeshRenderer>().material.color = bulletInfo.color;float lifeTime = bulletInfo.fireRange / bulletInfo.speed; // 存活时间Destroy(gameObject, lifeTime);}// Update is called once per framevoid Update(){transform.GetComponent<Rigidbody>().velocity = bulletInfo.flyDir * bulletInfo.speed;}public void SetBulletInfo(BulletInfo bulletInfo){this.bulletInfo = bulletInfo;}private void OnCollisionEnter(Collision other){if (isDying){return;}if(IsHitEnemy(gameObject.name, other.gameObject.name)){other.transform.Find("HP/Health").GetComponent<Image>().fillAmount -= 0.1f;isDying = true;Destroy(gameObject, 0.1f);}else if(IsHitPlayer(gameObject.name, other.gameObject.name)){GameObject.Find("PlayerHP/Panel/Health").GetComponent<Image>().fillAmount -= 0.1f;isDying = true;Destroy(gameObject, 0.1f);}}private bool IsHitEnemy(string name, string otherName){return name.Equals("PlayerBullet") && otherName.Equals("Enemy");}private bool IsHitPlayer(string name, string otherName){return name.Equals("EnemyBullet") && otherName.Equals("Player");}
}

4.PlayerController

PlayerController 脚本组件挂在 Player 游戏对象上。 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerController : MonoBehaviour
{private Transform firePoint; // 开火点private GameObject bulletPrefab; // 炮弹预设体private float tankMoveSpeed = 4f; // 坦克移动速度private float tankRotateSpeed = 2f; // 坦克转向速度private float fireWaitTime = float.MaxValue; // 距离上次开火已等待的时间private float bulletCoolTime = 0.15f; // 炮弹冷却时间void Start(){firePoint = transform.Find("Top/Gun/FirePoint");bulletPrefab = (GameObject)Resources.Load("Prefabs/Bullet");}// Update is called once per framevoid Update(){fireWaitTime += Time.deltaTime;float hor = Input.GetAxis("Horizontal");float ver = Input.GetAxis("Vertical");Move(hor, ver);if(Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)){Fire();}}// 坦克移动private void Move(float hor, float ver) {if (Mathf.Abs(hor) > 0.1f || Mathf.Abs(ver) > 0.1f) {GetComponent<Rigidbody>().velocity = transform.forward * tankMoveSpeed * ver;GetComponent<Rigidbody>().angularVelocity = Vector3.up * tankRotateSpeed * hor;}}// 开炮private void Fire(){if (fireWaitTime > bulletCoolTime) { BulletInfo bulletInfo = new BulletInfo("PlayerBullet", Color.red, transform.forward, 10f, 15f);GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity);bullet.AddComponent<BulletController>().SetBulletInfo(bulletInfo);fireWaitTime = 0f;}}
}

5.EnemyController

EnemyController 脚本组件挂在 Enemy 游戏对象上。  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyController : MonoBehaviour
{private Transform target; // 目标private Transform top; // 炮头private Transform firePoint; // 开火点private Transform hp; // 血条private GameObject bulletPrefab; // 炮弹预设体private float rotateSpeed = 0.4f; // 坦克转向速度private float fireWaitTime = float.MaxValue; // 距离上次开火已等待时间private float bulletCoolTime = 1f; // 炮弹冷却时间// Start is called before the first frame updatevoid Start(){target = GameObject.Find("Player/Top").transform;top = transform.Find("Top");firePoint = transform.Find("Top/Gun/FirePoint");hp = transform.Find("HP");bulletPrefab = (GameObject)Resources.Load("Prefabs/Bullet");}// Update is called once per framevoid Update(){fireWaitTime += Time.deltaTime;if (LookAtTarget()) {Fire();}HPLookAtCamera();}private bool LookAtTarget(){Vector3 dir = target.position - top.position;float angle = Vector3.Angle(dir, top.forward);if(angle > 5){int axis = Vector3.Dot(Vector3.Cross(dir, top.forward), Vector3.up) > 0 ? -1 : 1;GetComponent<Rigidbody>().angularVelocity = axis * Vector3.up * rotateSpeed;return false;}GetComponent<Rigidbody>().velocity = Vector3.zero;return true;}private void HPLookAtCamera(){Vector3 cameraPos = Camera.main.transform.position;Vector3 target = new Vector3(cameraPos.x, hp.position.y, cameraPos.z);hp.LookAt(target);}private void Fire(){if(fireWaitTime > bulletCoolTime){BulletInfo bulletInfo = new BulletInfo("EnemyBullet", Color.yellow, top.forward, 5f, 10f);GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity); // 通过预设体创建炮弹bullet.AddComponent<BulletController>().SetBulletInfo(bulletInfo);fireWaitTime = 0;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/669203.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全球5大住宅代理IP服务商测评对比

住宅IP代理为跨境出海用户提供了更加多元、安全和高效的网络访问体验。住宅代理服务使用真实的住宅IP地址&#xff0c;而这些IP地址通常最接近于海外个人家庭用户&#xff0c;从而减少了被封锁或标记为可疑流量的可能性&#xff0c;对于部分跨境电商平台账号&#xff08;如亚马…

Unity动画循环偏移的使用

最近项目中有一个需求是做煤矿中猴车的动画&#xff0c;动画本身不复杂&#xff0c;但是猴车很多&#xff0c;怎么能简化工作量呢&#xff1f; 首先单个猴车的动画循环是必须要做的&#xff0c;重点是怎么让不同的猴车动画按顺序错开&#xff0c;研究了以下&#xff0c;可以通过…

Docker Dockerfile

1、概念介绍 Dockerfile是用来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 每条保留字指令都必须为大写字母且后面要跟随至少一个参数 指令按照从上到下&#xff0c;顺序执行 #表示注释 每条指令都会创建一个新的镜像层并对镜像进…

[开源]GPT Boss – 用图形化的方式部署您的私人GPT镜像网站

在这个以数据和智能为核心的时代&#xff0c;掌握最新的技术趋势是每个企业和个人都需要做到的。这就是GPT Boss存在的意义&#xff1a;一个基于OpenAI技术的一站式GPT应用解决方案。 自2022年起&#xff0c;GPT Boss团队便投身于人工智能领域&#xff0c;将OpenAI的GPT模型带给…

《Linux C编程实战》笔记:有名管道

管道的一个问题就是没有名字&#xff0c;因此只能用于有亲缘关系的进程间通信。 有名管道(named pipe或FIFO)它提供一个路径名与之关联&#xff0c;以FIFO的文件形式存储于文件系统中。有名管道是一个设备文件&#xff0c;因此&#xff0c;即使进程与创建FIFO的进程不存在亲缘…

使用maven对springboot项目进行瘦身

目录 一、什么是Maven 二、springboot 项目 三、springboot 项目瘦身 一、什么是Maven Maven是一个基于Java的项目管理和构建工具。它通过提供一个一致的项目结构、自动化构建脚本和依赖管理系统&#xff0c;简化了Java项目的构建过程。 Maven使用一种称为POM&#xff08;…

华为数通方向HCIP-DataCom H12-821题库(单选题:381-400)

第381题 以下是某台设备通过display isis lsdb命令输出的信息,那么关于以上输出的信息的描述,正确的是哪一项? <R1>display isis lsdbDatabase information for ISIS(1)--------------------------------Level-1 Link State DatabaseLSPID Seq Num…

【Gephi项目实战-带数据集】利用gephi绘制微博肖战超话120位用户关系图,并计算整体网络指标与节点指标

数据集在评论区&#xff0c;B站演示视频在评论区&#xff01; 简介 最近2天需要用到gephi做社会网络分析&#xff0c;于是从0开始接触gephi并摸索出了gephi的基本使用指南。下面将结合真实的节点文件与边文件&#xff0c;利用gephi绘制社会网络并计算相关测量指标。整个过程会…

数据库学习笔记2024/2/5

2. SQL 全称 Structured Query Language&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了 一套操作关系型数据库统一标准 2.1 SQL通用语法 在学习具体的SQL语句之前&#xff0c;先来了解一下SQL语言的通用语法。 1). SQL语句可以单行或多行书写&…

扩展鸿蒙ArkUI日期组件

鸿蒙ArkUI日期组件使用的是DatePickerDialog.show基础上扩展的表单式输入组件&#xff0c;方便在输入日期方式快速使用及复用。 /*** 日期*/ Component export default struct DiygwDate{//绑定的值Link Watch(onValue) value:string;// 隐藏值State valueField: string valu…

(5)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—12种聚类算法说明与归纳

目录 一、12种聚类(无监督学习)算法说明和区分比较 聚类算法的类型(一) ​编辑导入函数库 加载数据集 ​编辑 (1)K-Means --Centroid models (2)Mini-Batch K-Means -- Centroid models (3)AffinityPropagation (Hierarchical) -- Connectivity models (4)Mean Shift…

DBNet详解及训练ICDAR2015数据集

论文地址&#xff1a;https://arxiv.org/pdf/1911.08947.pdf 开源代码pytorch版本&#xff1a;GitHub - WenmuZhou/DBNet.pytorch: A pytorch re-implementation of Real-time Scene Text Detection with Differentiable Binarization 前言 在这篇论文之前&#xff0c;文字检…

微信小程序的图片色彩分析,窃取网络图片的主色调

1、安装 Mini App Color Thief 包 包括下载包&#xff0c;简单使用都有&#xff0c;之前写了&#xff0c;这里就不写了 网址&#xff1a;微信小程序的图片色彩分析&#xff0c;窃取主色调&#xff0c;调色板-CSDN博客 2、 问题和解决方案 问题&#xff1a;由于我们的窃取图片的…

基于Langchain-Chatchat + chatGLM3 轻松在本地部署一个知识库

前面三篇分别讲解了如何在本地环境部署大模型&#xff0c;那么今天简单的通过 Langchain-Chatchat 和 chatGLM3结合在本地环境搭建一套属于自己的大模型知识库。 往期llm系列文章 基于MacBook Pro M1芯片运行chatglm2-6b大模型如何在本地部署chatGLM3基于ChatGLM.cpp实现低成…

论文阅读-通过云特征增强的深度学习预测云工作负载转折点

论文名称&#xff1a;Cloud Workload Turning Points Prediction via Cloud Feature-Enhanced Deep Learning 摘要 云工作负载转折点要么是代表工作负载压力的局部峰值点&#xff0c;要么是代表资源浪费的局部谷值点。预测这些关键点对于向系统管理者发出警告、采取预防措施以…

企业动态 | UFAPKU“金融科技”沙龙走进同创永益——前沿技术在金融科技领域的应用

金融科技作为金融发展的驱动力量&#xff0c;对金融行业有着深远的影响。金融行业通过技术创新和数字化转型&#xff0c;极大地提高了金融服务和产品的效率和便捷性。1月21日&#xff0c;UFAPKU“金融科技”第二期沙龙在北大校友企业同创永益北京总部举办&#xff0c;数十位来自…

请问CTF是什么?请介绍一下关于隐水印的知识特点技术原理应用领域技术挑战

目录 请问CTF是什么&#xff1f; 请介绍一下关于隐水印的知识 特点 技术原理 应用领域 技术挑战 请问CTF是什么&#xff1f; CTF&#xff08;Capture The Flag&#xff0c;夺旗比赛&#xff09;是一种信息安全竞赛&#xff0c;常见于计算机安全领域。这种比赛模拟各种信…

fastjson 导致的OOM

fastjson 导致的OOM 示例代码 public static void main(String[] args) throws Exception {try {List<Integer> list JSONObject.parseArray("[2023,2024", Integer.class);}catch (Exception e){System.err.println("error");}System.out.println…

一文搞懂 springboot 如何融合数据源

1、简介 springboot 支持关系型数据库的相关组件进行配置&#xff0c;包括数据源、连接池、事务管理器等的自动配置。降低了数据库使用的难度&#xff0c;除了 mysql 还支持 Derby、H2等嵌入式数据库的自动配置&#xff0c;MongoDB、Redis、elasticsearch等常用的 NoSQL 的数据…

BGP邻居故障检测

第一种情况:如果AR2和AR4采用直连建立邻居,则排查步骤如下: 1)在AR2和AR4上使用ping x.x.x.x命令检查AR2和AR4用于建立EBGP邻居关系的直连地址连通性是否正常。如果不能ping通。则需要使用二分法从网络层向下层逐层进行排查,首先检查接口地址及路由的可达性,修改完成后,如…