Tanks坦克大战
创建工程,场景:
将素材导入,Unity5以上的版本,无需担心素材包的路径问题,中文路径也可以直接导入了,简单方法就是将素材包直接拖到Project面板

游戏所需要的场景在Prefabs里的LevelArt,拖入后,加载很慢,是因为场景在渲染,这时需要去设置Window-lighting,选中Scene,讲auto的勾去掉,就不会自动渲染,其他设置以后再研究。

然后设置Camera中的背景色,选择自己喜欢的颜色,然后调整Camera的位置,适应场景

选择视野,设置为正交

添加坦克,控制坦克前后移动:
坦克由Tank,DustTrail组成。为坦克添加Box Collider,点击Edit Collider调整Collider大小

为Tank添加Rigidbody,然后将整个Tank制成Prefab。
代码控制Tank前后移动(TankMovement.cs):为什么用FixedUpdate而不是Update
public float speed = ;
private Rigidbody rigidbody;
// Use this for initialization
void Start () {
rigidbody = this.GetComponent<Rigidbody>();
} // Update is called once per frame
void FixedUpdate () {
float v = Input.GetAxis("Vertical");
//速度
rigidbody.velocity = transform.forward * v * speed;
}
运行程序后发现Tank会翻转,导致向上运动,需要设置Rigidbody中的属性,y轴位置是不变的,所以将Y轴定死,Tank是围绕Y轴旋转,并不围绕其他两轴旋转,则定死X,Z轴

控制坦克的旋转
float h = Input.GetAxis("Horizontal");
rigidbody.angularVelocity = transform.up * h * angularSpeed;
修改坦克控制的灵活性(增加坦克编号)
因为有两个坦克对战,一个允许使用A,S,W,D控制,一个允许使用方向键控制,则需要增加同样的控制不同的名称定义,在Edit-Project Setting-Input



同理,vertical也可以这样操作。
然后定义变量number,区分坦克1和坦克2。
float v = Input.GetAxis("VerticalPlayer" + number);
//速度
rigidbody.velocity = transform.forward * v * speed;
float h = Input.GetAxis("HorizontalPlayer" + number);
rigidbody.angularVelocity = transform.up * h * angularSpeed;
控制坦克子弹的发射
在Model文件夹中找到Shell,然后为Shell添加Capsule Collider(胶囊碰撞器),然后将其制成Prefab;
在Tank下创建Empty Gameobject,将其拖到坦克炮筒口,定义一个TankAttack.cs,控制子弹的生成,利用GameObject.Instantiate().
public class TankAttack : MonoBehaviour {
public GameObject shellPrefab;
public KeyCode fireKey = KeyCode.Space;
private Transform firePosition;
// Use this for initialization
void Start () {
firePosition = transform.Find("FirePosition");
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(fireKey))
{
GameObject.Instantiate(shellPrefab, firePosition.position, firePosition.rotation);
}
}
}
控制炸弹的飞行和爆炸
子弹的飞行需要速度,速度则需要刚体组件,为Shell添加Rigidbody。在TankAttack.cs中定义子弹的速度,public型,便于在界面上修改调试。
public class TankAttack : MonoBehaviour {
public GameObject shellPrefab;
public KeyCode fireKey = KeyCode.Space;
private Transform firePosition;
public float shellSpeed = ;
// Use this for initialization
void Start () {
firePosition = transform.Find("FirePosition");
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(fireKey))
{
GameObject go = GameObject.Instantiate(shellPrefab, firePosition.position, firePosition.rotation) as GameObject;
go.GetComponent<Rigidbody>().velocity = go.transform.forward * shellSpeed;
}
}
}
子弹发射后会存在很多Prefab,占内存,需要销毁,使用Destroy(),为Shell创建Shell.cs组件,子弹爆炸的动画效果,需要ShellExplosion这个prefab。这个Prefab勾选Play on awake,表示在实例化成功时即开始运行动画效果。

