从此
文章
📄文章 #️⃣专题 🌐上网 📺 🛒 📱

Godot 4.0+ move_and_slide / MoveAndSlide 方法入参变属性、CharacterBody3D 重力处理实例

🕗2022-12-16

Godot WASD移动方法基本概念和用法:

  完全自己处理移动 -
    瞬间移动 - Velocity = modifiedVelocity;
    匀速移动 - this.Position = this.Position.MoveToward(new Vector2(200, 200), (float)delta * MOVE_SPEED);
    非均匀移动 - sprite.Position = sprite.Position.Lerp(mousePos, (float)delta * MOVE_SPEED);
    纯Position方式需要手动处理碰撞 - GetSlideCollisionCount()
    施力 - rigidBody3D.ApplyImpulse(Vector3.Forward * 10); // 或持续施力ApplyForce(...)
 
  移动时遭碰撞停止 - MoveAndCollide()
  碰撞后依惯性滑动 - MoveAndSlide()

// Godot 3.x old method: 

velocity = MoveAndSlide(velocity, new Vector3(0, 1, 0), false, 6, (float)(Math.PI / 4.0), false);


// 4.0+:  KinematicBody2D、KinematicBody 已被 CharacterBody2D、CharacterBody3D 替代

  // 以下各项均为可选属性:
  UpDirection=new Vector3(0, 1, 0); // 等同 this.MotionMode = CharacterBody3D.MotionModeEnum.Grounded; 也等同 3.x 的 Vector3.Up
  FloorStopOnSlope=false;
  MaxSlides=6;
  FloorMaxAngle=(float)(Math.PI / 4.0);
  // infinite_inertia彻底废弃,可用单向碰撞层替代

Vector3 v3 = ...

Velocity = v3 ;

MoveAndSlide(); // 入参分散到CharacterBody3D属性了,比如移位 this.Velocity


 
Godot IDE 4.x 起 - 3D/WASD移动模板完整源代码:
 
using Godot;
public partial class CharacterBody3D : Godot.CharacterBody3D
{
    public const float Speed = 5.0f;
    public const float JumpVelocity = 4.5f;

    // Get the gravity from the project settings to be synced with RigidBody nodes.
    public float gravity = ProjectSettings.GetSetting("physics/3d/default_gravity").AsSingle();

    public override void _PhysicsProcess(double delta)
    {
        Vector3 velocity = Velocity;

        // Add the gravity.
        if (!IsOnFloor())
            velocity.Y -= gravity * (float)delta;

        // Handle Jump.
        if (Input.IsActionJustPressed("ui_accept") && IsOnFloor())
            velocity.Y = JumpVelocity;

        // Get the input direction and handle the movement/deceleration.
        // As good practice, you should replace UI actions with custom gameplay actions.
        Vector2 inputDir = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
        Vector3 direction = (Transform.Basis * new Vector3(inputDir.X, 0, inputDir.Y)).Normalized();
        if (direction != Vector3.Zero)
        {
            velocity.X = direction.X * Speed;
            velocity.Z = direction.Z * Speed;
        }
        else
        {
            velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
            velocity.Z = Mathf.MoveToward(Velocity.Z, 0, Speed);
        }

        Velocity = velocity;
        MoveAndSlide();
    }
}
 
  场景节点结构:
    RootNode
    --Camera3D
    --WorldEnvironment
    --StaticBody3D
    ----CollisionShape3D - 演示可设置WorldBoundaryShape3D做为无限平面地板
    --CharacterBody3D - 只是个空容器,必须配置CollisionShape3D子节点
    ----CollisionShape3D - 演示可设置BoxShape3D做为3D物体碰撞形状
    ----MeshInstance3D
 
模板源码来自:
 
Godot Github C#
Godot Github GDS
 

extends CharacterBody3D


const SPEED = 5.0
const JUMP_VELOCITY = 4.5

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")


func _physics_process(delta):
    # Add the gravity.
    if not is_on_floor():
        velocity.y -= gravity * delta

    # Handle Jump.
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY

    # Get the input direction and handle the movement/deceleration.
    # As good practice, you should replace UI actions with custom gameplay actions.
    var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
    if direction:
        velocity.x = direction.x * SPEED
        velocity.z = direction.z * SPEED
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)
        velocity.z = move_toward(velocity.z, 0, SPEED)

    move_and_slide()