移动方块

WASD 驱动 CharacterBody3D 在柱子之间穿行,相机在后面跟随。不用鼠标转视角。

上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。

用到的 Godot 类

CharacterBody3DCamera3DStaticBody3D

代码

scripts/main.gd
extends Node

const CAMERA_OFFSET: Vector3 = Vector3(0, 6, 9)
const GROUND_SIZE: Vector3 = Vector3(30, 1, 30)

var player: CharacterBody3D
var camera: Camera3D


func _ready() -> void:
	_add_environment()
	_add_light()
	_add_ground()
	_add_pillars()

	player = CharacterBody3D.new()
	player.set_script(Get.script('player'))
	player.position = Vector3(0, 1, 0)
	add_child(player)

	camera = Camera3D.new()
	camera.position = CAMERA_OFFSET
	add_child(camera)
	camera.current = true

	print('wasd moves the cube, the camera follows it')


func _process(delta: float) -> void:
	camera.position = camera.position.lerp(player.position + CAMERA_OFFSET, delta * 4.0)
	camera.look_at(player.position, Vector3.UP)


func _add_pillars() -> void:
	var mesh: BoxMesh = BoxMesh.new()
	mesh.size = Vector3(1.4, 3, 1.4)

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color('#fc7f7f')
	material.roughness = 0.5

	for i in 8:
		var angle: float = TAU * i / 8.0

		var visual: MeshInstance3D = MeshInstance3D.new()
		visual.mesh = mesh
		visual.material_override = material

		var shape: BoxShape3D = BoxShape3D.new()
		shape.size = mesh.size

		var collision: CollisionShape3D = CollisionShape3D.new()
		collision.shape = shape

		var pillar: StaticBody3D = StaticBody3D.new()
		pillar.position = Vector3(cos(angle), 0, sin(angle)) * 8.0 + Vector3(0, 1.5, 0)
		pillar.add_child(visual)
		pillar.add_child(collision)
		add_child(pillar)


func _add_ground() -> void:
	var mesh: BoxMesh = BoxMesh.new()
	mesh.size = GROUND_SIZE

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color('#2a2f3d')

	var visual: MeshInstance3D = MeshInstance3D.new()
	visual.mesh = mesh
	visual.material_override = material

	var shape: BoxShape3D = BoxShape3D.new()
	shape.size = GROUND_SIZE

	var collision: CollisionShape3D = CollisionShape3D.new()
	collision.shape = shape

	var ground: StaticBody3D = StaticBody3D.new()
	ground.position = Vector3(0, -0.5, 0)
	ground.add_child(visual)
	ground.add_child(collision)
	add_child(ground)


func _add_environment() -> void:
	var sky_material: ProceduralSkyMaterial = ProceduralSkyMaterial.new()
	sky_material.sky_top_color = Color(0.05, 0.06, 0.12)
	sky_material.sky_horizon_color = Color(0.14, 0.16, 0.24)
	sky_material.ground_bottom_color = Color(0.02, 0.02, 0.04)
	sky_material.ground_horizon_color = Color(0.1, 0.11, 0.16)

	var sky: Sky = Sky.new()
	sky.sky_material = sky_material

	var env: Environment = Environment.new()
	env.background_mode = Environment.BG_SKY
	env.sky = sky
	env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
	env.ambient_light_energy = 0.7

	var world: WorldEnvironment = WorldEnvironment.new()
	world.environment = env
	add_child(world)


func _add_light() -> void:
	var light: DirectionalLight3D = DirectionalLight3D.new()
	light.rotation_degrees = Vector3(-55, -35, 0)
	light.light_energy = 1.2
	light.shadow_enabled = true
	add_child(light)
scripts/player.gd
extends CharacterBody3D

const SPEED: float = 7.0
const GRAVITY: float = 16.0
const SIZE: Vector3 = Vector3(1.2, 1.2, 1.2)


func _ready() -> void:
	var mesh: BoxMesh = BoxMesh.new()
	mesh.size = SIZE

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color('#8eef97')
	material.roughness = 0.4

	var visual: MeshInstance3D = MeshInstance3D.new()
	visual.mesh = mesh
	visual.material_override = material
	add_child(visual)

	var shape: BoxShape3D = BoxShape3D.new()
	shape.size = SIZE

	var collision: CollisionShape3D = CollisionShape3D.new()
	collision.shape = shape
	add_child(collision)


func _physics_process(delta: float) -> void:
	if not is_on_floor():
		velocity.y -= GRAVITY * delta

	var direction: Vector3 = Vector3(
		float(Input.is_key_pressed(KEY_D)) - float(Input.is_key_pressed(KEY_A)),
		0,
		float(Input.is_key_pressed(KEY_S)) - float(Input.is_key_pressed(KEY_W))
	).normalized()

	velocity.x = direction.x * SPEED
	velocity.z = direction.z * SPEED

	move_and_slide()

更多3D 场景示例