Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • CreatiCode
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

CreatiCode Scratch Forum

  1. CreatiCode Forum
  2. 知识库
  3. 小教程
  4. 三维 - 化身与物体互动(难度:4)

三维 - 化身与物体互动(难度:4)

Scheduled Pinned Locked Moved 小教程
1 Posts 1 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • CreatiCodeI Offline
    CreatiCodeI Offline
    CreatiCode
    wrote on last edited by admin
    #1

    介绍

    在许多游戏中,玩家控制自己的化身与场景内的其他物体交互,比如撞到墙上或者拾取奖励物品。本教程将会演示三种方法:射线投射、包围盒和距离测量。

     
     

    第 1 步 - 重做起始项目

    这是为你分享的一个起始项目:https://play.creaticode.cn/projects/4a308d8eb17ad7ae526cffb4

    请改编这个项目,作为你自己的项目。

    这个项目包含了玩家可以按键控制的数字人化身,以及添加一些其他物体的代码: 一条通往平台的斜坡,皇冠和金币,以及一个圆形目标区域。

    ed5c4340-146e-451a-a0ac-39b4cf2d9c05-image.png

     
     

    第 2 步 - 基于射线投射检测与平台的碰撞

    目前,玩家的化身无法行走在斜坡或平台上。相反,它将穿过斜坡。

    g5.gif

     

    要修复这个问题,我们可以打开基于射线投射的碰撞。在 “化身” 角色中插入以下积木 (你可以通过搜索 “碰撞” 来找到这个积木):

    686f4db6-0c71-43d1-b6a0-dc675231789a-image.png

     
    注意正确设置如下参数:

    • 它是 “不可穿过的” 碰撞,这意味着化身将在产生碰撞时停止;
    • 碰撞目标是 "平台” 角色,所以化身只会与在 “平台” 中创建的物体发生碰撞,也是斜坡和平台。
    • 精度是 “下方和前方”,这样的话化身添加了两个感应射线,一个向下指向地面,一个在脚面高度指向前方。
    • “调试” 选项设置为 “是”,所以我们可以看到射线和碰撞盒子。

     
    当我们再次运行项目时,我们可以看到感应射线和一个碰撞盒子(黄色的盒子),这是三维引擎用来代表化身身体的形状。但是这里还有个问题:黄色盒子位于角色底部,并且感应射线在地面下方。

    g3.gif

     

    这是因为所有化身和模型的位置原点都在其身体的底部中点,而不是整个身体的中心点。要解决这个问题,我们只需要添加一个 “z 位移”, 将黄色盒子向上移动半个化身高度,即 100 / 2 = 50。

    409d4e82-efc4-4a84-ac15-6be9146fe7f4-image.png

     
    现在我们可以看到黄色碰撞盒子和 2 个感应射线都在正确的位置了:

    g4.gif

     
     

    第 3 步 - 跑上斜坡

    现在我们尝试让角色跑上斜坡时,会看到这个:

    g6.gif

     
    好消息是碰撞检测已经起作用了,化身已经“知道”有斜坡,不再穿过它。坏消息是化身被卡住了,因为前向的射线报告说被阻挡了。

    要解决这个问题,我们需要将“精度”更改为“低”,这样会在所有6个方向上安装6个射线,并将前向的射线提高到身体中心的高度。

    3add0e9b-d021-4368-bbe6-5b660e6b35a3-image.png

     

    g7.gif

     
    现在我们的化身能够跑上坡了。这是因为前向射线与前方坡面的距离更大,所以它不再报告前方被坡面阻挡了。

    g1.gif

     
    请注意,如果你使用“移动到 X/Y/Z 位置”积木来移动化身,它仍然会穿过斜坡。你必须使用“设置速度”积木来配合基于射线投射的碰撞。

     
     

    第 4 步 - 修复动画和运动

    现在的问题是角色在坡道上移动时不会停下来,而且一直显示“跳在空中”的动画。

    这是因为程序仍然使用化身的“z位置”来测试它是否在空中,所以化身在斜坡上时候就一直以为它在跳跃。既然我们已经打开了基于射线投射的碰撞检测,我们其实可以检查化身是否脚踩在地面或其他物体上。

    在化身角色中,下滑找到“处理按键”积木的定义,并进行以下更改,这样当化身下方没有任何障碍物时,我们将显示跳跃动画。

    23ba563f-0d13-4f42-9182-c4e70280e271-image.png

     

    现在动画已修复,而且化身也可以停在斜坡上了:

    g2.gif

     
     

    第 5 步 - 与皇冠碰撞

    现在让我们继续下一个任务:使化身与平台上的皇冠发生碰撞。有几种方法可以做到这一点。我们将首先尝试使用基于射线的碰撞检测。

    我们需要进行两个代码更改:

    首先,在化身角色中,我们需要打开化身和“物体”角色之间的“可穿过的”碰撞,因为我们不希望化身被皇冠阻挡。

    b93ea388-07a1-418b-a5df-bb24aeb27d78-image.png

     
    接下来,在“物体”角色中,我们需要使用"当与化身碰撞时"积木来处理与“化身”的碰撞事件。由于在这个角色中创建了2个物体,皇冠和金币,与化身发生碰撞的那个物体会自动被选择为当前的"角色物体"。我们可以通过打印角色物体的名称来验证这一点。

    1a742210-75d6-4050-b323-5f940dd50043-image.png

     
    现在,当化身撞上皇冠时,我们在控制台面板中看到打印的信息。它说“物体”角色打印了一条信息:“a”。这正是与化身发生碰撞的皇冠的名称。

    g4.gif

     

    c88a5136-bd93-44e3-ae59-9bed65a95346-image.png

     
     

    第 6 步 - 删除皇冠

    现在我们知道与化身相撞的物体的名称是“a”,我们可以方便地将其删除,就好像化身已经获得了皇冠一样。

    66637081-8af1-4177-a78a-9092202bbe46-image.png

     
    我们甚至不需要指定要删除的物体的名称,因为在发生碰撞时,皇冠已被选为"角色物体"。现在,当化身碰到它时,皇冠将被删除:

    g5.gif

     
     

    第 7 步 - 用射线碰撞方法收集金币?

    现在,如果我们尝试移动角色来收集金币,我们会发现它不起作用:

    g6.gif

     
    原因是我们使用的是基于射线的方法,所以只有当射线触碰到目标物体时,化身才会与物体产生相撞。在这个场景里,金币位于前向射线的上方,所以不会触发碰撞事件。它也不会与化身指向上方的射线发生碰撞,因为化身没有上升的速度。如果我们让化身跳一下,那么它的向上的射线将触发碰撞事件:

    g7.gif

     
    显然,这不是一个很好的解决方案。我们需要让化身在碰到金币时就删除掉金币。我们下一步换到另一种方法。

     
     

    第 8 步 - 显示边界盒子

    三维场景中的每个物体都有一个隐形的“边界盒子”,这是一个包裹整个物体的盒子。要显示物体的边界盒子,可以添加“显示边界盒子”积木。

    在“化身”角色中,让我们取消与“物体”角色的碰撞,并隐藏碰撞射线。然后让我们添加“显示边界盒子”积木:

    e09f7c32-61c7-42bb-8fe2-0538f7413919-image.png

     
    你将在角色周围得到一个白色框架:

    g8.gif

     
    在“物体”角色中,删除“当与化身碰撞时”的事件处理,并显示皇冠和金币的边界盒子:

    8ad1d57e-3ed9-4533-99db-bb6c35c3e0bf-image.png

     
    现在你可以看到这两个物体的边界盒子:

    g9.gif

     
     

    第 9 步 - 检测边界盒子是否重叠

    每个物体或者化身的外形可以非常复杂,所以比起检查它们的实际形状是否重叠,计算它们的边界盒子是否重叠要快得多。我们可以这样要求游戏引擎:在化身的边界盒子与“物体”角色中的任何物体重叠时,广播一个消息给我们处理。

    首先,在“物体”角色中,让我们创建一个名为“碰到物体”的新消息,并将附加的信息存储在变量“信息”中(这个变量已经为你创建好了)。我们可以这样打印出“信息”的内容:

    d4ff8a0f-2d21-42e6-8b53-722ad5eab706-image.png

     

    接下来,在“化身”角色中,添加这个积木,在化身与“物体”角色的物体重叠时广播“碰到物体”的消息。请注意,“p”是化身的名称,“所有物体”是一个特殊参数值,表示“物体”角色中的所有物体都可以被碰到。

    4836422e-fc42-4bd4-9313-5f0a87e53b48-image.png

     
    现在,当化身碰到皇冠时,“信息”变量将包含以下信息:“p,a”。这是告诉我们物体“p”正在与物体“a”重叠。

    c54bc0c2-e57d-41ed-a300-74debbdae3e7-image.png

     
     

    第 10 步 - 删除被触碰的物体

    现在,我们已经找到了感知化身是否触碰王冠或者金币的另一种方法。这样的话,我们可以在“物体”角色中用这个名称来删除该物体:

    86e37ca5-789e-4e24-9073-cab2c22f0f87-image.png

     
    我们使用“分割”积木,通过逗号分隔符将“信息”变量的内容"p,a"拆分为两部分,第2部分就是名称“a”。这样的话,我们可以使用这个个名称来删除对应的物体。当化身碰到金币时,“信息"变量的内容将变成"p,c",那么第2部分就是“c”,即金币物体的名字。

    g10.gif
     
    请注意,现在我们可以成功检测到金币了,因为化身的边界盒子会与金币的边界盒子重叠。 比起使用碰撞射线,这个重叠方法对于检测小物体更好用,因为两个边界盒子的任何部分的重叠都可以被检测到。

     
     

    第 11 步 - 使用边界盒子检测目标区域

    对于我们的最后一个任务,我们将尝试检测化身是否到达了圆形的目标区域。由于目标区域是一个薄薄的圆柱体,它不会被前向的射线传感器检测到。因此,让我们尝试使用边界盒子重叠方法。

    首先,在“化身”角色中,添加一个新的消息处理程序来接收“碰到目标”的消息。当收到这个消息时,我们将使化身停止移动。我们可以停止所有其他代码积木,并将化身的前进速度设置为零。然后我们让化身显示“胜利”的动画。请注意,起始项目已经为你的角色添加了“胜利”动画。

    475eac6d-500b-4365-a122-f491190babe4-image.png

     
    其次,还是在“化身”角色中,当化身的边界盒子与目标物体的边界盒子重叠时,广播“碰到目标”消息。

    3ea2dc4c-7568-4903-bd30-9cf2d789691d-image.png

     
    现在,当化身碰到目标区域的边界盒子时,它将立即停止:

    t1.gif

     
     

    第 12 步 - 关于物体之间的距离

    当我们使用边界盒子检查目标区域时,存在一些小问题。首先,化身一旦碰到目标区域的边缘就会停下来,而不是在目标的中心。另外,由于边界盒子比目标区域本身要大,所以化身可能会卡在边界盒子的一个方角处:

    t2.gif
     

    此外,如果每个动画帧都需要计算2个边界盒子是否重叠,这还是需要耗费不少的计算时间的,在稍慢的计算机上可能会让动画变得不够流畅。

    为了解决这些问题,我们可以尝试第3种方法:我们可以简单地计算化身和目标之间的距离,如果该距离小于某个阈值,则判定化身已经到达了目标区域。

    请注意,当我们测量两个物体之间的距离时,我们是指它们的位置之间的距离。对于像圆柱体这样的简单形状,其位置是其中心点的位置。对于模型或化身,其位置是其底部中心点的位置。

    例如,下面的图片中,目标区域和角色之间的距离是两个红点之间的距离:

    t3.gif

     
     

    第 13 步 - 使用距离检测目标区域

    为了使用距离测量来检查化身是否到达目标位置,我们需要删除用于检查边界盒子的积木,并将其替换为距离检测积木:

    171b7211-9c2e-4a45-b750-e7d8f749ae79-image.png

     
    注意,我们正在检查“3D”距离,这考虑到两个物体的X/Y/Z位置。如果我们选择“2D”(二维),那么Z位置将被忽略。那样的话,即使化身站在目标正下方的草地上,它们之间的 2D 距离也可能会很小。

    我们使用30的阈值,这样当距离小于30时,游戏引擎会自动广播"碰到目标"的消息。

    现在,“碰到目标”消息只有在角色更接近目标区域中心时才会发送。

    t4.gif

     
     

    总结

    总结起来,你应该根据你要解决的问题来决定哪种方法适合你:

    1. 基于射线的方法非常适用于检测那些阻止化身移动的障碍物,例如墙壁、平台、斜坡和楼梯。当障碍物太小而无法被传感器射线检测到时,这个方法就不是很适合。
    2. 对于较小的物体(例如金币或装备),我们可以检查化身的边界盒子是否与这些物体的边界盒子有重叠。这个方法虽然需要一定的计算时间,但是更加准确。
    3. 如果我们只需要知道化身是否靠近另一个物体,还可以使用基于距离的方法。计算两点之间的距离比前两个方法要快得多。

    请注意,即使玩家是在驾驶汽车或飞机,而不是控制化身,我们还是可以使用类似的方法的。

    1 Reply Last reply
    0

    Hello! It looks like you're interested in this conversation, but you don't have an account yet.

    Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

    With your input, this post could be even better 💗

    Register Login
    Reply
    • Reply as topic
    Log in to reply
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes


    • Login

    • Don't have an account? Register

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • CreatiCode