您当前的位置: 首页 >  ide

开发游戏的老王

暂无认证

  • 1浏览

    0关注

    803博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Godot Engine:KinematicBody中move_and_slide的返回值不是闹着玩的

开发游戏的老王 发布时间:2020-07-30 19:25:29 ,浏览量:1

文章目录
      • 方法概述
      • 缘起一个BUG
      • 解决办法

方法概述

KinematicBodymove_and_slide方法,它的原型是下面这样的

Vector3 move_and_slide(linear_velocity: Vector3, up_direction: Vector3 = Vector3( 0, 0, 0 ), stop_on_slope: bool = false, max_slides: int = 4, floor_max_angle: float = 0.785398, infinite_inertia: bool = true)

很多时候我们只要给定此方法的前面两个参数(对象的速度以及对象的向上方向),就可以很简单的移动KinematicBody对象了,如下:

move_and_slide(velocity,Vector3.UP)

这个方法还允许我们设置可滑行的坡度,非常方便。

缘起一个BUG

老王之前并没有把move_and_slideVector3返回值当回事,直到很久以前的一篇博文《Godot Engine:3D角色移动(走/跑/跳)》被热心网友cgoxopx 指出有BUG:

在这里插入图片描述 原来的代码如下

extends KinematicBody

class_name Player

const walk_speed = 5.0
const run_speed = 10.0

var gravity:Vector3 = Vector3.DOWN*12
var speed:float = walk_speed
var jump_speed:float = 6.0
var velocity : Vector3 = Vector3.ZERO
var jump : bool = false


func _ready():
	add_to_group("player")

func _physics_process(delta):
	velocity += gravity*delta
	get_input()
	move_and_slide(velocity,Vector3.UP)
	if jump and is_on_floor():
		velocity.y = jump_speed
	
func get_input():
	var vy = velocity.y
	velocity = Vector3.ZERO
	if Input.is_action_pressed("ui_run"):
		speed = run_speed
	if Input.is_action_just_released("ui_run"):
		speed = walk_speed
		
	if Input.is_action_pressed("ui_up"):
		velocity += Vector3.FORWARD
	if Input.is_action_pressed("ui_down"):
		velocity += Vector3.BACK
	if Input.is_action_pressed("ui_left"):
		velocity += Vector3.LEFT
	if Input.is_action_pressed("ui_right"):
		velocity += Vector3.RIGHT
	
	velocity = velocity.normalized()*speed
	if velocity != Vector3.ZERO:
		look_at(translation - velocity,Vector3.UP)
	velocity.y = vy
	#动作键和跳跃键
	if Input.is_action_just_pressed("ui_action"):
		print("action")
	jump = false
	if Input.is_action_just_pressed("ui_jump"):
		jump = true
			

仔细看了一下代码,确实只考虑到了角色主动起跳时将重力加速度清零的情况,如果角色是站在悬崖上滑落,加速度是会积累到非常大,而且没有清零。

解决办法

按照传统思路应该想办法获取到这种“滑落事件”,说实话这事儿还是有点麻烦,需要增加新的节点并且又要连接信号。老王差点想回复“直接用状态机吧”。后来查了一些教程,发现其实有非常非常简单的办法实现这个重力清零

将以上代码中的

move_and_slide(velocity,Vector3.UP)

改为

velocity = move_and_slide(velocity,Vector3.UP)

就OK了!

move_and_slide 的返回值到底是什么,其实就是通过我们所给的速度velocity以及KinematicBody对象的此时的各种碰撞因素,得出的实际运动速度。 比如,我们给一个处在地面的KinematicBody对象一个值为(1.0,-5.0,1.0) 的速度,给的速度在Y轴有一个向下的分量,但是由于对象在地面,所以这个分量会被抵消,那么实际的运动速度就是(1.0,0.0,1.0)

那么在本例中,其实我们根本没有必要“费尽心机”寻找什么“滑落事件”,如果我们把对象每一帧的实际速度“返还”给它,那么只要它在地面这,这个重力加速度就每时每刻都被清零了。

关注
打赏
1656935939
查看更多评论
立即登录/注册

微信扫码登录

0.0396s