本博只为复习知识,纯属博主个人碎碎念,不具有普适性,大神绕道。
说了那么多碰撞器,动画,声音什么的,游戏中常见的字幕还没说过。像我们玩消消乐什么的,是不是都会有分数的变化?那这个是怎么实现的呢?
本节会设计到的有Canvas、Text和Image组件。本节要实现的是:现在要限制玩家自由地进入门中——只有在收集到了全部必要物品的情况下才可以进入门中。通过在玩家进入触发区域时,在屏幕上显示相关的提示,就能让玩家意识到他必须收集完所有能源才能进入房中。
思路如下:
添加能源:
通过预制体,拖动到Hierarchy面板产生GameObject这个就不多说了,当人碰到能量石的时候,能量石就消失,所以能量时要有碰撞器,并且是触发式的。我们想让能量石一直在旋转,因此我们写了一个脚本控制它,意思就是这个能量石绕着Y轴进行旋转:
●rotationSpeed乘上Time.deltaTime的原因还是把以帧为单位变化改为以秒为单位变化。
然后添加碰撞检测的代码:
当游戏场景中有物体进入powerCell触发器碰撞器的区域内,就会触发调用如上函数。函数首先会检测这个物体是否为玩家(Player)。
如果是玩家,我们便通过SendMessage()函数发送一个消息给玩家对象,让其执行自身(玩家对象)脚本中一个名为CellPickup的函数。最后,我们移除场景中的这个能源物体,完成拾取操作。
编写玩家脚本:
我们要把玩家当前所收集到的能源数保存到一个变量charge中,为了确保这个变量可以被其它脚本访问到,我们将把它声明为static(静态变量),静态变量是一种可以被其它脚本访问的全局变量,并且不会像公有变量一样出现在检视面板中。
这点考虑一下c++其实也是一样的, 在c++中如果该类中的某个变量想被其他类中的变量访问,一个方法就是把该变量设置为全局变量,一个方法就是把该变量设置为static。
当我们重新加载或测试同一场景时,变量值可能会被系统保留,因此我们在Start()函数中对其进行初始化,确保程序能正确运行。
在变量charge之外,我们还需添加一个公有变量,用来保存玩家收集到能源时播放声音。请在脚本中添加如下代码(箭头所指一行):
因为玩家物体上没有音频源,我们使用AudioSource.PlayClipAtPoint()命令生成一个带有音频源的临时物体,播放完音乐之后移除自己。PlayClipAtPoint的第二个参数是位置参数,我们传入的是玩家的位置。这是因为我们希望在玩家周围播放声音,也意味着,当玩家走开时,声效会渐渐地消失。
当然我们也可以像前面为door做的那样,给first person controller添加一个AudioSource组件,然后使用函数audio.PlayOneShot()来播放音频
限制岗哨的进入:
接着我们要编写代码,我们要让玩家收集到所有能源后,哨岗的门才开启。也就是当玩家当前收集的能源数为4时,才会触发门的开启,在屋子这个游戏体挂载的cs文件下,判断
你看它这里访问charge的方式,就是直接 类名.变量。和c++是一样一样的。
//.h
class Inventory{
public:
static int charge;
}
//.cpp
Inventory::charge = 0;
int main(){
if (Inventory.charge == 4)
//do something
}
//这是c++
显示能源收集情况HUD
在工程面板中的Book Assets | Textures文件夹中,保存着我们可以用来作为用户界面(UI)的图像文件。( 你可以注意到这些图片都是RGBA格式,是带不透明度的。)
这几个图像,分别代表着能源在各个阶段的状态(0~4):
我们在层次面板直接创建UI|Image
我们把整个岛缩小,可以看到,在屏幕的正中心出现了默认的白色图片。跟随一起也创建了canvas及事件系统EventSystem。
我们要把这个图片换成我们要的能源图(5种电池状态),所以接下来,我们选中刚创建的Image,在右侧的监视面板中设置 Source Image .注意这些png图片其实是Sprite
设置能源显示脚本
我们的对象需要在不同能源状态下,使用不同的图片。我们利用charge变量数值的不同来变换显示的图片。。只有在脚本中对所需要利用的UI元素进行声明,才可以将我们的能源图像传进去(作为参数)。 所以我们要在脚本内部先命名以下几个变量,用于存放我们要显示的文本及图像等元素。
其中第一行的Light类型的灯光用于之后的门灯设置(当玩家收集到所有能源后,我们需要改变门口提示灯的颜色);
第四行AudioClip类型音效用于存放按钮音效;
剩下的GameObject类型的几个都是UI层面的元素,用来存放我们的五个电池状态(hudgameobjX)和两个提供给玩家的文本提示(chargeHudGUI:提示需要收集所有能源; chargeEnoughGUI:能量已经收集满的文本提示)
当玩家搜集的能源数量分别为:0-4时,分别让对应的图片(h0 - h5)显示。而在游戏的一开始,我们不希望他们都显示,所以,我们按住shift键选定这5个物体,在监视面板内将其激活对勾取消。如下图:
为玩家提供提示
其实从字面意思GUI(graphical user interface)图形用户界面,也就是可以方便用户与游戏程序进行交互。
玩家如果不知道需要收集4个能源才能进入,我们则需要在其反复尝试进入的时候进行提示。
如何做到这样的提示,就需要应用我们的图形用户界面了。
新版本的unity可以通过canvas(画布)来实现。
一个canvas可以放置多个原件,可以是图片、文字、按钮等等。
首先,添加(create)一个新的UI | Text 。
可以得到如下,一个自动生成的画布(那么我们就可以在这个画布上制作我们的UI啦~)我们需要创建一个提示玩家需要收集所有的能源才能开门的text(起名为textEnergy)~ 和一个 已经收集满了所有能源的text(textgetall),并将这两项作为参数拖拽到脚本的chargeHudGUI和chargeEnoughGUI中实现显示了
当玩家收集了全部的能量之后,我们希望这个成功提示只显示一会儿,那就需要引入计时器了。
我们继续在Inventory1脚本中添加代码:
在上方添加时间变量timer,用来计时:
如果chargeEnoughGUI已经被激活,也就是Text组件被激活,开启计时器了。当计时器超过4秒时,我们就关闭Text组件,并且归零计时器。
确保输入无误后,保存你的脚本,回到Unity中。测试你的游戏,你会发现当你进入哨岗触发区时,屏幕会出现可进门的提示信息,并在一段时间(4s)后自动消失。
知识点补充:
- 有关canvas(画布)
我们已经知道了Canvas是用户交互界面的画布,可以放置多种展示型元素和交互性元素。
其渲染模式有三种:Screen Space –Overlay 、Screen Space – Camera、World Space.
第一种Screen Space –Overlay(屏幕空间-覆盖模式)模式的画布会填满整个屏幕空间,且画布内所有的UI元素都会被放置在屏幕的最上层。如果屏幕尺寸被改变,则画布也将会自动改变尺寸来匹配屏幕。
第二种Screen Space – Camera(屏幕空间-摄像机模式)与第一种相似,但在该模式下,画布会被放置在制定摄像机的前方。画布会看起来是绘制在一个与摄像机固定距离的平面上的。所有的UI元素都由摄像机进行渲染,因此摄像机的设置会影响UI画面。UI 元素的perspective是由视角设定的,其广度由Field of View进行设置。
第三章World Space(世界空间模式),画布会被视为和其他游戏对象相同性质的一张图片来看待,其尺寸可以通过Rect Transform 进行设置,UI元素的显示先后也都根据需要进行设定。
它会有一个Event Camera 用来制定接受事件的摄像机。该模式适合3D 类型的UI.
关于prefab
以前资源中的powerShell其实就是个fbx的模型文件,还不是一个prefab。其也没有面板来让设置size等变化。我们将其参数改了很多,然后才将之拖入到project面板中设置为了prefab。
有关SendMessage。GameObject.SendMessage向一个物体发送一个消息。
假设有两个物体 A,B 实现在A中单击鼠标左键 发送消息调用B中的方法。
A中绑定的c#代码
void Update () {
if (Input.GetMouseButton(0))
{//很多人其实在这很容易犯错误,先得找到B物体,然后再发送消息才有效果,不然会显示SendMessage has no receiver!
GameObject.Find("B").SendMessage("GetMsg");
}}
- Image和raw image两种图片类型
Image: 图片类型有四种,分别是
simple, //简单类型
sliced, //九宫切片
tiled , //平铺
filled //填充
需要注意一下:一般更改Image图片的大小都通过with和height 来进行更改,不用缩放scale的方式。这样能够减小很多可能受影响的因素(例如字体大小)。
RawImage(原始图片)类型,可以用来显示任意文理.包括RenderTexture, MovieTexture. 从网上下载一张图片一般用RawImage显示.
- richText 富态字(富文本). 这个可以让文本内容通过加xml标签来改变.
目前支持的标签:
<b>hello </b> 粗体
<i>yes </i> 斜体
<size> no</size> 字号
<color>world</color>字颜色
演示如下图: