PlayMaker:触发事件

事件(event)的触发是PlayMaker交互设计的基础。


鼠标(mouse)、键盘(keyboard)、按钮(button)触发

这类触发逻辑的原理是:
当用户通过输入设备(比如鼠标、键盘、触碰屏、手柄等)向游戏发送信息时(比如按键被按下、滚轮被拨动等等),触发指定event并通过该event实现状态改变。

PlayMaker中Input类别下的动作列表

这类触发事件的相关动作可以在PlayMaker的Input Actions中找到。


1. 鼠标(mouse)

GetMouseButton.png
GetMouseButtonDown.png
GetMouseButtonUp.png
  • GetMouseButton
    单纯检测鼠标按键是否被按下,并将结果储存在一个bool变量中
  • GetMouseButtonDown
    在鼠标按键被按下时立刻触发指定event
  • GetMouseButtonUp
    在鼠标按键被松开时立刻触发指定event

我们可以在PlayMaker中检测到的鼠标按钮包括:Left、Middle、Right、None。

注意:MouseButtonDown不等于鼠标单击。鼠标单击代表快速执行按键的按下和松开两个操作。如果一定需要检测“单击”输入操作,需要使用多个state来设计一个简单的逻辑:

pm_click_detaction01.png
pm_click_detaction02.png
pm_click_detaction03.png
  • State 1检测按键是否被按下
  • State 2检测按键是否被松开,但添加了一个短暂的计时器(使用wait动作),在时限内如果按键松开,单击操作成立,触发LMB down事件
  • 如果在短暂的时间间隔内(比如0.1s)按键没有被松开,说明单击操作不成立,触发cancel事件
  • 因为cancel事件导致State 2休眠,所以之后即便再松开按键也不再会触发LMB down事件了

触发检测到按键松开则跳转到“单击”所触发的目标状态,同时在State 2中设定一个计时器,设置一个短暂的时间间隔(比如0.1s),一旦超过时间间隔,立即跳转到“


2. 键盘(keyboard)

AnyKey.png
GetKey.png
GetKeyDown.png
GetKeyUp.png
  • AnyKey
    任何按键被按下都会触发event
  • GetKey
    单纯检测一个按键是否被按下,并将结果储存在一个bool变量中
  • GetKeyDown
    在指定按键被按下时立刻触发指定event
  • GetKeyUp
    在指定按键被松开时立刻触发指定event

指定按键比较麻烦,要从一个很长的列表中选择,这也算是“可视化”带来的弊端之一吧。

3. 按钮(Button)

GetButton.png
GetButtonDown.png
GetButtonUp.png
  • GetButton
    单纯检测一个按钮是否被按下,并将结果储存在一个bool变量中
  • GetButtonDown
    在指定按钮被按下时立刻触发指定event
  • GetButtonUp
    在指定按钮被松开时立刻触发指定event

注意,按钮名称需要自行输入,必须严格与Input面板中的名称对应,请注意大小写规范以及是否空格。

按钮(Button)的概念在Unity3D中比较特殊。并不一定专指鼠标按键、键盘或者手柄,而是通过预先的定义可以囊括一系列不同的按键,以方便使用。

从菜单Edit > Project Settings > Input可以打开Input面板:

unity_menu_input.png

这里指定了18个不同的Axes,可以理解为“轴向值”。Name是这个轴向的名称,Positive ButtonAlt Positive Button中所指定的按键被按下时,该轴向的值迅速增长到1,Negative ButtonAlt Negative Button中所指定的按键被按下时,该轴向的值迅速减少为-1,无任何按键被按下时,轴向值迅速归0。

而Button就是指的轴向中所规定的所有按键。比如这个叫做Horizontal的轴向,我们可以理解为“横向输入按钮”,当键盘leftright键或ad键被按下时,就相当于“横向输入按钮”被按下了。

我们经常会使用到的Button有:

  • 使用Horizontal、Vertical来设置运动方向或旋转方向
  • 使用Fire1来控制攻击行为
  • 使用Jump来控制跳跃
  • 使用Cancel来取消或者呼出游戏菜单

我们还可以自己增加更多的Axes。


碰撞(collision)触发

这类触发逻辑的原理是:
Unity3D的游戏物体可以设置碰撞边界(Collider),当有其他的带有collider组件的游戏物体进入/离开/停留这个游戏物体时,可以触发event并由此引起游戏物体的状态改变。

Collision Event行为:

CollisionEvent.png

  • Collision中所指定的情况发生,且碰撞对象带有Collide Tag中所指定的Tag时,触发Send Event中指定的事件,并可以将碰撞对象储存为一个GameObject类型变量,将碰撞力量储存为一个Vector3类型变量
  • On Collision EnterOn Collision StayOn Collision Exit三个选项针对其他碰撞体collider进入、停留、离开本碰撞体的状况
  • On Controller Collider Hit选项针对Controller类型的碰撞体与本碰撞体碰撞的状况
  • On Particle Collision选项针对与粒子物体发生碰撞的状况

Get Collision Info行为

GetCollisionInfo.png

  • 这个行为可以紧接着Collision Event行为使用,用来储存更多关于碰撞的信息,比如:碰撞物体、相对速度(vector3)、相对速度(float)、碰撞点坐标(vector3)、碰撞点法线方向(vector3)、物理材质名称。

在Collider组件上,我们可以勾选Is Trigger选项来将碰撞体变成一个触发器(trigger)。触发器和碰撞体的区别在于,触发器不会实际阻挡其他碰撞体,相当于一个虚拟的开关。

如果设置成了Trigger,不能使用Collision Event和Get Collision Info行为了,而要使用Trigger Event和Get Trigger Info行为,用法是一样的。

Trigger Event

TriggerEvent.png

Get Trigger Info

GetTriggerInfo.png

通常适合使用碰撞触发来制作的交互逻辑有:

  • 拾取游戏物体:
    将道具放置在场景中,设置成trigger类碰撞体,玩家进入碰撞体范围时触发相应事件
  • 玩家“获得”物品
  • 道具模型消失
  • 游戏积分增加
  • 启动机关:
    当碰撞发生时机关被触发,可以是“开门”、“启动升降机”、“进入下一关”等等
  • 伤害、死亡:
    当“子弹”物体与对象发生碰撞时,对对象造成伤害或者让对象死亡
  • 特效:
    当“子弹”击中对象时,从“伤口”处发射粒子特效(血、烟雾、碎片等等)

射线(raycast)触发

这类触发逻辑的原理是:
从目标点向特定方向发射一条光线(ray),然后获得这条光线与场景物体的碰撞信息。通常是从某个游戏物体沿着特定轴向(x、y、z)发射,或者是摄影机平面上某一点垂直于摄影机平面向场景发射。

Raycast是即时发生的,不论距离多远,都会在同一帧返回碰撞结果,所以适用于需要立即得到反馈的情况。

Raycast:

Raycast.png

Raycast从一个游戏物体(From Game Object)或某个点(From Position)沿着特定坐标空间(Space)某个方向(Direction)发射一条长度为Distance单位长度的探测光线,并将结果储存在相应的变量中:

  • Hit Event:如果碰到游戏物体,则触发相应事件
  • Store Did Hit:是否碰到游戏物体(bool)
  • Store Hit Object:碰撞对象物体(GameObject)
  • Store Hit Point:碰撞接触点(Vector3)
  • Store Hit Normal:碰撞法线方向(Vector3)
  • Store Hit Distance:发射点距离碰撞点距离(float)
  • Repeat Interval:射线发射频率(0代表仅发射1次;1代表每帧发射一次;2代表每两帧发射一次…)
  • Layer Mask:可以指定仅探测与特定层中的物体之间的碰撞
  • Debug:可以在视图中显示一条直线方便我们判断raycast是否正确

注意:ray是有长度的,在这个长度范围以内如果没有触碰到物体,那就是“没有击中”。这个长度默认为100米,如果场景过大有可能会出现距离不够而不能正确返回结果的情况。同时特定情况下也可以将这个值缩小以获得特定效果,比如游戏设定手枪射距为30米的话,就要将ray设成30。

Raycast All:

RaycastAll.png

Raycast All和Raycast用法几乎完全一样,但Raycast All会返回Ray碰撞到的所有游戏物体并返回为一个GameObject类型的数组(array)变量Store Hit Objects

Get Raycast Hit Info:

GetRaycastHitInfo.png

Get Raycast All Info:

GetRaycastAllInfo.png

这两个行为用在Raycast行为之后用以获得更多的碰撞信息。

有一些action同样基于Raycast原理,但名字中没有“ray”这个词,也没有被归类在Physics动作组中。

Mouse Pick:

MousePick.png

Mouse Pick会由鼠标屏幕二维坐标转换成摄影机平面二维坐标,再将这一坐标对应的三维空间位置沿着垂直于摄影机平面的方向发射一条长度为Ray Distance的ray,并返回碰撞结果为相应数据类型的变量值。

Mouse Pick Event:

MousePickEvent.png

Mouse Pick Event同样基于上述原理,是用来查看鼠标是否在特定游戏物体(Game Object)上,并根据不同的鼠标状态而触发不同的事件:

  • Mouse Over:鼠标划入游戏物体范围内
  • Mouse Down:鼠标在游戏物体范围内按下左键
  • Mouse Up:鼠标在游戏物体范围内松开左键
  • Mouse Off:鼠标从游戏物体范围内划出

Mouse Pick 2d与Mouse Pick 2d Event这两个行为与上两个行为完全一致,只不过专门适用于2D游戏,因为它们返回的位置坐标数据类型是Vector2而不是Vector3

MousePick2d.png
MousePick2dEvent.png

通常适合使用碰撞触发来制作的交互逻辑有:

  • FPS类游戏中的设计判定,使用Raycast来判断是否击中目标,比发射子弹后再判断碰撞要准确得多
  • 获得鼠标指向位置,并通过这个位置来指引角色运动
  • 通过鼠标与游戏物体进行互动

数据触发

关于“数据”和“数据格式”的详细介绍,可以参看《Unity3D的变量及数据类型》

数据触发的基本原理是:
通过监控数据的数值状态或数值变化,并使用各种数值比较action来触发不同的事件。

Bool Test检查一个bool变量的值,然后根据“True/False”可以触发最多2个不同的event

BoolTest.png

Int Compare和Float Compare检查两个不同的int数值或者float数值,根据“第一个数值等于/小于/大于第二个数值”可以触发最多3个不同的event

IntCompare.png

FloatCompare.png

String Compare检查两个字符串是否一致,根据“一致/不一致”可以触发最多2个不同的event

StringCompare.png

Object Compare检查两个Object(也就是组件)是否一致,根据“一致/不一致”可以触发最多2个不同的event

ObjectCompare.png

Object Compare检查两个数组是否一致(一致的意思是A数组中每一个数据都等于B数组中对应序号的数据),根据“一致/不一致”可以触发最多2个不同的event

ArrayCompare.png

Enum Compare检查两个Enum状态是否一致,根据“一致/不一致”可以触发最多2个不同的event

EnumCompare.png

Fsm State Test检查特定游戏物体上某个FSM是否正处于某个特定State,根据“True/False”可以触发最多2个不同的event

FsmStateTest.png

这些检查都可以将结果储存进一个bool变量中(Store Result)。

Every Frame选项如果被勾选,则代表该action会一直不断执行,也就是实时监控数据是否满足比较标准。如果不被勾线,则只在刚进入该state时执行一次数值比较。

在这些情况下我们通常使用这种数值触发来设计交互逻辑:

  • 角色离某个NPC的距离小于特定数值的时候,角色吸引NPC的注意,NPC开始追逐角色
  • 角色生命值小于等于0的时候,角色死亡
  • 当时间间隔超过特定数值的时候,开始执行某种操作
  • 当对象处于特定state(比如攻击僵直)的时候,指令输入不起作用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容