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

  主角都能移动了,那不得做点什么伸张正义,守护世界和平的事嘛,拿起家伙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

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

转载于:https://www.cnblogs.com/agamer/p/9003622.html

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

  1. unity零基础开始学习做游戏(五)看看你的完成度,进度条了解一下?

    -------小基原创,转载请给我一个面子 上回书说道,英雄和魔王都做完了,子弹也能发射了,就是不知道啥时候能干死魔王.那小基得做个血条来展示一下,他离死不远了(•౪• ) 其实血条也可以看作是进度条 ...

  2. 零基础如何学习3DMax游戏建模?看完你又了解多少呢?

    什么是游戏3D建模 在大型的游戏研发公司,3D建模是一个非常大的职能,分为4个岗位:3D角色低模手绘,3D场景低模手绘,次世代角色高模,次世代场景高模.通常我们所说的3D建模是指低模手绘. 零基础可以 ...

  3. SQL零基础入门学习(十四)

    上篇:SQL零基础入门学习(十三) SQL NULL 值 NULL 值代表遗漏的未知数据. 默认地,表的列可以存放 NULL 值. 如果表中的某个列是可选的,那么我们可以在不向该列添加值的情况下插入新 ...

  4. 零基础怎样学习3d游戏建模,职业前景怎么样?

    在确定要入行学习时,要确定你需要进入哪个行业,像我当初学习的时候就选择了游戏次时代建模一样. 有不少人说学3D建模直接去购买书籍学就可以了,其实学任何技术就好比建筑打地基,如果你地基不打扎实,那是不可 ...

  5. Innovus零基础lab学习全面复盘总

    Innovus零基础lab学习全面复盘总结(附完整版pdf) 文章右侧广告为官方硬广告,与吾爱IC社区无关,用户勿点.点击进去后出现任何损失与社区无关. 为了让各位训练营学员更快入门数字 IC 后端, ...

  6. 学习次世代游戏建模需要了解什么?零基础成为次世代游戏设计师需要哪些阶段

    次世代这个名词一直伴随着游戏机产业.从字面上看,次世代游戏就是"下一个游戏"的日文字面内容.如今众多的游戏都被冠以"次世代",但是"次世代" ...

  7. 零基础如何学习游戏3D建模,要学些什么内容?学多久?

    一.什么是游戏3D建模在大型的游戏研发公司,3D建模是一个非常大的职能,分为4个岗位:3D角色低模手绘,3D场景低模手绘,次世代角色高模,次世代场景高模.通常我们所说的3D建模是指低模手绘. 二.零基 ...

  8. SQL零基础入门学习(四)

    SQL零基础入门学习(三) SQL INSERT INTO 语句 INSERT INTO 语句用于向表中插入新记录. SQL INSERT INTO 语法 INSERT INTO 语句可以有两种编写形 ...

  9. python新手教程 从零开始-Python零基础从零开始学习Python十分钟快速入门

    原标题:Python零基础从零开始学习Python十分钟快速入门 学习Python的,都知道Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.Python是一种动态解释型的 ...

最新文章

  1. Modus串行链路系统电气特性:2线-Modus、4线-Modus、RS232-Modus和RS485-Modus的特性
  2. 【 Linux 】创建一个文件夹并在此文件下创建一个c源文件
  3. git拉取单个文件_Git拿来就用
  4. 【算法竞赛学习】金融风控之贷款违约预测-数据分析
  5. 在 ASP.NET Core 中使用 Serilog 使用 Fluentd 将日志写入 Elasticsearch
  6. wow工程修理机器人图纸_工程的修理机器人图纸是哪里弄来的……
  7. 亚马逊的新Linux发行版对红帽造成了威胁
  8. 代码逻辑分析_双十一模块 79.34% 的代码是怎样智能生成的
  9. wamp2.2c集成环境搭建网站问题总结
  10. 6.2016年国赛A题“系泊系统的设计”
  11. c#元胞自动机_元胞自动机+生命游戏
  12. UE高级性能剖析技术(三)-- Android内存分布和优化
  13. 等保备案和通信网络单元定级备案的五大区别讲解
  14. 阿里云centos环境之vsftpd安装(十五)
  15. 单核cpu多核cpu如何执行多线程
  16. html背景渲染原理(body透明渐变)
  17. find -perm 里的 + -的含义
  18. anaconda 代码提示,Anaconda安装OpenCV没有自动代码补全
  19. java调用其他java项目的Https接口
  20. 关于对《Spring Security3》翻译 (第一章 - 第三章)

热门文章

  1. 液晶屏ESD防护解决方案
  2. 【亲测有效】解决PPT里多个图片无法使用组合功能
  3. java读取qq邮箱邮件
  4. Mac系统下MySQLWorkbench出现no connection established问题
  5. python 处理锯齿波信号
  6. 大魔王程序员生成记#01#C语言基础
  7. wince 串口 编程
  8. 嵌入式软件管培生每日总结-第1天
  9. 如何使用 IntelliJ IDEA中配置PHP开发环境 及项目搭建
  10. 免费好用的录屏软件OBS-Studio