Unity入门第三天:子弹发射,触发器,标签与无敌死亡动画

本篇讲述了子弹的发射代码,子弹碰到不同物体时的不同触发,和角色的死亡,无敌时间的动画。

子弹发射与发射间隔

话不多说,直接上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//在player文件中:
//引用子弹的模型
public GameObject bulletPrefab;
//设置参数
//子弹旋转度数
private Vector3 bulletEulerAngles;
//计时器
private float timeVal;

//在之前控制坦克方向的代码中添加坦克旋转度数:
//2D游戏是反着的,本身沿着x轴旋转180度,“2D游戏和UI要反过来(正90度 -> 负90度)”
if (h < 0){
sr.sprite = tankSprite[3];
//往左
bulletEulerAngles = new Vector3(0,0,90);
}
else if (h > 0){
sr.sprite = tankSprite[1];
//往右旋转
bulletEulerAngles = new Vector3(0,0,-90);
}
if (v < 0){
sr.sprite = tankSprite[2];
//下面
bulletEulerAngles = new Vector3(0,0,-180);
}
else if (v > 0){
sr.sprite = tankSprite[0];
//朝上;原本图像就是朝上的,不需要设置成180,否则会和朝向下面的图像一样
bulletEulerAngles = new Vector3(0,0,0);
}

//坦克的攻击方法
private void Attack(){
//如果玩家按下空格键
if(Input.GetKeyDown (KeyCode.Space))
{
//实例化子弹(游戏物体,坦克的位置,旋转角度)
//子弹产生的角度:当前坦克的角度+子弹应该旋转的角度
//面板中的Rotation是转化为欧拉角的四元数,不是rotation本身。
//使用API:Quaternion.Euler将四元数转化为rotation
Instantiate(bulletPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bulletEulerAngles));
//重置timeVal计时器
timeVal = 0;
}
}

//子弹射击间隔(攻击cd)
void Update(){
//攻击的cd
//通常计时器都放在Update()里
if(timeVal >= 0.4f){
Attack();
}
//如果没有0.4f就随着时间而增加,从而达到攻击间隔的效果
else{
timeVal += Time.deltaTime;
}
}

//最后,在bullet文件中设置射速和移动方法:
public float movespeed = 10;
void Update()
{
//不是transform.forward, forward是沿着z轴移动
//应该用.up来实现x轴移动
//Translate方法两个参数:第一个参数可以是沿着世界坐标轴移动,
//或者是沿着自身方向移动,
//如果是世界,则第二个参数不用填,
//也可以选择Space.World或者Space.Self,
//否则必须填Space.World
transform.Translate(transform.up * movespeed * Time.deltaTime, Space.World);

触发器与标签

众所周知,坦克大战中的子弹打到墙壁时应该与墙壁产生碰撞,并消失。于是我们在这里设置了子弹触发:两方都需要有碰撞器组件(Box Collider 2D),其中一方必须有触发器(is trigger☑️) , 并且运动的一方有刚体(Rigidbody 2D),并将他的重力设为0。

而不同的物体与子弹撞击时我们希望会有不同的结果:如当子弹打到玩家时会爆炸,并导致玩家死亡;当子弹打到草时会穿过去等。我们可以设置标签(tag)来方便操作:

在子弹脚本中,我们用switch来搭建出触发框架:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//要用2D的触发器 collision->子弹碰到的物体
public void OnTriggerEnter2D(Collider2D collision){
switch(collision.tag){
case "Tank":
collision.SendMessage("Die");
break;
case "Heart":
break;
case "Barrier":
break;
case "Wall":
break;
case "Enemy":
break;
default:
break;
}

无敌与死亡

死亡function

1
2
3
4
5
6
7
8
9
10
11
12
13
//引用死亡动画
public GameObject explosionPrefab;
//坦克的死亡方法
private void Die(){
//检测玩家是不是处于被保护状态,如果是,直接return不进行下面的死亡特效
if(isDefended == true){
return;
}
//产生爆炸特效
Instantiate(explosionPrefab, transform.position, transform.rotation);
//死亡
Destroy(gameObject);
}

无敌时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//设置无敌状态
private bool isDefended = true;//布尔值的默认值都是false
//设置无敌时间累减器
private float defendTimeVal = 3;

//引用无敌动画
public GameObject defendEffectPrefab;
//在Update主程序中设置无敌:
void Update()
{ //是否处于无敌状态
if(isDefended){
//SetActive直接操作图像的显示与关闭
defendEffectPrefab.SetActive(true);
//保护的时间累减
defendTimeVal -= Time.deltaTime;
//如果3秒无敌时间过去,动画关闭,无敌状态为false
if(defendTimeVal <= 0){
isDefended = false;
defendEffectPrefab.SetActive(false);
}
}}
}

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2020-2024 Yangyang Cui

请我喝杯咖啡吧~

支付宝
微信