unity零基础开始学习做游戏(四)biu~biu~biu发射子弹打飞机

内容预览:
  • &;&;-小基原创,转载请给我一个面子   主角都能移动了,那不得做点什...~
  •    下面考虑怎么让主角射出子弹,这个就需要代码控制了 1 usi...~
  • CreateBullet()这里面使用了Instantiate这个自带的方法,通过前面载入...~

——-小基原创,转载请给我一个面子

  主角都能移动了,那不得做点什么伸张正义,守护世界和平的事嘛,拿起家伙biu~biu~biu~

 

首先得做一个好人和一个坏人

老规矩,Canvas下创建两个Image,一个叫做player,一个叫做enemy1好了

 

一个红色,一个蓝色(自古红蓝出CP,不好意思,走错片场了●﹏●)

 新知识:要加BoxCollider2D

子弹打到别人,其实是碰撞检测的过程

一种是根据位置坐标,判断子弹有没有打中,另一种是使用物理碰撞系统(小基这里使用后者)

 两个物体物理碰撞检测条件

1.物体A,物体B,必须都有Collider

2.运动的一方要有刚体(本例对应的是子弹,后面介绍)

最终效果是这样的。

 

 

下面开始制作子弹

Canvas下创建一个Image,修改名字叫做Bullet,使用自带的圆形图片凑合用吧

同样添加BoxCollider2D,最后切记添加RigidBody,不然没法碰撞成功

额外提一句,重力调成0吧,不然子弹抛物线飞=_=

现在看起来是这样的。

 

接下来想想怎么让子弹动起来,上代码(创建一个脚本Bullet),给那个子弹挂上

 1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4
5 public class Bullet : MonoBehaviour {
6
7 public float speed = 15;
8 public Vector2 dir = new Vector2(1, 0);
9 public float lifeTime = 5f;
10
11 public float damage = 1;
12 // Use this for initialization
13 void Start () {
14 DestroySelf(lifeTime);
15 }
16
17 // Update is called once per frame
18 void Update () {
19 this.transform.Translate(dir * speed * Time.deltaTime, Space.World);
20 }
21
22 void DestroySelf(float time)
23 {
24 Destroy(this.gameObject, time);
25 }
26
27 void OnTriggerEnter2D(Collider2D other)
28 {
29 //Debug.Log("enter");
30 if (other.gameObject.tag == "Enemy")
31 {
33 Destroy(this.gameObject);
34 }
35 }
36 }

start()里面调用DestroySelf(),意思是子弹存活lifeTime 时间后,自动消失。不然“让子弹飞”飞到啥时候是个头啊,飞出屏幕外就没有意义了。存活时间可以自己控制

Update()方法里面,每帧都在按照指定的dir方向移动,你想让子弹怎么飞,朝哪飞,就自行设计吧,螺旋升天都没有问题~

OnTriggerEnter2D这个方法是Unity自带的,用处就是当进入碰撞盒Collider时调用,小基的内容是销毁自己,不是~意思是销毁掉子弹

这里加了一个if的判断,判断tag是不是Enemy,毕竟打到友军可是会被喷猪队友的

Tag一般默认是Untagged的,点击一下后有弹出AddTag这个选项,然后

点击加号,可以自己创建需要的tag,这样可以给不同类别的物体做区分。

 

 下面考虑怎么让主角射出子弹,这个就需要代码控制了

  1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4
