游戏开发中的物理之使用KinematicBody2D(01)

简介: 游戏开发中的物理之使用KinematicBody2D

介绍


Godot提供了多个碰撞对象以提供碰撞检测和响应。试图确定要为您的项目使用哪个选项可能会造成混淆。如果您了解每个问题的工作原理和优点和缺点,则可以避免这些问题并简化开发。在本教程中,我们将研究 KinematicBody2D节点,并显示一些使用它的示例。


注意

本文档假定您熟悉Godot的各种物理机构。请先阅读物理简介。

什么是运动机构?


KinematicBody2D用于实现通过代码控制的主体。运动物体在移动时会检测到与其他物体的碰撞,但不受重力或摩擦等发动机物理特性的影响。虽然这意味着您必须编写一些代码来创建其行为,但也意味着您可以更精确地控制它们的移动和反应方式。


提示

一个KinematicBody2D可以通过重力和其他力量的影响,但必须计算在代码运动。物理引擎不会移动KinematicBody2D。

运动与碰撞


移动时KinematicBody2D,您不应position直接设置其属性。而是使用move_and_collide()ormove_and_slide()方法。这些方法沿给定矢量移动物体,如果检测到与另一个物体的碰撞,则立即停止。KinematicBody2D发生碰撞后,必须手动编码任何碰撞响应。


警告

您只应在_physics_process()回调中进行运动身体运动。

两种移动方法具有不同的用途,在本教程的后面,您将看到有关它们如何工作的示例。


move_and_collide


此方法采用一个参数:Vector2,指示人体的相对运动。通常,这是您的速度矢量乘以帧时间步(delta)。如果引擎在沿该矢量的任何位置检测到碰撞,车身将立即停止移动。如果发生这种情况,该方法将返回KinematicCollision2D对象。


KinematicCollision2D是一个包含有关碰撞和碰撞对象的数据的对象。使用此数据,您可以计算碰撞响应。


move_and_slide


该move_and_slide()方法旨在简化在您希望一个物体沿另一个物体滑动的常见情况下的碰撞响应。例如,它在平台游戏或自上而下的游戏中特别有用。


提示

move_and_slide()使用会自动计算基于帧的移动delta。难道不是由乘你的速度矢量delta

它传递给前move_and_slide()。

除了速度矢量之外,还move_and_slide()可以使用许多其他参数来自定义滑动行为:


up_direction-默认值: Vector2( 0, 0 )


此参数允许您定义引擎应将哪些表面视为地板。设置这个可以让你使用is_on_floor(),is_on_wall()和is_on_ceiling()方法来检测机身的接触是什么类型的表面。默认值表示所有表面均视为墙。


stop_on_slope-默认值: false


此参数可防止人体在站立时滑落斜坡。


max_slides-默认值: 4


此参数是身体停止移动之前的最大碰撞次数。设置得太低可能会完全阻止移动。


floor_max_angle-默认值:( 0.785398以弧度表示,等于45度)


此参数是在不再将表面视为“地板”之前的最大角度。


infinite_inertia-默认值: true


当此参数为时true,主体可以推动RigidBody2D 节点,而忽略其质量,但不会检测到与它们的碰撞。如果是这样,false 则身体将与刚体碰撞并停止。


move_and_slide_with_snap


此方法move_and_slide()通过添加snap参数来添加一些其他功能。只要此矢量与地面接触,物体就会保持附着在地面上。请注意,例如,这意味着您必须在跳跃时禁用捕捉。您可以通过设置snap 为Vector2.ZERO或使用move_and_slide()来实现。


检测碰撞


使用move_and_collide()该函数时KinematicCollision2D 直接返回一个,您可以在代码中使用它。


在move_and_slide()计算滑动响应时,使用时可能会发生多次碰撞。要处理这些冲突,请使用get_slide_count() 和

get_slide_collision():
# Using move_and_collide.
var collision = move_and_collide(velocity * delta)
if collision:
    print("I collided with ", collision.collider.name)
# Using move_and_slide.
velocity = move_and_slide(velocity)
for i in get_slide_count():
    var collision = get_slide_collision(i)
    print("I collided with ", collision.collider.name)

注意

get_slide_count()仅计数身体碰撞和改变方向的次数。

有关返回哪些碰撞数据的详细信息,请参见KinematicCollision2D。


使用哪种运动方式?


Godot新用户的一个常见问题是:“您如何决定使用哪种运动功能?” 通常,使用响应是move_and_slide()因为它“更简单”,但不一定是这种情况。想到它的一种方法move_and_slide()是一种特殊情况,并且move_and_collide() 更为笼统。例如,以下两个代码段导致相同的碰撞响应:

20201218154826753.gif

// using MoveAndCollide
var collision = MoveAndCollide(velocity * delta);
if (collision != null)
{
    velocity = velocity.Slide(collision.Normal);
}
// using MoveAndSlide
velocity = MoveAndSlide(velocity);



您所做的任何事情都move_and_slide()可以使用来完成move_and_collide(),但可能需要花费更多的代码。但是,正如我们在下面的示例中看到的那样,在某些情况下move_and_slide()无法提供所需的响应。


在上面的示例中,我们将move_and_slide()返回的速度分配给velocity变量。这是因为当角色与环境碰撞时,该函数会在内部重新计算速度以反映速度下降。


例如,如果您的角色掉在地板上,您不希望它由于重力作用而积累垂直速度。相反,您希望其垂直速度重置为零。


