角色快速入门
最近更新时间:2023-09-18
概述
本文档介绍了如何创建一个可控玩家角色。
创建项目
新建一个空项目,详见项目。
创建关卡
新建一个默认关卡,详见关卡。
导入美术资源
导入骨架网格体和动画。详见资源工作流程。
骨架网格体:
关于如何为模型(.xmod)设置材质可参考材质编辑器。
动画:
Actor组装
创建一个包含所需动画资产的组合体(Actor),详见Actor组装。
配置动画树
创建动画树
添加状态机节点
可先参考动画状态机了解状态机节点的相关内容。
添加一个状态机(State Machine)节点,并连接到最终动画姿势(Final Animation Pose)。
双击该状态机(State Machine)节点,进入状态图的编辑界面,添加Idle和Run两个状态(State)节点,并连接这两个状态,使这两个状态可形成一个循环。
双击Idle状态节点,在该状态中添加站立动画。添加一个序列播放节点,并将其连接到最终动画姿势(Final Animation Pose)。
同样的,在Run状态中添加跑步动画,并将其连接到最终动画姿势(Final Animation Pose)。
在动画编辑器中的参数(Parameter)窗口中,点击按钮,选择浮点(Float),添加一个浮点型参数。
将所添加参数的参数名称(Parameter Name)修改为Speed。
选中Idle -> Run的状态迁移,在属性窗口(Property Window)中勾选使用条件(Use Condition)后,点击 按钮添加一个条件,将该条件设置为Speed大于0.1。
将Run -> Idle的状态迁移条件设置为Speed小于0.1。
点击保存(Save)按钮,保存该动画树。
输入设置
在组件编辑器(Component Editor)中,依次点击菜单栏配置(Config) -> 项目设置(Project Settings),打开项目设置窗口。
在项目设置(Project Settings)窗口中,点击输入设置(Input Settings)切换到输入设置界面,点击轴映射列表(Axis Mapping List)旁的 可添加新的轴映射。添加如下图中的7个轴映射。
创建角色
依次点击工具栏创建游戏对象(Create Game Object) -> 角色(Character),创建一个玩家角色。
在观察器(Inspector)面板中选中CharacterMesh0(Inherited),从项目(Project)面板中,将之前所创建的组合体文件(.actor)拖拽到骨架网格体配置文件(Skeletal Mesh Config File)中。
拖拽完成:
修改默认行为覆盖(Default Action Override)属性为之前创建的动画树tp_tree。
在观察器(Inspector)面板中,选中CollisionCylinder(Inherited)和CharacterMesh0(Inherited)分别调整该角色胶囊体和网格体的位置,使胶囊体尽可能在包裹角色的前提下,让蒙皮角色的脚部贴地,胶囊体也需在地面上方。
为CollisionCylinder(Inherited)组件添加一个弹簧臂组件(Spring Arm Component)作为其子组件。选中CollisionCylinder(Inherited),点击添加组件(Add Component),选择弹簧臂组件(Spring Arm Component)。
为弹簧臂组件(LSpringArm)添加一个摄像机组件(Camera Component)作为其子组件。
调整摄像机组件至合适位置。
选中角色对象,在观察器(Inspector)面板中选中LCharacter(Instance),然后将下方的自动持有玩家(Auto Possess Player)设置为玩家0(Player 0),此时PIE后会自动使用角色身上的摄像机。
取消勾选使用控制器偏航角(Use Controller Angle Yaw)。
选中弹簧臂组件(LSpringArm),勾选使用角色控制旋转(Use Pawn Control Rotation)和启用摄像机延迟(Enable Camera Lag),取消勾选做碰撞测试(Do Collision Test)。
选中CharMoveComp(Inherited),勾选朝移动方向旋转(Orient Rotation To Movement)。
编写角色控制脚本
选择项目(Project)面板中的script文件夹,然后在资源预览窗口中右键打开快捷菜单,选择脚本(Script File),创建一个脚本文件controller.lua。
双击所创建的脚本文件,可打开编写脚本的界面。
编写如下脚本代码:
--动画资源类型
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)。
从项目(Project)面板中将controller.lua脚本文件拖拽到脚本组件的脚本文件(Script File)中。
拖拽完成:
运行
PIE后,可通过WASD键控制角色移动,按住鼠标右键移动可转动视角,通过鼠标滚轮可拉近拉远摄像机。