You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让仅含4个斜向精灵的Godot角色实现8方向移动?

问题描述

我想在Godot引擎中实现角色8方向移动,但只准备了东南(DownRight)、东北(UpRight)、西南(DownLeft)、西北(UpLeft)4个斜向方向的精灵。预期逻辑如下:

  • 角色朝东南方向时,单独向南移动不切换精灵;朝西南方向时,单独向南移动同理
  • 从东南方向改为向上移动,切换为东北方向精灵;从东北方向改为向左移动,切换为西北方向精灵;东南转西南的逻辑以此类推

目前角色能正常控制移动,但精灵切换完全不符合预期,始终显示UpLeft行走动画,原代码如下:

extends CharacterBody2D

const max_speed = 50
const accel = 1500
const friction = 400

var input = Vector2.ZERO

@onready var animation = $AnimationPlayer

func get_input():
    input.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
    input.y = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
    return input.normalized()
    
func player_movement(delta):
    input = get_input()
    
    if input == Vector2.ZERO:
        if velocity.length() > (friction * delta):
            velocity -= velocity.normalized() * (friction * delta)
        else:
            velocity = Vector2.ZERO
    else:
        velocity += (input * accel * delta)
        velocity = velocity.limit_length(max_speed)
        
    move_and_slide()

func updateAnimation():
    var direction = "_DownRight"
    
    if Vector2(1, -1): direction = "_UpRight" 
    if Vector2.ONE: direction = "_DownRight"
    if Vector2(-1, 1): direction = "_DownLeft"
    if Vector2(-1, -1): direction = "_UpLeft"
    if Vector2.ZERO:
        animation.play("walk" + direction + "Idle")
    else:
        animation.play("walk" + direction)
        
func _physics_process(delta):
    player_movement(delta)
    updateAnimation()
解决方案

你的updateAnimation函数逻辑完全错误——没有基于实际输入或角色速度判断方向,而是直接判断固定的Vector2常量(这些判断永远为真,最后一个Vector2(-1,-1)的赋值覆盖了前面所有结果,所以才会一直显示UpLeft动画)。以下是符合你需求的修正方案:

核心逻辑

把8方向输入映射到4个斜向精灵,遵循你的规则:

  • 当有左右输入时,优先锁定左右方向,再结合上下输入确定斜向
  • 当只有上下输入时,保留当前的左右方向,切换对应上下斜向
  • 当只有左右输入时,保留当前的上下方向,切换对应左右斜向

修正后的完整代码

extends CharacterBody2D

const max_speed = 50
const accel = 1500
const friction = 400

var input = Vector2.ZERO
# 记录当前使用的方向精灵,避免无意义的动画切换
var current_direction = "_DownRight"

@onready var animation = $AnimationPlayer

func get_input():
    input.x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
    input.y = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
    # 零向量不归一化,避免报错
    return input if input != Vector2.ZERO else Vector2.ZERO
    
func player_movement(delta):
    input = get_input()
    
    if input == Vector2.ZERO:
        if velocity.length() > (friction * delta):
            velocity -= velocity.normalized() * (friction * delta)
        else:
            velocity = Vector2.ZERO
    else:
        velocity += (input * accel * delta)
        velocity = velocity.limit_length(max_speed)
        
    move_and_slide()

func updateAnimation():
    # 有输入时更新方向
    if input != Vector2.ZERO:
        # 优先处理左右输入
        if input.x > 0:
            # 向右:结合上下输入确定右上/右下
            current_direction = "_UpRight" if input.y < 0 else "_DownRight"
        elif input.x < 0:
            # 向左:结合上下输入确定左上/左下
            current_direction = "_UpLeft" if input.y < 0 else "_DownLeft"
        else:
            # 只有上下输入:保留当前左右方向,切换上下
            if current_direction.contains("Right"):
                current_direction = "_UpRight" if input.y < 0 else "_DownRight"
            else:
                current_direction = "_UpLeft" if input.y < 0 else "_DownLeft"
    
    # 根据角色是否移动播放对应动画
    if velocity == Vector2.ZERO:
        animation.play("walk" + current_direction + "Idle")
    else:
        animation.play("walk" + current_direction)
        
func _physics_process(delta):
    player_movement(delta)
    updateAnimation()

关键修改说明

  • 修复输入归一化问题:get_input中不对零向量归一化,避免Godot报错
  • 新增current_direction变量:记录当前使用的方向精灵,纯上下/左右移动时保留原有斜向的一侧属性
  • 正确的方向判断逻辑:完全基于输入的x、y分量判断,符合你要求的切换规则
  • 动画播放优化:根据velocity判断是否播放 idle 动画(输入为零时角色可能还在减速移动)

内容的提问来源于stack exchange,提问作者ConvexProjects

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:56:04