move_and_slide()可能还会在一个循环中多次重新计算运动体的速度,因为要产生平滑运动,它将移动角色并默认碰撞最多5次。在过程结束时,该函数返回角色的新速度,该速度可以存储在velocity 变量中,并用于下一帧。


例子


要查看这些示例,请下载示例项目: using_kinematic2d.zip


机芯和墙壁


如果您下载了示例项目,则此示例位于“ BasicMovement.tscn”中。


对于此示例,添加KinematicBody2D具有两个子元素的aSprite和a CollisionShape2D。使用Godot“ icon.png”作为Sprite的纹理(将其从Filesystem停靠拖到的Texture属性Sprite)。在 CollisionShape2D“形状”属性中,选择“新建RectangleShape2D”并调整矩形大小以适合精灵图像。


注意

有关实施2D移动方案的示例,请参见2D移动概述。

将脚本附加到KinematicBody2D并添加以下代码:

using Godot;
using System;
public class KBExample : KinematicBody2D
{
    public int Speed = 250;
    private Vector2 _velocity = new Vector2();
    public void GetInput()
    {
        // Detect up/down/left/right keystate and only move when pressed
        _velocity = new Vector2();
        if (Input.IsActionPressed("ui_right"))
            _velocity.x += 1;
        if (Input.IsActionPressed("ui_left"))
            _velocity.x -= 1;
        if (Input.IsActionPressed("ui_down"))
            _velocity.y += 1;
        if (Input.IsActionPressed("ui_up"))
            _velocity.y -= 1;
    }
    public override void _PhysicsProcess(float delta)
    {
        GetInput();
        MoveAndCollide(_velocity * delta);
    }
}


目录
相关文章
|
资源调度 算法 关系型数据库
5G 物理层|带你读《5G无线网络规划与设计》之十
使用非授权频谱是移动通信系统扩展频谱资源的重要手段之一。非授权频谱上的业务非常繁忙,抢占信道最好的方法是一旦发现信道空闲马上开始传输。在 LTE 中,资源调度以时隙为单位,即使监听到信道空闲,也必须等到下一个时隙开始进行传输
5G 物理层|带你读《5G无线网络规划与设计》之十
|
6天前
|
人工智能 IDE 调度
Claude Code还是Codex?老金告你怎么选!
本文用“露营报名页”实例,揭示AI编程的核心不是选工具(Claude Code重现场协作,Codex重委托交付),而是厘清自身角色:许愿型需转任务描述,现场型宜边看边调,派单型要明边界验收,调度型则按任务脏/清/险动态组合。关键在学会“安排AI干活”,而非只会提需求。(239字)
|
NoSQL
mongodb每天上亿数据量定期清理
背景:mongodb(应用运营数据分析与自动自助化支持平台)每分钟有30w~40w的insert,20w~30w的update。数据保留一天,一天之前的数据可以清理。一天的数据量大概1亿左右。由于数据量较大,清理数据对系统造成了较大影响,入库会出现堵塞。
4378 0
|
开发工具 Nacos git
Git如何checkout远程tag
Git如何checkout远程tag
4474 0
|
11月前
|
机器学习/深度学习 人工智能 自然语言处理
掌握这5大要素,开启AI项目落地的成功之门
在AI浪潮下,大模型成为企业转型的关键动力。本文三桥君探讨了AI项目落地的挑战与潜力,并提出五大成功要素:业务热情、认清AI能力、编程能力、小处着手与老板耐心。通过合理选择应用场景,企业可有效推动AI技术融入业务,实现效率提升与决策优化,助力持续发展。
615 3
|
人工智能 自然语言处理 算法
AI-Researcher:告别熬夜肝论文!港大开源AI科研神器,从选题到发表全自动
AI-Researcher 是香港大学数据科学实验室推出的开源自动化科研工具,基于大型语言模型(LLM)代理,支持从研究想法到论文发表的全流程自动化,涵盖文献综述、算法设计、实验验证和论文撰写等功能。
1832 8
AI-Researcher:告别熬夜肝论文!港大开源AI科研神器,从选题到发表全自动
|
11月前
|
存储 固态存储 安全
阿里云服务器最新租用价格:收费标准与2核4G/4核8G等热门配置活动价格参考
阿里云服务器租用价格是多少?阿里云服务器报价主要看所选云服务器的实例规格与带宽和云盘等配置,现在购买阿里云服务器,轻量应用服务器2核2G200M带宽38元1年,经济型e实例2核2G3M带宽99元1年,通用算力型u1实例2核4G5M带宽199元1年。本文为大家展示阿里云服务器最新的收费标准与活动价格情况,以供了解和参考。
|
开发框架 前端开发 开发工具
一个小案例带你快速了解鸿蒙ArkUI的基本使用
一个小案例带你快速了解鸿蒙ArkUI的基本使用
1020 124
|
存储 分布式计算 分布式数据库
云计算和虚拟化技术
云计算是指把计算资源、存储资源、网络资源、应用软件等集合起来,采用虚拟化技术,将这些资源池化,组成资源共享池,共享池即是“云”。
543 65
|
数据采集 传感器 机器学习/深度学习
人工智能在农业中的应用:从数据采集到智能决策
本篇文章将详细探讨人工智能(AI)技术在现代农业中的应用,包括从数据采集、分析到智能决策的全过程。通过具体案例,展示AI如何帮助提高农业生产效率、降低成本并增强环境可持续性。
2288 0