5 public class MyInput2 : MonoBehaviour {
6 //移动方向枚举
7 enum MoveDir
8 {
9 None = 0, //不动
10 Up = 1, //上8
11 Down = -1, //下2
12 Left = 10, //左4
13 Right = -10, //右6
14 UL = 11, //左上7
15 UR = -9, //右上9
16 DL = 9, //左下1
17 DR = -11, //右下3
18 }
19
20 //输入按键常量(之后走配置)
21 const KeyCode INPUT_UP = KeyCode.W;
22 const KeyCode INPUT_DOWN = KeyCode.S;
23 const KeyCode INPUT_LEFT = KeyCode.A;
24 const KeyCode INPUT_RIGHT = KeyCode.D;
25
26 //默认移动方向
27 private MoveDir moveDir = MoveDir.None;
28 //按压值
29 private int moveDirValue = 0;
30 //按压记录
31 private bool isUpPress = false;
32 private bool isDownPress = false;
33 private bool isLeftPress = false;
34 private bool isRightPress = false;
35
36 //是否可以移动
37 private bool canMove = true;
38 //右移动
39 private Vector3 MOVE_RIGHT = new Vector3(1, 0, 0);
40 //上移动
41 private Vector3 MOVE_UP = new Vector3(0, 1, 0);
42
43 //外部调控速度
44 public float speed = 2f;
45 //移动速度向量
46 private Vector3 move_speed_dir = Vector3.zero;
47 //移动距离
48 private Vector3 move_dis = Vector3.zero;
49
50 //控制目标
51 public Transform target;
52
53
54 //鼠标按下时的坐标
55 private Vector3 mouseStartPos = Vector3.zero;
56 //鼠标是否按下
57 private bool isMousePress = false;
58 //鼠标枚举
59 const KeyCode INPUT_MOUSE = KeyCode.Mouse0;
60 //鼠标拖动范围
61 const float MOUSE_RADIUS = 20;
62 //鼠标移动向量
63 private Vector3 mouseDir = Vector3.zero;
64 //鼠标速度衰减
65 private float mouseSpeedRate = 0;
66 //鼠标速度
67 public float mouseSpeed = 100;
68 //摇杆底
69 public RectTransform joyStickDown;
70 //摇杆顶
71 public RectTransform joyStickUp;
72 //摄像机
73 public Camera camera;
74
75 //子弹prefab
76 GameObject prefabBullet;
77 //是否开火
78 bool isFire = false;
79 // Use this for initialization
80 void Start () {
81 prefabBullet = (GameObject)Resources.Load("Prefab/Bullet");
82 //Debug.Log("bullet:" + prefabBullet);
83 }
84
85 // Update is called once per frame
86 void Update () {
87 CheckInputKey();
88 CheckMoveDir();
89 CheckMouseDir();
90 }
91
92 void FixedUpdate()
93 {
94 CheckMove();
95 CheckFire();
96 }
97
98 //检测输入按键
99 void CheckInputKey()
100 {
101 //检测单一输入
102 foreach (KeyCode kcode in System.Enum.GetValues(typeof(KeyCode)))
103 {
104 if (Input.GetKeyDown(kcode))
105 {
106 //Debug.Log("Single KeyCode Down: " + kcode);
107 ChangeKeyPressState(kcode, true);
108 }
109
110 if (Input.GetKeyUp(kcode))
111 {
112 //Debug.Log("Single KeyCode Up: " + kcode);
113 ChangeKeyPressState(kcode, false);
114 }
115 }
116 }
117
118 //记录按键的按压状态
119 void ChangeKeyPressState(KeyCode keyCode, bool isPress)
120 {
121 switch(keyCode)
122 {
123 case INPUT_UP:
124 isUpPress = isPress;
125 break;
126 case INPUT_DOWN:
127 isDownPress = isPress;
128 break;
129 case INPUT_LEFT:
130 isLeftPress = isPress;
131 break;
132 case INPUT_RIGHT:
133 isRightPress = isPress;
134 break;
135 case INPUT_MOUSE:
136 MouseStateChange(isPress);
137 break;
138 case INPUT_FIRE:
139 isFire = isPress;
140 break;
141 }
142 }
143
144 //鼠标按键输入
145 void MouseStateChange(bool isPress)
146 {
147 isMousePress = isPress;
148 mouseStartPos = isPress ? Input.mousePosition : Vector3.zero;
149 joyStickDown.gameObject.SetActive(isPress);
150 joyStickDown.position = camera.ScreenToWorldPoint(mouseStartPos);
151 }
152
153 //鼠标移动
154 void CheckMouseDir()
155 {
156 if(isMousePress)
157 {
158 mouseDir = Input.mousePosition - mouseStartPos;
159 mouseSpeedRate = Mathf.Min(mouseDir.magnitude / MOUSE_RADIUS, 1);
160 move_dis = mouseSpeed * mouseSpeedRate * Time.deltaTime * mouseDir.normalized;
161 target.position += move_dis;
162 joyStickUp.localPosition = mouseDir.normalized * mouseSpeedRate * MOUSE_RADIUS;
163 }
164 }
165
166 //确定移动方向
167 void CheckMoveDir()
168 {
169 moveDirValue = 0;
170 //确定方向
171 if(isUpPress)
172 {
173 moveDirValue += (int)MoveDir.Up;
174 }
175 if (isDownPress)
176 {
177 moveDirValue += (int)MoveDir.Down;
178 }
179 if (isLeftPress)
180 {
181 moveDirValue += (int)MoveDir.Left;
182 }
183 if (isRightPress)
184 {
185 moveDirValue += (int)MoveDir.Right;
186 }
187 }
188
189 //检测是否可以移动
190 void CheckMove()
191 {
192 //某些情况下可能禁止移动,例如暂停,播放CG等
193 if(canMove && moveDirValue != (int)MoveDir.None)
194 {
195 PlayerMove(target, speed);
196 }
197 }
198
199 //移动
200 void PlayerMove(Transform target, float speed)
201 {
202 move_dis = speed * Time.deltaTime * GetSpeedDir();
203 target.position += move_dis;
204 }
205
206 //速度向量
207 Vector3 GetSpeedDir()
208 {
209 switch(moveDirValue)
210 {
211 case (int)MoveDir.Up:
212 move_speed_dir = MOVE_UP;
213 break;
214 case (int)MoveDir.Down:
215 move_speed_dir = -MOVE_UP;
216 break;
217 case (int)MoveDir.Left:
218 move_speed_dir = -MOVE_RIGHT;
219 break;
220 case (int)MoveDir.Right:
221 move_speed_dir = MOVE_RIGHT;
222 break;
223 case (int)MoveDir.UL:
224 move_speed_dir = MOVE_UP - MOVE_RIGHT;
225 break;
226 case (int)MoveDir.UR:
227 move_speed_dir = MOVE_UP + MOVE_RIGHT;
228 break;
229 case (int)MoveDir.DL:
230 move_speed_dir = -MOVE_UP - MOVE_RIGHT;
231 break;
232 case (int)MoveDir.DR:
233 move_speed_dir = -MOVE_UP + MOVE_RIGHT;
234 break;
235 }
236 return move_speed_dir.normalized;
237 }
238
239 //开火
240 public const KeyCode INPUT_FIRE = KeyCode.Space;
241 //开火时间cd
242 public float fireCD = 0.5f;
243 //上次开火时间
244 float lastTime = 0;
245 //当前时间
246 float curTime = 0;
247
248 void CheckFire()
249 {
250 if(isFire)
251 {
252 Fire();
253 }
254 }
255
256 void Fire()
257 {
258 curTime = Time.time;
259 if(curTime - lastTime > fireCD)
260 {
261 //创建子弹
262 CreateBullet();
263 lastTime = curTime;
264 }
265 }
266
267 //画布
268 public Canvas canvas;
269 //创建子弹
270 void CreateBullet()
271 {
272 GameObject bullet = Instantiate(prefabBullet, target.localPosition, target.rotation);
273 bullet.transform.SetParent(canvas.transform, false);
274 }
275 }

