编程新手求助:如何为精灵行走动画添加等待切换纹理?
嘿,我来帮你搞定这个精灵行走动画的问题!你现在的代码之所以看不到纹理切换,是因为load()和赋值操作是瞬间完成的——程序会立刻把纹理换成第二张,根本不会停留显示第一张,自然看不到动画效果。
下面给你两种简单易上手的解决方案,都是适合新手的:
方法一:用Timer节点实现帧切换(手动控制逻辑)
这种方法能让你更清晰理解动画切换的底层逻辑,步骤如下:
添加Timer节点
在你的精灵节点(比如LilBoiTexture所在的父节点)下添加一个Timer节点,命名为AnimationTimer。在检查器里把它的Wait Time设为0.5(就是你要的切换间隔),把One Shot关掉(这样计时器会循环触发)。预加载纹理并定义变量
在脚本开头定义两个变量:一个存储要切换的纹理数组,一个记录当前显示的帧索引,还有一个标记是否在向上移动:# 预加载纹理(比load()更高效,避免运行时卡顿) var walk_back_textures = [ preload("res://LilBoiAssets/LilBoiBackward.png"), preload("res://LilBoiAssets/LilBoiBackward2.png") ] var current_frame = 0 var is_moving_up = false处理输入与计时器启动
在_process(delta)函数里处理移动输入,当按下"move_up"时启动计时器,同时设置初始纹理;松开时停止计时器并恢复站立纹理:func _process(delta): var vel = Vector2.ZERO is_moving_up = Input.is_action_pressed("move_up") if is_moving_up: vel.y -= 1 facingDir = Vector2(0, -1) # 如果计时器没在运行,启动它并重置初始帧 if not $AnimationTimer.is_processing(): $AnimationTimer.start() current_frame = 0 $LilBoiTexture.texture = walk_back_textures[current_frame] else: # 停止计时器,回到站立状态的纹理 $AnimationTimer.stop() $LilBoiTexture.texture = walk_back_textures[0] # 这里加上你原来的移动逻辑(比如应用velocity到位置) # position += vel * speed * delta连接计时器的timeout信号
选中AnimationTimer节点,在右侧"信号"面板找到timeout信号,连接到你的脚本,然后实现切换帧的函数:func _on_animation_timer_timeout(): # 只有在移动时才切换帧 if is_moving_up: # 循环切换两张纹理(取模运算实现循环) current_frame = (current_frame + 1) % walk_back_textures.size() $LilBoiTexture.texture = walk_back_textures[current_frame]
方法二:用AnimationPlayer节点(更直观的可视化操作)
如果你觉得手动写逻辑麻烦,用AnimationPlayer能更快速创建动画:
添加AnimationPlayer节点
在父节点下添加AnimationPlayer节点,命名为AnimationPlayer。创建行走动画
选中AnimationPlayer,点击"Animation"->"New Animation",命名为walk_back。然后:- 点击"Add Track"->"Property Track",选中
LilBoiTexture的texture属性。 - 在时间轴的0秒位置添加关键帧,设置纹理为
LilBoiBackward.png。 - 在0.5秒位置添加第二个关键帧,设置纹理为
LilBoiBackward2.png。 - 在检查器里把动画的
Loop选项打开,让它循环播放。
- 点击"Add Track"->"Property Track",选中
脚本里控制动画播放
在_process(delta)里处理输入,按下时播放动画,松开时停止并恢复站立纹理:func _process(delta): var vel = Vector2.ZERO if Input.is_action_pressed("move_up"): vel.y -= 1 facingDir = Vector2(0, -1) # 如果动画没在播放,启动它 if not $AnimationPlayer.is_playing(): $AnimationPlayer.play("walk_back") else: # 停止动画,回到站立纹理 $AnimationPlayer.stop() $LilBoiTexture.texture = preload("res://LilBoiAssets/LilBoiBackward.png") # 移动逻辑 # position += vel * speed * delta
小提示
- 一定要用
preload()代替load()来加载纹理,这样游戏启动时就会把纹理加载好,避免运行时切换卡顿。 - 如果你以后要做更多方向的动画(比如左右、向下),可以用同样的逻辑扩展纹理数组和计时器/动画。
内容的提问来源于stack exchange,提问作者Silent Program

