Godot/Gdscript网格运动培训
因此,我一直在使用KidsCancode的Godot教程/文档来帮助我为我正在从事的项目创建一个基于口袋妖怪的网格运动。出于所有意图和目的,我想在早期的手持式口袋妖怪游戏中创建一个与该运动系统一样接近的动作系统。
我想在开始之前添加两件事。第一,我已经喜欢Kidscancode试图教授基于网格的运动的方式,因此,虽然编码的其他方法可能更简单,例如可以在诸如此类的视频中找到的方式(
因此,首先,这是我的 player场景节点树。最重要的部分是Raycast2d和Tween节点。
这是我的主要区域2D播放器节点的代码:
extends Area2D
const tile_size = 16
export var speed = 5
var inputs = { "ui_right": Vector2.RIGHT,
"ui_left": Vector2.LEFT,
"ui_up": Vector2.UP,
"ui_down": Vector2.DOWN }
func _ready():
position = position.snapped(Vector2.ONE * tile_size/2)
func _unhandled_input(event):
if $Tween.is_active():
return
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(inputs[dir])
func move(dir):
$RayCast2D.cast_to = inputs[dir] * tile_size
$RayCast2D.force_raycast_update()
if !$RayCast2D.is_colliding():
move_tween(dir)
func move_tween(dir):
$Tween.interpolate_property(self, "position", position,
position + inputs[dir] * tile_size, 1.0/speed, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
$Tween.start()
快速解释,func _ready():
将播放器捕捉到网格。 func _unhandled_input(事件):
然后检查是否发生了补间,如果没有发生,请调用func move(dir)
。此功能射线播放到给定的方向输入,强制射线播放更新,如果没有静态主体在给定的方向,请调用func move_tween(dir)
。最后一个功能将补间插值处理到给定的方向,并启动二元过程。就是这样。再一次,这曾经工作正常。
但是,现在,当我尝试运行此操作时,我会遇到一个错误“无效的获取索引'(0,1)'(在基础上:'dictionary')“ where”(0,1)“基于我尝试的方向更改在游戏运行时搬进来。
在调试器码头中,在堆栈帧的下方,它在“ 22- at function; move; move” $ raycast2d.cast_to = inputs = inputs [dir] * tile_size
和“ 19- at function:_unhandled_input” 移动(输入[dir])。
网站上的代码只有以下是(dir)
而不是(inputs [dir])
。但是这样做只会给我另一个错误。如果有人比我更聪明地知道发生了什么,我将非常感谢任何洞察力。谢谢 !
So I've been using KidsCanCode's Godot tutorials/documentation to help me create a Pokemon-like grid-based movement for a project I'm working on. For all intents and purposes, I would like to create a movement system as close to that in the earlier handheld Pokemon games as possible.
I would like to add two things before I start; one, I have grown fond of the way KidsCanCode attempted to teach grid-based movement, so while other ways of coding it may be simpler such as those that can be found on videos such as this one (https://www.youtube.com/watch?v=jSv5sGpnFso), I would like to hard-headidly stick to this method of coding it... you'll see what I mean when you read the code. Lastly, I would like to add that I had this code working before ! I actually haven't made any changes to the code since it was last working, however, for some reason it no longer seems to work, I'm not sure if that's due to Godot updating since, but hopefully someone can help me out with that.
So first of all, this is my player scene node tree. The most important parts of this being the RayCast2D and Tween nodes.
And this is my code for the main Area2D Player node:
extends Area2D
const tile_size = 16
export var speed = 5
var inputs = { "ui_right": Vector2.RIGHT,
"ui_left": Vector2.LEFT,
"ui_up": Vector2.UP,
"ui_down": Vector2.DOWN }
func _ready():
position = position.snapped(Vector2.ONE * tile_size/2)
func _unhandled_input(event):
if $Tween.is_active():
return
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(inputs[dir])
func move(dir):
$RayCast2D.cast_to = inputs[dir] * tile_size
$RayCast2D.force_raycast_update()
if !$RayCast2D.is_colliding():
move_tween(dir)
func move_tween(dir):
$Tween.interpolate_property(self, "position", position,
position + inputs[dir] * tile_size, 1.0/speed, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
$Tween.start()
To quickly explain, func _ready():
snaps the player to the grid. func _unhandled_input(event):
then checks to see if a Tween is occurring, and if not, calls func move(dir)
. This function raycasts to the given direction input, forces a raycast update, and if no static body is in the given direction, calls func move_tween(dir)
. This last functions handles tween interpolation to the given direction and starts the tweening process. That's pretty much it. Once again, this used to work just fine.
However, now when I try to run this, I get an error "Invalid get index '(0, 1)' (on base: 'Dictionary')" where "(0, 1)" changes based on what direction I tried to move in when the game was running.
In the Debugger dock, underneath Stack Frames, it gives me errors on lines "22 - at function; move" $RayCast2D.cast_to = inputs[dir] * tile_size
and "19 - at function: _unhandled_input" move(inputs[dir])
.
The code on the website had these say (dir)
only instead of (inputs[dir])
. But doing so only gives me another error. If anyone smarter than me has any idea what's going on, I would very much appreciate any and all insight. Thank you !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
了解问题
还可以,让我们看看。变量
输入
具有您的字典:键是
string
,并且值为vector2
。因此,这里:
变量
dir
将是String
。这是您所需的is_action_pressed
,所以这是正确的。和
输入[dir]
将是vector2
。这意味着在移动
中,您将vector2
作为参数中。现在,在
中移动
您说::,但请记住,您通过的参数是
vector2
,input> Input
的键都是字符串
。因此,它在这里失败:输入[dir]
。使用类型类型的类似问题的预警
可以帮助您尽早确定此类问题。可悲的是,在Godot 3.x中,无法指定
字典
的键和值。可以说,您可以使用c#并使用.net
dictionary< tkey,tvalue>
来自system.collections.collections.generic
,它可以指定键和值类型。但是,我们不是在这里谈论这些词典。您可以用GDScript判断的是您的参数是
vector2
:或
string
godot可以告诉当您用错误的参数调用它们时。
另一件事将有所帮助。尽管它更多地在纪律方面,但要保持一致的名称。如果您使用的名称在您的系统中具有具体的含义,它们将为您提供帮助。
例如,您调用
移动
这样:这意味着您所传递的内容不称为
dir
※。但是您的移动
按这样的定义:移动
期望您称之为dir
。您会看到,当您键入MOVE
的调用时。※:我会说您正在传递
Inputs
的值之一,因此所传递的内容称为Input
。或者,您可以将它们称为Action
,鉴于您在is_action_pressed
中使用它们。同样,这将以帮助您的方式使用名称。解决问题的
方法是通过使用
字符串
和inputs
in_UNHANDLED_INPUT
仅使用带有输入)。并从那里使用vector2
。这意味着:dictionary
中查找的努力。诚然,对于您的游戏来说,这些并不重要。最终,您要做的就是取决于您。但是,请考虑将这种方法提交您的考虑。
这是代码(我添加了一些类型的注释):
或者您可以每次都使用
String
思考并查询字典。我相信,这是您的意图。像这样:请注意,
_unhandled_input
将dir
传递给移动
。移动
的方式相同,将dir
传递给move_tween
。Understanding the problem
Alright, let us see. The variable
inputs
has your dictionary:The keys are
String
, and the values areVector2
.Thus, here:
The variable
dir
is going to be aString
. Which is what you need foris_action_pressed
, so that is correct.And
inputs[dir]
is going to be aVector2
. Which means that inmove
you are getting aVector2
as argument.Now, in
move
you say::But remember that the argument you are passing is a
Vector2
, and the keys ofinput
are allString
. So it fails here:inputs[dir]
.Early warning for similar problems
Using types can help you identify this kind of problems early. Sadly in Godot 3.x there is no way to specify the the keys and values of a
Dictionary
.Arguably you could use C# and use .NET
Dictionary<TKey,TValue>
from theSystem.Collections.Generic
, which would let you specify the key and value types. Yet, we are not talking about those dictionaries here.What you can tell with GDScript is that your parameters are either
Vector2
:Or
String
This way Godot can tell you when you are calling them with the wrong parameter.
Another thing that will help. Although it is more on the discipline side, is to keep consistent names. If the names you use have a concrete meaning in your system, they will help you.
For instance, you call
move
like this:Meaning that what you are passing is not called
dir
※. But you havemove
defined like this:So
move
expects something you call adir
. And you would see that when you are typing the call tomove
.※: I'd say you are passing one of the values of
inputs
, so what you are passing is called aninput
. Or you could call themaction
, given that you use them inis_action_pressed
. Which, again, would be using names in a way that helps you.Solving the problem
The way I would solve this is by using the
String
andinputs
in_unhandled_input
only (after all, that function is meant to deal with inputs). And work withVector2
from there on. This means that:Dictionary
.Admittedly, these aren't a huge deal for your game right now. And ultimately what you do is up to you. Yet, consider this approach submitted to your consideration.
This is the code (I have added some type annotations):
Or you can using
String
thought out, and querying the dictionary every time. Which, I believe, is what you intended. Like this:Notice here that
_unhandled_input
is passingdir
tomove
. The same way thatmove
is passingdir
tomove_tween
.