还是之前的移动代码,增加了

这里是需要先把Bullet制作成Prefab预制体,使用Resources.Load方法载入子弹prefab

在Project下创建文件夹Resources(必须用这个才可以载入)下面Prefab里面都是做好的预制体,做法就是把Hierarchy下的对象直接拖到Prefab文件夹下(请无视与本例无关的东西)

ChangeKeyPressState()方法里面增加判断开火的按键,FixedUpdate里面检测是不是开火,if里面可以加很多条件,比如CG时候不能开火,没有子弹不能开火等等。

Fire()这个方法里面记录了开火的当前时间,下次开火的时候判断是不是已经过了CD时长,不然按住按键,每帧都会开火,火力太猛没法玩了,氪金大佬专属。

CreateBullet()这里面使用了Instantiate这个自带的方法,通过前面载入的子弹预设体prefab可以克隆出bullet(就是通过模版复制的过程)

切记要把bullet的父物体设置成Canvas,就是通过代码把bullet放到canvas下面,不然你子弹可能不在UI里面哦~

SetParent()方法的第二个参数用false,这样可以保证bullet的size不会因为父节点变化而变化。好奇的话,你可以写成true试试

来试试发射子弹,打到敌人就消失了。

 

 

不过这敌人木头人太愣了,给他点反应吧,enemy1上添加脚本enemy1(脚本名字你随便起)

 1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4
5 public class Enemy : MonoBehaviour {
6 void ByHit()
7 {
8 Debug.Log("byHit");
9 this.transform.Translate(Vector2.one);
10 }
11 }

就写一个方法,被揍了,效果就是朝着vector2.one也就是(1,1)这个方向移动。你想让有啥反映就在这里写就可以,想变大变小变色都没问题

那么怎么才能被调用呢?

1 void OnTriggerEnter2D(Collider2D other)
2 {
3 Debug.Log("enter");
4 if (other.gameObject.tag == "Enemy")
5 {
6 other.gameObject.SendMessage("ByHit");
7 Destroy(this.gameObject);
8 }
9 }

刚才子弹的碰撞里面,增加sendMessage这个方法,参数是被调用方法的名字。这样就可以调用到碰撞的对方身上的脚本里面的”ByHit”这个方法

虽然敌人暂时还不能反击,不过起码不那么木讷了∠( ᐛ 」∠)_

敌人怎么反击的话,大家自己发挥想象力去做就好了,让他发出散弹打你也是可以的哦~

但愿你可以不用参考这个工程就能自己做出来https://pan.baidu.com/s/1e9rQIJt8AYDgHVPvbyJEuQ

 

不过,这个敌人为啥打不死呢?!哦,因为他没有血条啊!那咋整啊?下一篇介绍制作通用进度条(血条)(= ̄ω ̄=)

以上就是:unity零基础开始学习做游戏(四)biu~biu~biu发射子弹打飞机 的全部内容。

本站部分内容来源于互联网和用户投稿,如有侵权请联系我们删除,谢谢。
Email:[email protected]


0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论