Skip to main content

角色快速入门

最近更新时间:2023-09-18

概述

本文档介绍了如何创建一个可控玩家角色。

创建项目

新建一个空项目,详见项目

创建关卡

新建一个默认关卡,详见关卡

导入美术资源

导入骨架网格体和动画。详见资源工作流程

骨架网格体:

image-20230913095726019

关于如何为模型(.xmod)设置材质可参考材质编辑器

动画:

image-20230913095421879

Actor组装

创建一个包含所需动画资产的组合体(Actor),详见Actor组装

image-20230913100856266

配置动画树

创建动画树

打开动画编辑器后,创建一个动画树

image-20230907101710504

添加状态机节点

可先参考动画状态机了解状态机节点的相关内容。

添加一个状态机(State Machine)节点,并连接到最终动画姿势(Final Animation Pose)

image-20230911105949973

双击该状态机(State Machine)节点,进入状态图的编辑界面,添加Idle和Run两个状态(State)节点,并连接这两个状态,使这两个状态可形成一个循环。

image-20230911112520297

双击Idle状态节点,在该状态中添加站立动画。添加一个序列播放节点,并将其连接到最终动画姿势(Final Animation Pose)

image-20230911113121435

同样的,在Run状态中添加跑步动画,并将其连接到最终动画姿势(Final Animation Pose)

image-20230911113638106

在动画编辑器中的参数(Parameter)窗口中,点击image-20230911131222889按钮,选择浮点(Float),添加一个浮点型参数。

image-20230911131442794

将所添加参数的参数名称(Parameter Name)修改为Speed。

image-20230911131628790

选中Idle -> Run的状态迁移,在属性窗口(Property Window)中勾选使用条件(Use Condition)后,点击 image-20230911131934987 按钮添加一个条件,将该条件设置为Speed大于0.1。

image-20230911132219076

将Run -> Idle的状态迁移条件设置为Speed小于0.1。

image-20230911132431907

点击保存(Save)按钮,保存该动画树。

image-20230911133100783

输入设置

组件编辑器(Component Editor)中,依次点击菜单栏配置(Config) -> 项目设置(Project Settings),打开项目设置窗口。

image-20230911135342360

项目设置(Project Settings)窗口中,点击输入设置(Input Settings)切换到输入设置界面,点击轴映射列表(Axis Mapping List)旁的 image-20230911141512266 可添加新的轴映射。添加如下图中的7个轴映射。

image-20230911142815681

image-20230911142949773

创建角色

依次点击工具栏创建游戏对象(Create Game Object) -> 角色(Character),创建一个玩家角色。

image-20230911143616864

观察器(Inspector)面板中选中CharacterMesh0(Inherited),从项目(Project)面板中,将之前所创建的组合体文件(.actor)拖拽到骨架网格体配置文件(Skeletal Mesh Config File)中。

image-20230911161554646

拖拽完成:

image-20230911173341050

修改默认行为覆盖(Default Action Override)属性为之前创建的动画树tp_tree。

image-20230912162842193

观察器(Inspector)面板中,选中CollisionCylinder(Inherited)和CharacterMesh0(Inherited)分别调整该角色胶囊体和网格体的位置,使胶囊体尽可能在包裹角色的前提下,让蒙皮角色的脚部贴地,胶囊体也需在地面上方。

image-20230912163030263

为CollisionCylinder(Inherited)组件添加一个弹簧臂组件(Spring Arm Component)作为其子组件。选中CollisionCylinder(Inherited),点击添加组件(Add Component),选择弹簧臂组件(Spring Arm Component)

image-20230912163110699

image-20230911175915207

弹簧臂组件(LSpringArm)添加一个摄像机组件(Camera Component)作为其子组件。

image-20230912163140323

调整摄像机组件至合适位置。

image-20230912163234099

选中角色对象,在观察器(Inspector)面板中选中LCharacter(Instance),然后将下方的自动持有玩家(Auto Possess Player)设置为玩家0(Player 0),此时PIE后会自动使用角色身上的摄像机。

image-20230912163301191

取消勾选使用控制器偏航角(Use Controller Angle Yaw)

image-20230912163331170

选中弹簧臂组件(LSpringArm),勾选使用角色控制旋转(Use Pawn Control Rotation)启用摄像机延迟(Enable Camera Lag),取消勾选做碰撞测试(Do Collision Test)

image-20230912163403574

选中CharMoveComp(Inherited),勾选朝移动方向旋转(Orient Rotation To Movement)

image-20230912163430244

编写角色控制脚本

选择项目(Project)面板中的script文件夹,然后在资源预览窗口中右键打开快捷菜单,选择脚本(Script File),创建一个脚本文件controller.lua。

image-20230912111715432

双击所创建的脚本文件,可打开编写脚本的界面。

image-20230912111814209

编写如下脚本代码:

--动画资源类型
AT_UNKNOWN = 0
AT_SKELETON = 1
AT_SKELETON_AS_ANIMSEQUENCE = 2
AT_ANIMSEQUENCE = 3
AT_MONTAGE = 4
AT_BLENDSPACE = 5
AT_BLENDSPACE1D = 6
AT_AIMOFFSETBLENDSPACE = 7
AT_ANIMTREE = 8

local IE_Pressed = 0 --按键按下
local IE_Released = 1 --按键抬起
local IE_Repeat = 2
local IE_DoubleClick = 3
local IE_Axis = 4
local IE_MAX = 5