public class Shell : MonoBehaviour {
public GameObject shellExplosionPrefab;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider col) {
GameObject.Instantiate(shellExplosionPrefab, transform.position, transform.rotation);
GameObject.Destroy(this.gameObject);
}
}
然后爆炸的动画Prefab没有自动销毁,为ShellExplosion创建组件DestoryForTime.cs,在Start方法中就调用Destory()方法销毁,但不是立即销毁,而是在一定时间以后。然后该动画的Duration = 1.5s,所以设置为1.5秒以后销毁。
public class DestoryForTime : MonoBehaviour {
public float time;
// Use this for initialization
void Start () {
Destroy(this.gameObject, time);
}
// Update is called once per frame
void Update () {
}
}
控制炸弹对坦克的伤害
为Tank的Prefab添加tag名为"Tank",在Shell.cs中使用SendMessage()方法,在碰撞后触发方法中参数的方法。
if (col.tag == "Tank")
{
col.SendMessage("TankDamage");
}
为Tank创建组件TankHealth.cs。这里涉及使用tank爆炸的动画Prefab,TankExplosion,注意里面的方法必须与Shell中SendMessage()方法中的参数相同。
public class TankHealth : MonoBehaviour {
public int hp = ;
public GameObject tankExplosion;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void TankDamage()
{
if (hp <= ) return;
hp -= Random.Range(, );
if (hp <= )
{
GameObject.Instantiate(tankExplosion, transform.position + Vector3.up, transform.rotation);
Destroy(this.gameObject);
}
}
}
然后创建第二个坦克,注意修改键盘按键。
修改坦克的外观
控制相机视野的跟随
为Camera创建FollowTarget.cs
这里是两个Gameobject,则跟随物体移动,取两者中点与相机(Camera)的距离保持不变:offset = this.transform.position - (player1.position + player2.position) / 2
控制视野的大小:相机随两物体中点的变化在移动,渐渐的会失去某一个物体的视野,由于我们相机的Projection选择的是Orthographic,所以可以控制其Size属性,使其Size和两坦克之间的距离的比例保持不变,这样当距离变大时,Size也变大,视野就变大,两个坦克就会一直在视野中。我们一开始的Size定为10,两个坦克之间的距离是16,10/16 = 0.625,比例是定值。运动过程中求两物体间距离,使用Vector3.Distance().
然后这里还存在一个问题,当某个坦克被消灭时,则某个物体的position就取不到,是空指针,这时我们继续去算Distance或者中点,就会报错,需要加上null的判断。
public class FollowTarget : MonoBehaviour {
public Transform player1;
public Transform player2;
private Vector3 offset;
private Camera camera;
// Use this for initialization
void Start () {
offset = this.transform.position - (player1.position + player2.position) / ;
camera = GetComponent<Camera>();
}
// Update is called once per frame
void Update () {
if (player1 == null || player2 == null) return;
transform.position = (player1.position + player2.position) / + offset;
float distance = Vector3.Distance(player1.position, player2.position);
float size = distance * 0.625f;
camera.orthographicSize = size;
}
}
给游戏添加音效
添加音乐两种方法:1.为物体添加AudioSource组件,如果不需要Awake时播放,就把勾去掉,从代码里使用AudioSource.play();2.代码里定义一个AudioClip,然后使用AudioSource.PlayClipAtPoint();
背景音乐:创建一个空物体,命名为GameManager,添加AudioSource组件。然后添加音乐,勾选循环播放即可。
坦克爆炸的声音:在爆炸的时候播放而不是在Awake的时候播放,在代码里添加;
public AudioClip tankExplosionAudio; AudioSource.PlayClipAtPoint(tankExplosionAudio, transform.position);
添加子弹打出的声音:在TankAttack.cs中添加;
public AudioClip shootAudio; AudioSource.PlayClipAtPoint(shootAudio, transform.position);
添加子弹爆炸的声音:在Shell.cs中添加;
public AudioClip shellExplosionAudio; AudioSource.PlayClipAtPoint(shellExplosionAudio, transform.position);
给坦克添加音效
因为坦克声音一直存在,所以可以通过添加组件AudioSource,然后用play()来使用。坦克有两种状态,行走和停止,要切换声音,在TankMovement.cs中通过代码控制。
void FixedUpdate () {
float v = Input.GetAxis("VerticalPlayer" + number);
//速度
rigidbody.velocity = transform.forward * v * speed;
float h = Input.GetAxis("HorizontalPlayer" + number);
rigidbody.angularVelocity = transform.up * h * angularSpeed;
//tank声音切换
if (Mathf.Abs(v) > 0.1 || Mathf.Abs(h) > 0.1)
{
audio.clip = drivingAudio;
if(audio.isPlaying == false)
audio.Play();
}
else
{
audio.clip = idelAudio;
if (audio.isPlaying == false)
audio.Play();
}
}
给坦克添加血条控制
利用UGUI的Slider,但是Slider是长条进度条,要做成圆形,可以去Sprite的文件中利用Health Wheel。系统的Slider,删除Handle Slide Area,这是进度条的拖动点,不需要。将Slider的Background的Source Image设置成Health Wheel,将Fill Area中的Fill的Source Image也设置成Health Wheel。然后修改Slider的大小,改成40*40;然后修改滑动方式,修改成360度的,修改Fill的Image Type属性,改成Filled。为了让两个Health Wheel重叠,设置Background、Fill Area、Fill的Stretch,选择上下左右填充。然后将Canvas的Render Mode设置成World Space(设置成世界空间的原因是为了让Main Camara渲染)。将Cavas整体移动到Tank中。
修改Canvas的大小,发现并没有变化,是因为Slider并没有在Stretch中选择四周填充。,将Slider调整到与地面平行,适当的大小。
void TankDamage()
{
if (hp <= ) return;
hp -= Random.Range(, );
hpSlider.value = (float)hp / hpTotal;
if (hp <= )
{
//没血了,播放爆炸的声音
AudioSource.PlayClipAtPoint(tankExplosionAudio, transform.position);
GameObject.Instantiate(tankExplosion, transform.position + Vector3.up, transform.rotation);
Destroy(this.gameObject);
}
}
Tanks坦克大战的更多相关文章
- 《杜增强讲Unity之Tanks坦克大战》10-相机控制
10 相机控制 本节主要学习如何控制相机自动调整位置和焦距,使两个坦克一直同时在视野内. image 在Hierarchy点击右键 image 点击 Create Empty,生成空对象,改名 ...
- 《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制
11 游戏流程控制 使用协程来控制游戏流程 11.1 添加MessageText 首先添加一个Text来显示文字 image 设置GameMgr image 11.2 游戏整体流程 下面Gam ...
- 《杜增强讲Unity之Tanks坦克大战》9-发射子弹时蓄力
9 发射子弹时蓄力 实现效果如下 image 按下开火键(坦克1为空格键)重置力为最小力,一直按着的时候蓄力,抬起的时候发射.如果按着的时候蓄力到最大,则自动发射,此时在抬起则不会重复发射. 首先 ...
- 《杜增强讲Unity之Tanks坦克大战》4-坦克的移动和旋转
4 坦克移动和旋转 本节课的目标是实现同时wsad和上下左右控制两个坦克分别移动和旋转 4.1 本节代码预览 image 将上节课场景s2另存为s3. 4.2 添加车轮扬沙效果 从Prefabs里 ...
- 《杜增强讲Unity之Tanks坦克大战》1-准备工作
0.案例介绍 0.1开始界面 点击Play Now 进入游戏界面 左边的坦克使用ws控制前后移动,ad键左右旋转,空格键开火 右边的坦克使用方向键上下控制前后移动,方向键左右键实现左右旋转 ...
- 《杜增强讲Unity之Tanks坦克大战》2-场景设置
2 场景设置 2.1 本节效果预览 2.2 项目目录设置 点击Project面板的Create按钮,在根目录下面新建wm文件夹 Wm文件夹用于存放我们自己生成的Prefab和脚本等其他资源, ...
- 《杜增强讲Unity之Tanks坦克大战》3-添加坦克
3 添加坦克 3.1 本节效果预览 3.2 另存新场景 首先打开上次的场景s1,另存为s2,放到同一个文件夹下面. 3.3 添加坦克模型 在Model文件夹下面找到Tank模型 将Tank ...
- 《杜增强讲Unity之Tanks坦克大战》5-子弹
5 子弹 本节的任务是创建子弹的Prefab image 首先从Model/Shell找到子弹的模型,拖入Hierarchy中,添加刚体组件,所有属性默认值. 添加Capsule Collider ...
- 《杜增强讲Unity之Tanks坦克大战》6-发射子弹
6 发射子弹 本节完成发射子弹的功能,最终代码如下: image 首先,发射子弹得确定发射的位置和方向,还有发射的初始速度.具体的发射速度和按下发射按键的时间长短有关,这个关于子弹的蓄力我们在第九 ...
- 《杜增强讲Unity之Tanks坦克大战》7-坦克血条
7 坦克血条 点击菜单GameObject->UI->Slider创建Slider 选中EventSystem,设置Horizontal Axis为HorzontalUI,Vertic ...
随机推荐
- iOS编程中遇到的问题
1.应用在iPhone6plus 系统iOS9.1安装时没遇到问题,在iPhone4s 系统iOS 7时bulid success 但是安装失败提示 There was an internal API ...
- linux 添加 service 服务并自动添加 chkconfig 启动级别
下面以添加一个叫做watchcat的服务为例进行说明: 1.写一个提供给service命令使用的脚本 service 命令的使用方法一般如下 启动: $ service watchcat start ...
- struts2自定义MVC框架
自定义MVC:(首先了解Model1和Model2的概念) Model1与Model2: Model1:就是一种纯jsp开发技术,将业务逻辑代码和视图渲染代码杂糅在一起. Model2:Model2是 ...
- CentOS7 编译安装 Nginx (实测 笔记 Centos 7.0 + nginx 1.6.2)
环境: 系统硬件:vmware vsphere (CPU:2*4核,内存2G,双网卡) 系统版本:CentOS-7.0-1406-x86_64-DVD.iso 安装步骤: 1.准备 1.1 显示系统版 ...
- mount windows-linux文件共享
. (2)在linux下访问windows共享: smbclient -L 192.168.2.12 -U admin //查看共享了那些目录,由此知道主机名为XIAOXING-PC smbcli ...
- 关于type erasure
哇,好久没有写blog了,再不写的话,blog的秘密都要忘记了,嘿嘿. 最近在试着参与一个开源项目,名字叫avim(A Vibrate IM),别想多了哟.地址是:https://github.com ...
- 宿主机远程桌面连接vmware中的虚拟机
参考了:http://jingyan.baidu.com/article/3052f5a1e8c56397f21f8674.html 感谢~ 宿主机安装了vmware,vmware中安装虚拟机,怎 ...
- BZOJ 1003 物流运输【最短路】【动态规划】
这道题数据太小啦!先枚举i,j表示从第i天到第j天不更改航线的费用. 然后直接跑最短路算法(我用的是Q版男朋友算法) 动归方程显然是f[i] = min(f[i], f[j] + cost[j+1][ ...
- 【Demo】QQ,github,微博第三方社交登录
本文主要讲解 集成 第三方社交账号登录 为什么会有这个需求? 主要是因为目前互联网的网站数量太多,如果在各个站点都注册一个账号 用户非常不容易记住每个账号的用户名和密码,并且非常难保证每个账号的密码足 ...
- 使用Qt5.7.0 VS2015版本生成兼容XP的可执行程序 good(从VS2012 update1开始支持xp和c++11)
一.直接使用VS2012/VS2013/VS2015生成XP兼容的可执行程序 Visual Studio刚发布时没打补丁,称为RTM版,之后会陆续发布补丁,进行bug修复和功能增强.VS2010及之前 ...