篇首语:本文由编程笔记#小编为大家整理,主要介绍了Ruby‘s adventureUnity期末上机考试题目预测与解析(6/17已更新)相关的知识,希望对你有一定的参考价值。
说明:针对于6月18日Unity上机考试,不少同学问我有关考试怎么弄,为此写一篇博客讲一下我自己的理解。
考试内容:Ruby‘s adventure案例的修改,老师给完整案例后在完整案例的基础上按照老师的要求添加三个功能,也可以自行添加功能,老师要求的功能必须添加,不会的可以自己加功能,老师给给分,但是不会有原来的高。
举个栗子🌰,老师三个要求每个要求10分共三十分,我只会两个,另一个我不会,但是我自己加了一个功能,老师觉得我那个功能还行,给了我8分,那么我最后就是20+8=28分。
由于学的东西比较简单,所以考得也不会很难,按照老师之前说的话,结合大家技术水平,考题预测如下:
场景内机器人计数功能:如下图所示
包括:1.未被修复的机器人存在的数量;2修复的机器人的数量.
接受任务计时以及完成任务结束计时功能 || 整个游戏的计时功能
图中当Ruby跟青蛙对话后开始计时,由于GIF上传的大小有上限这里就截图了,不然有动图。
场景中计时计数相应GUI的添加:如上图所示
机器人发射子弹:
机器人发射的子弹对Ruby会造成伤害
退出游戏功能//重玩功能
机器人修复功能:在一段时间内攻击机器人两次,否则机器人会自动回血。举个栗子🌰,我要在两秒钟内击打机器人两次才算修复机器人,从我打了机器人开始后的两秒,这两秒内我没有打机器人,那么机器人就自动回血,也就是说我要修复他,还得打他两次,且要在两秒内。
代码数值的修改:1.陷阱对Ruby造成的血量更多或更少;2.草莓恢复的血量更多或更少;3.机器人被击打修复的次数;4.无敌时间的修改;5.重生位置的修改。
改变机器人的行走路线:使其不仅可以上下行走也可以左右行走,可以随时转换
机器人也可以伤害Ruby
子弹限制功能 || 子弹包拾取功能
大体上我先例举一些考得可能性比较大的,在这里面的1、3、4、5、7、8、9中可能会出考题,一个题目可能会包含多个考题,举个栗子🌰:比如要你弄个计数的功能,那计数了就得显示出来,相应的就会要你弄GUI那么这个题目就包含了1、3两个题目。
当然,如果这些题目没有考到,那么也可以作为自己的功能添加上去,也能加分,只是加得没那么多,过还是没问题的。
1.场景内机器人计数功能:这个计数的数据我们上课已经做好了,只需要找出来显示出来就行了,在我们的脚本里面找到一个脚本,名为NPCDialog,在其中我们可以发现一个函数
public void displayDialog()
{
if (b != 1)
{
a = 1;
Dialog.SetActive(true);
timer = displayTime;
UIHealthBar._instance.hasTask = true;
if (UIHealthBar._instance.fixnum >= 4) //就是这行UIHealthBar._instance.fixnum >= 4
{
DialogText.text = "Thanks you , you are good!";
b = 1;
if (!hasCompleteTask)
{
audiosource.PlayOneShot(CompleteClip);
hasCompleteTask = true;
}
}
}
}
这句代码的意思就是当修复的机器人大于4个后,就可以执行if里面的代码,我们可以找到其原本的脚本,也就是UIHealthBar,发现此脚本已经被实例化,同时有两个参数,一个是修复好的机器人数量,一个是未修复好的机器人数量,且此脚本被实例化,能够被其它脚本调用,那这就很好办了。
那么我们只需要在我们修复好机器人后将修复好的数值加加,未被修复好的数组减减即可,为此我们找到控制机器人的脚本,找到修复的函数,加上对应的代码即可:
接下来就得让它显示出来,为此我们要自己加代码,方法很多,我是自己新建了一个脚本写的,关健代码如下:
public Text norepaire; //未修复机器人计数的文本框
public Text repaire; //修复机器人计数的文本框
public int isRepair = 0;
public int noRepair = 7;
public Text time; //场景计时
float timer = 0;
private void Start()
{
}
private void Update()
{
//这里下面
if(NPCDialog._instance.a==1)
if (NPCDialog._instance.b!=1)
{
timer = timer + Time.deltaTime;
}
//这里上面不用写 这是我加的任务完成计时功能,想加也可以,我会把我的NPCDialog相关代码给大家
isRepair = UIHealthBar._instance.fixnum;
noRepair = UIHealthBar._instance.unfixumn;
repaire.text = isRepair.ToString() + " 个";
norepaire.text = noRepair.ToString() + " 个";
Debug.Log("isRepair: "+isRepair);
time.text = timer.ToString("f1") + " s";
}
NPCDialog相关代码:a,b是我设置的参数来控制计时的,逻辑自己看,解释有点麻烦
public void displayDialog()
{
//a,b自己定义 类型public int 初始值为0
if (b != 1)
{
a = 1;
Dialog.SetActive(true);
timer = displayTime;
UIHealthBar._instance.hasTask = true;
if (UIHealthBar._instance.fixnum >= 4)
{
DialogText.text = "Thanks you , you are good!";
b = 1;
if (!hasCompleteTask)
{
audioSource.PlayOneShot(CompleteClip);
hasCompleteTask = true;
}
}
}
}
最后在场景里面摆放好UI,然后将文本框拖拽给你新建的脚本即可:(Camera Fellow是我自己新建的脚本)
2.机器人发射子弹:当Ruby进入到机器人的攻击范围,机器人向Ruby发射子弹
方法:范围检测,射线检测(99%的都是范围检测,除非不会就搬运与青蛙对话的射线检测)
实现步骤:
(1)新建一个空对象并重命名,并给其给添加一个范围检测的collider 2D,我是用的圆形collider,添加脚本,我的脚本名是AttackRuby,记住要勾上is Trigger,可以自行修改检测范围
(2)AttackRuby脚本的编写:这个不需要像我那么复杂,我那纯粹是为了好玩,实现的效果如下,进入攻击范围后就会攻击,离开后不会攻击效果图如下
我么可以修改代码里面的一些数值来修改发射子弹的速度
public GameObject Ruby_vector2;
public GameObject BulletPrefab;
public Rigidbody2D RubyRigidbody2D;
public float N = 50; //射击速度
bool isAttack = false; //模式1触发
void Update()
{
//Ruby进入检测范围后 isAttack变为true 同时time开始计时
if(isAttack)
{
time = time + Time.deltaTime;
if(time>=0.25)//当time>0.25s 调用函数发射子弹 同时time=0 开始重新计时 这里设置射击间隔
{
Launch();
time = 0;
}
}
private void Launch()
{
GameObject bullet = Instantiate(BulletPrefab, transform.position, Quaternion.identity); //Quaternion.identity 没有角度 (0,0,0)
//生成一个预制体
bullet.GetComponent<bullet>().Lauch(RubyRigidbody2D.position&#43;Vector2.up*2, N);
// bullet.GetComponent
//获取生成物体子弹上的脚本bullet&#xff0c;并调用其发射函数Lauch,里面的参数为位置&#xff0c;发射速度
//在这里我们要改一下发射的位置&#xff08;方向&#xff09;,改为Ruby的位置
//再说明一下&#xff0c;由于每个人的场景大小不同&#xff0c;Ruby大小也有偏差&#xff0c;加上Ruby的中心在脚下&#xff0c;为了让子弹能够打到Ruby&#xff0c;我们需要对其位置微调&#xff0c;也就是向上调整一段距离&#xff0c;加一个vector2.up乘以一个数值&#xff0c;这个数值每个人因人而异&#xff0c;大体上差不多
}
private void OnTriggerEnter2D(Collider2D collision)//进入范围攻击
{
//将Ruby的标签改为Ruby
if(collision.tag&#61;&#61;"Ruby")
{
isAttack &#61; true;
}
}
private void OnTriggerExit2D(Collider2D collision)//离开范围不攻击
{
if (collision.tag &#61;&#61; "Ruby")
{
isAttack &#61; false;
}
}
我们攻击时是攻击Ruby的中心&#xff0c;而Ruby的中心在脚部&#xff0c;所以我们得微调&#xff1a;
说明&#xff1a;你在完成这个东西的时候会发现&#xff0c;子弹会有些许偏差&#xff0c;原因是因为在Ruby移动的过程中其Rigidbody2D位置发生了改变&#xff0c;所以会有偏差&#xff0c;如果是换成我下面注释的代码后&#xff0c;就不会出现&#xff0c;但是射击中心不太准&#xff0c;在Ruby的脚部&#xff0c;这个时候我们就需要改变Ruby位置的中心&#xff0c;我花了一些时间做了修改&#xff0c;包括代码的形式&#xff0c;调整Sprite Renderer的相关参数&#xff0c;都没有用&#xff0c;主要是因为这不是一个image&#xff0c;按理来说将Piovt修改成Center就没事了&#xff0c;但是没有成功&#xff0c;应该是需要在最开始的Ruby上进行修改&#xff0c;但是我的Ruby已经修改过了&#xff0c;没有原版了&#xff0c;就先放在这里&#xff0c;也有可能是需要在项目设置里面去进行调整&#xff0c;当然了如果你成功的调整好了可以在评论下方提出你的见解&#xff0c;我调整好后也会第一时间更新。
正常的位置&#xff1a;
最后赋值即可&#xff1a;预制体就是子弹
附加说明&#xff1a;当然了也可以给Ruby身上面加一个空物体&#xff0c;将其的位置赋值给目标&#xff0c;调整空位置的位置到Ruby中心&#xff0c;这个理论上是可以的&#xff0c;实践上还是有问题&#xff0c;个人觉得还是跟脚本有问题&#xff0c;后面再改吧。
3.子弹对Ruby造成伤害&#xff1a;
这个有很多方法&#xff1a;1.可以给Ruby写代码&#xff1b;2.可以个给子弹写代码&#xff1b;
原理&#xff1a;碰撞检测&#43;传参
方法&#xff1a;当然了&#xff0c;这里推荐一个很简单的方法&#xff0c;找到子弹预制体&#xff0c;为其添加一个我们写好了的陷阱脚本即可&#xff0c;脚本名为&#xff1a;
相关提示与说明&#xff1a;由于有陷阱有无敌功能&#xff0c;如果题目要求子弹打中就掉血&#xff0c;没有无敌功能&#xff0c;那么我们就需要进行适当修改&#xff1a;
他是通过调用Ruby脚本中的changehealth方法来修改血量的&#xff0c;对此我们要修改的话就需要找到对应的函数进行修改&#xff0c;修改changehealth
陷阱脚本中调用的方法&#xff1a;
Ruby脚本中修改血量的方法&#xff1a;
当然了&#xff0c;具体题目怎么样改&#xff0c;改不改我也说不准&#xff0c;告诉大家怎么改。
也可以自己通过添加脚本的形式来修改血量&#xff0c;但是要注意两个事情&#xff1a;
1.利用碰撞检测
2.调用changehealth&#xff08;可以用老师的&#xff0c;也可以自己写改变血量的脚本&#xff09;
3.最后调用UIHealthBar._instance.SetValue(Mathf.Lerp(a / (float)maxHealth, b / (float)maxHealth,1f));
来修改血量的显示
在这里我就不做过多说明。
4.退出游戏功能 || 重玩功能
退出游戏的函数&#xff1a;
public void GetExit()//退出运行
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying &#61; false;//用于退出运行
#else
Application.Quit();
#endif
}
随便写在一个脚本里面&#xff0c;再在场景外面弄一个Button&#xff0c;点加号
将你添加这个退出函数的脚本的物体拖拽给他&#xff0c;在下拉菜单中找到脚本名称&#xff0c;找到对应函数即可&#xff0c;我这里举个&#x1f330;
游戏的重玩&#xff1a;
首先需要在Bulit setting里面找到对应的设置
记住每个场景后面的编号&#xff0c;没有当前场景的就添加场景
和退出函数的调用方法一样&#xff0c;在脚本中的引用加上&#xff1a;
using UnityEngine.SceneManagement;
顺便说一下&#xff0c;用了图片和文本框的需要引用&#xff1a;
using UnityEngine.UI;
然后写下函数&#xff1a;
public void PlayeAgain()
{
SceneManager.LoadScene(1); //你要重玩的/加载的场景编号&#xff0c;看上面图
}
用button来调用此方法&#xff0c;与退出游戏相似
5.机器人自动回血&#xff1a;
逻辑&#xff1a;第一发子弹攻击后的两秒内如果不再进行下一次攻击&#xff0c;机器人要被修复&#xff0c;需要被击打两次
实现流程&#xff1a;
1.给机器人添加一个碰撞检测的代码&#xff0c;检测第一次攻击&#xff0c;当检测第二次攻击后再调用修复函数
当hit>&#61;2时调用被修复&#xff0c;每次击打一次就hit&#43;&#43;
2.当第一次被击打后&#xff0c;isRepairing变为true&#xff0c;开始计时
JishiTime的初始值为2s&#xff0c;如果在两秒内没有修复好的话&#xff0c;hit&#61;0&#xff0c;机器人回血&#xff0c;jishiTime&#61;2&#xff0c;同时isRepairing&#61;false&#xff1b;停止计时&#xff0c;以此来达到一个自动回血的效果&#xff0c;下面的代码写在Update里面&#xff0c;每时每刻都要检测&#xff0c;方法很多&#xff0c;我的思路大致是这样&#xff0c;之前帮人改东西&#xff0c;把我的代码给改坏了&#xff0c;现在演示不出来&#xff0c;应该没有什么问题。
没有的参数自己看类型定义一下&#xff01;&#xff01;&#xff01;
6.改变机器人的行走&#xff1a;
原理&#xff1a;跟机器人自动回血差不多&#xff0c;设置一个计时功能&#xff0c;计时结束后&#xff0c;将其vertical改为false即可&#xff1a;
时间问题我就不多说了&#xff0c;这里我现在写了4个小时了
7.机器人伤害Ruby&#xff1a;给机器人添加陷阱脚本&#xff0c;改变一下collider的范围&#xff0c;类似于解析2
8.子弹限制功能 || 子弹包拾取功能
&#xff08;1&#xff09;把子弹包拖拽进场景中&#xff0c;调整好其大小&#xff0c;为其添加box collider 2D&#xff0c;勾上 is trigger
&#xff08;2&#xff09;为子弹包添加脚本&#xff1a;我起名为BulletPag&#xff0c;其代码如下
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag&#61;&#61;"Ruby")
{
//给Ruby打上标签为Ruby
PlayerMove playermove &#61; collision.GetComponent<PlayerMove>();
playermove.bulletnum &#61; playermove.bulletnum &#43; 30;
Destroy(this.gameObject);
}
}
在Ruby的脚本中添加相关代码&#xff1a;
定义变量部分&#xff1a;定义子弹数和显示子弹数的文本框
public Text bulletnumText;
public int bulletnum &#61; 30;
Update函数中&#xff1a;显示剩余子弹数
bulletnumText.text &#61; bulletnum.ToString()&#43;"个";
修改部分&#xff1a;
if(bulletnum>0) //当子弹数大于零才能发射子弹&#xff0c;一开始子弹数是30&#xff0c;不影响其他功能&#xff0c;因为有一个地方是要跟青蛙对话后才能够发射子弹的功能
if (Input.GetKeyDown(KeyCode.Space))
{
Launch();
bulletnum--; //发射一次子弹子弹数减少
spark.Play();
}
再在场景外面设置UI&#xff1a;
并把相应的文本框拖拽给脚本&#xff1a;上面定义了一个Txet文本框
拓展&#xff1a;这里面还可以加上换弹夹的功能&#xff0c;简答说一下&#xff0c;当子弹发射完后&#xff0c;并且还有剩余子弹&#xff0c;那么需要按下一个按键后才能够按下空格键发射子弹&#xff0c;需要在加上一个子弹计数变量来存储子弹剩余数&#xff0c;按下键后相应的减少对应的数&#xff0c;子弹数相应的加上相应的数&#xff0c;还有很多可以修改的地方&#xff0c;我就不一一细说了。
1.这个案例的代码有些地方是我自己写的&#xff0c;和老师写的不一样&#xff0c;大同小异&#xff0c;所以可能你照着我的写&#xff0c;在涉及到老师的代码时&#xff0c;可能会出错&#xff0c;但是概率还是很小&#xff0c;也不排除自己的原因打错看错出错&#xff0c;主要参考看我的逻辑和方法。
2.个别地方省略了一些很简单的步骤&#xff0c;加UI的地方就不多说了
3.不是要知道整个代码才能做出来&#xff0c;知道逻辑和一些关键代码也能够写出来
1.考试应该不会很难&#xff0c;所以不需要太慌张&#xff0c;这里推荐给你一个完整的Ruby教程&#xff0c;你觉得我的不太行&#xff0c;你也可以从这里面去学习一些东西&#xff1a;点击跳转&#xff1a;Ruby官方案例完整版
2.要明白代码的意思和逻辑&#xff0c;明白一些操作为什么要那么操作&#xff0c;如果不那么操作那么写会产生什么结果&#xff0c;这对于日常学习尤为重要
3.养成独立思考的习惯&#xff0c;遇事后自己先独立思考&#xff0c;不到万不得已实在没办法绝不向别人求助&#xff0c;培养自己的钻研精神&#xff0c;有些东西仔细自己想想并不难&#xff0c;不要养成过渡依赖别人的习惯
4.本次考试为开卷考试&#xff0c;可以提前做好一些功能&#xff0c;把相关代码写在纸上&#xff0c;带入考场&#xff0c;如果觉得本篇内容还行&#xff0c;也可以将本篇内容打印出来带入考场&#xff0c;
5.祝大家考试顺利&#xff01;
前言&#xff1a;这两天同学们可能试了一下我的子弹发射功能&#xff0c;但是大家可以发现&#xff0c;他并不是很准确&#xff0c;特别是在斜对角的时候&#xff0c;偏差太大&#xff01;&#xff01;&#xff0c;只有在正上、下、左、右的方向是比较准的&#xff0c;这就让我想起了一个问题&#xff01;没错&#xff0c;就是方向的问题&#xff01;&#xff01;&#xff01;&#xff01;
我们之前的代码如下&#xff1a;
bullet.GetComponent<bullet>().Lauch(RubyRigidbody2D.position&#43;Vector2.up*2, N);
bullet.GetComponent<bullet>().Lauch(AttackVect, N);
大致一看&#xff0c;诶&#xff0c;确实没啥问题&#xff0c;发射的时候&#xff0c;里面的参数是一个方向×速度&#xff1b;这里的方向参数我给的是一个二维的点&#xff0c;不管是Rigdbody2D 还是 Transform.position 都是一样&#xff0c;但是都有一个问题&#xff0c;不准&#xff01;&#xff01;&#xff01;
这就要涉及一些数学问题了&#xff0c;不得不说&#xff0c;数学还是挺有用的&#xff0c;这里面就用到了一些数学知识&#xff0c;首先&#xff0c;我们为什么发射不准呢&#xff1f;我们首先要明白&#xff0c;我们这个2D游戏他是有世界坐标系的&#xff0c;二维的坐标系&#xff0c;那二维坐标系怎么来表示方向呢&#xff1f;向量啊&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;我们之所以射击不准&#xff0c;是因为我们给的方向是一个点的坐标&#xff0c;而不是一个方向向量&#xff0c;而且Ruby和发射子弹的坐标位置相对于游戏中的坐标原点是不一样的&#xff0c;因为在不同的参考坐标系中&#xff0c;所以射不准就很正常了&#xff0c;这也就解释了为什么在正方向的时候&#xff0c;它就不影响&#xff0c;因为正方向是当x轴等于0或者是y等于0的时候&#xff0c;所以只有在正方向的时候才准点。
那么我们以发射点为坐标原点记为A&#xff08;0&#xff0c;0&#xff09;&#xff0c;Ruby的二维坐标为B&#xff08;X&#xff0c;Y&#xff09;,那么由向量的知识我们知道&#xff0c;我们需要的方向是AB向的&#xff0c;那么就需要B-A&#61;AB&#xff1b;
更新后的代码如下&#xff1a;
public GameObject Aim;
public GameObject BulletPrefab;
public float N &#61; 50;
bool isAttack &#61; false; //模式1触发
private Vector2 RubyVect;
private Vector2 AttackVect;
float time&#61;0;
void Update()
{
RubyVect.x &#61; Aim.transform.position.x; //获取目标点的X坐标
RubyVect.y &#61; Aim.transform.position.y; //获取目标点的y坐标
AttackVect.x &#61; RubyVect.x - this.transform.position.x; //两坐标相减 得出一个向量 表示方向
AttackVect.y &#61; RubyVect.y - this.transform.position.y; //两坐标相减 得出一个向量 表示方向
//两个方向向量合并成一个指向Ruby的方向向量
if (isAttack)
{
time &#61; time &#43; Time.deltaTime;
timer &#43;&#61; Time.deltaTime;
if(time>&#61;0.25)
{
Launch();
time &#61; 0;
}
}
}
private void Launch()
{
GameObject bullet &#61; Instantiate(BulletPrefab, transform.position, Quaternion.identity); //Quaternion.identity 没有角度 (0,0,0)
bullet.GetComponent<bullet>().Lauch(AttackVect, N); //方向向量✖力
}
另外我也查了这个子弹发射的文档&#xff0c;是个矢量&#xff0c;前几天没仔细看&#xff0c;不然也就解决了。
然后大家需要建一个空对象&#xff0c;将空对象绑定到Ruby身上&#xff0c;调节他的位置到Ruby的中心&#xff1a;
记住将其拖拽个修改后的脚本&#xff1a;
看一下效果&#xff1a;
妥妥的不管在哪里都射击到了Ruby的中心&#xff0c;解决了以前的问题&#xff01;这个还是比较简单的数学问题&#xff0c;后面做东西的时候还会遇到很多类似的问题&#xff0c;包括渲染&#xff0c;角度的计算&#xff0c;所以学好数学很重要&#xff01;&#xff01;
芜湖&#xff0c;懂了就点个赞吧O(∩_∩)O哈哈~