跳到主要内容

场景1—相机控制

概述

这个案例实现了通过键盘控制一个相机移动的效果,主要使用到了Input方法和事件,以及向量和运动学的相关内容,完整的项目介绍请见应用教程

场景准备

创建一个3D场景,场景中有一个飞行相机,删除这个相机,新建一个空相机:

场景结构如下:

脚本实现

相机节点新建一个脚本。

自定义变量

移动的主要参数有速度和方向,其中速度添加一个export关键字,这样可以通过属性栏对其进行快速设置,而不需要在脚本中进行修改。

export var speed = 4 #移动速度,单位为m/s
var direction = Vector3.ZERO #移动方向

属性栏中的脚本变量:

键盘控制相机移动

移动功能通过在物理进程_physics_process中调用自定义的移动方法update_move实现,_phyicis_process方法会每帧循环调用,带有一个用于表示帧时差的参数delta,将这个参数传递到update_move

func _physics_process(delta):
update_move(delta)
info

_physics_process方法的帧时差是固定的,按每秒60帧的速度执行,物理运动相关的方法一般都在此方法内实现,可以避免硬件运算速度不同导致的偏差;

如果想要一个基于设备本身的帧速率调用的进程,可以使用_process方法,该方法会基于设备尽可能快地调用,帧时差也会发生变化。

移动方法实现如下。这个方法首先获取一个移动的时间,根据时间、速度、方向可以得出位移。移动的实现通过按键映射表实现,使用Input单例快速获取按键事件并根据按键改变方向,最后使用translate方法移动物体

info

Input单例的使用方法详情可以通过脚本编辑器的搜索帮助查看,本教程其他案例中的大部分默认方法和类型都可以通过此方法查阅相关详情。

func update_move(delta_time):
direction = Vector3.ZERO
#前进,”move_forward"在映射表中对应W键
if Input.is_action_pressed("move_forward"):
direction += Vector3.FORWARD

#后退,”move_backward"在映射表中对应S键
if Input.is_action_pressed("move_backward"):
direction += Vector3.BACK

#左移,”move_left"在映射表中对应A键
if Input.is_action_pressed("move_left"):
direction += Vector3.LEFT

#右移,”move_right"在映射表中对应D键
if Input.is_action_pressed("move_right"):
direction += Vector3.RIGHT

#升高,”move_up"在映射表中对应Q键
if Input.is_action_pressed("move_up"):
direction += Vector3.UP

#下降,”move_down"在映射表中对应E键
if Input.is_action_pressed("move_down"):
direction += Vector3.DOWN

#根据帧时差、速度、方向计算位移,并移动物体
translate(delta_time*speed*direction)

右键拖动旋转镜头

实现旋转功能需要计算一定时间内鼠标的位移差来获取鼠标的位移,将鼠标的位移转换为旋转的度数。定义一个局部变量,通过局部变量计算两帧之间鼠标位置的差值,根据差值旋转相机

    var mouse_position = get_viewport().get_mouse_position() #获取当前鼠标位置
var offset = mouse_position - mouse_position_last_frame #计算和上一帧位置的差值
mouse_position_last_frame = mouse_position #保存当前位置,用于下一帧计算

使用Input单例获取鼠标的按下状态,如果按下了鼠标右键,将得到的差值向量在X、Y轴上的两个值分别映射到相机Y、X轴的旋转上,

    #当按下右键时旋转相机
if Input.is_mouse_button_pressed(BUTTON_RIGHT):
#通过差值旋转相机
rotate_object_local(Vector3(1, 0, 0), -deg2rad(offset.y)) #绕向量(1, 0, 0)旋转y轴
rotate_y(-deg2rad(offset.x)) #绕自身x轴旋转x轴

鼠标滚轮推进镜头

滚动鼠标滚轮时进行相机镜头的拉近、拉远。滚轮也是鼠标按钮事件的一种,需要在_input函数中通过Input单例获取

func _input(event):
if Input.is_mouse_button_pressed(BUTTON_WHEEL_DOWN):
translate(Vector3(0, 0, 1))
if Input.is_mouse_button_pressed(BUTTON_WHEEL_UP):
translate(Vector3(0, 0, -1))