local CAMERA_DISTANCE_CHANGE_SPEED = 0.5
local CAMERA_DISTANCE_MIN = -1
local CAMERA_DISTANCE_MAX = 50


--use this for initialization
function on_begin_play(component)
local owner = component.ActorOwner

if nx_is_valid(owner) then
local input_comp = owner.InputComponent

if nx_is_valid(input_comp) then
nx_bind_script(owner, nx_current())

--第一个参数对应输入设置中的Axis Name
--最后一个参数为自定义事件名
input_comp:AddAxisBinding("MoveForward", true, false, true, "InputAxisEvent_MoveForward")
input_comp:AddAxisBinding("MoveRight", true, false, true, "InputAxisEvent_MoveRight")
input_comp:AddAxisBinding("Turn", true, false, true, "InputAxisEvent_Turn")
input_comp:AddAxisBinding("LookUp", true, false, true, "InputAxisEvent_LookUp")
input_comp:AddAxisBinding("AdjustCameraDis", true, false, true, "InputAxisEvent_AdjustCameraDis")

--第二个参数为AddAxisBinding中的最后一个参数,最后一个参数表示脚本中的函数名
nx_callback(owner, "InputAxisEvent_MoveForward", "on_moveforward")
nx_callback(owner, "InputAxisEvent_MoveRight", "on_moveright")
nx_callback(owner, "InputAxisEvent_Turn", "on_turn")
nx_callback(owner, "InputAxisEvent_LookUp", "on_lookup")
nx_callback(owner, "InputAxisEvent_AdjustCameraDis", "on_adjust_camera_dis")

nx_callback(owner, "on_velocity_changed", "on_velocity_changed")

end
end

nx_callback(component, "on_tick", "tick")
end

--use this for release
function on_end_play(component)
end

--获取actor
function character_get_actor(character)
if nx_is_valid(character) then
local mesh_component = character.MeshComponent

if nx_is_valid(mesh_component) then
local vis_base = mesh_component.VisBase

if nx_is_valid(vis_base) and nx_is_kind(vis_base, "Actor") then
return vis_base
end
end
end

return nx_null()
end

--获取spring_arm
function character_get_spring_arm(character)
if nx_is_valid(character) then
local spring_arm_component = character:FindComponentByClassName("LSpringArmComponent")

return spring_arm_component
end

return nx_null()
end

--向前移动回调
function on_moveforward(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end

--获得控制器Y轴角度
local controller = owner.Controller

if nx_is_valid(controller) then
local yaw = controller.AngleY
--获得向前方向
local x, y, z = nx_function("ext_angle_get_forward_vector", 0.0, yaw, 0.0)

--增加移动量

owner:AddMovementInput(x, y, z, axis_value)
end

return 1
end

--向右移动回调
function on_moveright(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end

--获得控制器Y轴角度
local controller = owner.Controller

if nx_is_valid(controller) then
local yaw = controller.AngleY
--获得向右方向
local x, y, z = nx_function("ext_angle_get_right_vector", 0.0, yaw, 0.0)

--增加移动量
owner:AddMovementInput(x, y, z, axis_value)
end
return 1
end

--左右旋转(绕Y轴旋转)回调
function on_turn(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end

owner:AddControllerYawInput(axis_value)

return 1
end

--上下旋转(绕X轴旋转)回调
function on_lookup(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end

owner:AddControllerPitchInput(-axis_value)

return 1
end

--鼠标滚轮回调
function on_adjust_camera_dis(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end

local spring_arm_component = character_get_spring_arm(owner)

if nx_is_valid(spring_arm_component) then
local delta = axis_value * CAMERA_DISTANCE_CHANGE_SPEED

local cur_value = spring_arm_component.TargetArmLength
local new_value = cur_value + delta

if delta > 0 then
if new_value > CAMERA_DISTANCE_MAX then
new_value = CAMERA_DISTANCE_MAX
end

spring_arm_component.TargetArmLength = new_value
else
if new_value < CAMERA_DISTANCE_MIN then
new_value = CAMERA_DISTANCE_MIN
end
spring_arm_component.TargetArmLength = new_value
end
end

return 1
end


--速度变化回调
function on_velocity_changed(owner, component_id, new_x, new_y, new_z, old_x, old_y, old_z)
local actor = character_get_actor(owner)

if nx_is_valid(actor) then
if actor:GetBlendActionCount() > 0 then
local action_name = actor:GetBlendActionName(0)
local action_type = actor:GetActionType(action_name)
local action_index = actor:GetActionIndex(action_name)

if action_type == AT_ANIMTREE then
local speed = math.sqrt(new_x * new_x + new_y * new_y + new_z * new_z)
actor:SetAnimTreeValue(action_index, "Speed", speed)

nx_set_custom(actor,"CurSpeed",speed);
end
end
end

return 1
end

绑定角色控制脚本

选中LCharacter(Instance),然后添加一个脚本组件(Script Component)

image-20230912163507071

项目(Project)面板中将controller.lua脚本文件拖拽到脚本组件的脚本文件(Script File)中。

image-20230912163538328

拖拽完成:

image-20230912163613317

运行

PIE后,可通过WASD键控制角色移动,按住鼠标右键移动可转动视角,通过鼠标滚轮可拉近拉远摄像机。

Preview