Skip to main content

混合姿势节点

概述

混合姿势(Blend Pose)节点包括按布尔型混合姿势(Blend Pose By Bool)节点和按整型混合姿势(Blend Pose By Int)节点,使用该类节点可切换不同的姿势,并且切换时过渡自然流畅,不会过于突兀。

按布尔型混合姿势节点

按布尔型混合姿势(Blend Pose By Bool)节点根据各类参数(除向量参数)结合操作符的使用来控制输出姿势在两个输入姿势之间进行切换,最终结果为false时输出假姿势(False Pose),为true时输出真姿势(True Pose)

节点使用

动画树(Anim Tree)空白处右键打开节点选择面板,展开混合(Blends)分类并从中选取按布尔型混合姿势(Blend Pose By Bool)

image-20230704151525224

成功添加节点:

image-20230704151545251

可以继续为节点配置合适的输入/输出。

image-20230704151840258

属性

选中节点后,可以在属性窗口(Property Window)中看到该节点的各项属性。

image-20220913134344953

属性说明
过渡模式(Transition Mode)播放节点时采用的过渡模式。
  • 交叉淡入淡出(Cross Fade):原动画权重逐渐减少,新动画权重逐渐增加。
  • 惯性过渡(Inertia Transition):在过渡开始时保留原动画的惯性,过渡中原动画惯性逐渐消失。
假混合时间(False Blend Time)混入假姿势混合所需的时间。
真混合时间(True Blend Time)混入真姿势混合所需的时间。
回调字符串(Callback String)配置回调函数,根据返回值决定是否迁移。
是否使用条件(Use Conditions)勾选后,可选择除向量外的其他参数用于条件表达式,将最终结果用于控制节点混合,可参考动画参数文档中的使用参数部分。

按整型混合姿势节点

按整型混合姿势(Blend Pose By Int)节点可根据整型参数控制输出姿势在多个输入姿势中进行切换,整型参数值为0时输出混合姿势0(Blend Pose 0),为1时输出混合姿势1(Blend Pose 1),依此类推。

节点使用

动画树(Anim Tree)空白处右键打开节点(Nodes)选择面板,展开混合(Blends)分类并从中选取按整型混合姿势(Blend Pose By Int)

image-20230704151919099

成功添加节点:

点击节点上添加引脚(Add Pin)可以为其添加新的引脚。

成功添加引脚:

若要删除新添加的引脚,可右击引脚,选择删除引脚(Delete Pin)即可删除该引脚。初始的两个混合姿势引脚不可删除。

image-20230704152805290

然后可以继续为节点配置合适的输入/输出。

image-20230704093757662

属性

选中节点后,可以在属性窗口(Property Window)中看到该节点的各项属性。

image-20230625163411585

属性说明
过渡模式(Transition Mode)播放节点时采用的过渡模式。
  • 交叉淡入淡出(Cross Fade):原动画权重逐渐减少,新动画权重逐渐增加。
  • 惯性过渡(Inertia Transition):在过渡开始时保留原动画的惯性,过渡中原动画惯性逐渐消失。
混合时间列表(Blend Time)各姿势混入所需要的时间。
回调字符串(Callback String)配置回调函数,根据返回值决定是否迁移。
参数(Parameter)勾选后代表该属性使用动画整型参数。在下拉列表中指定从哪个参数中获取参数控制量。

示例

以下是使用按整型混合姿势(Blend Pose By Int)节点来切换动画姿势的一个简单示例。

创建组合体

参考Actor组装创建一个组合体(Actor),包含SK_Human_tpose、ALS_CLF_Walk_B和ALS_N_Run_F动画资产。

image-20230703095411753

配置动画树

在该组合体编辑器(Actor Editor)动作列表(Action List)中双击一个骨架资产打开动画编辑器(Animation Editor)

image-20230703095458621

创建一个动画树。在打开的动画编辑器(Animation Editor)中,依次点击菜单栏文件(File)-> 创建(Create),在弹出的窗口中点击下拉框选择动画树(AnimTree),为其命名并选择创建路径,点击是(Yes)完成创建并进入到动画树编辑器(Anim Tree Editor)

image-20230626135426638

在动画树中添加一个按整型混合姿势(Blend Pose By Int)节点,分别为混合姿势0(Blend Pose 0)混合姿势1(Blend Pose 1)引脚链接一个序列播放节点,最后将按整型混合姿势节点链接到最终动画姿势(Final Animation Pose)节点。

image-20230703095741235

动画参数(Animation Parameter)窗口中,点击 image-20230626144933359 按钮后选择整型(Int) 创建一个整型参数。

image-20230626155333308

创建完成后,修改它的参数名称(Parameter Name)为WalkIndex。

image-20230703095807817

选中按整型混合姿势(Blend Pose By Int)节点,在属性窗口(Property Window)中勾选参数(Parameter),然后在其下拉框中选择刚才所创建的WalkIndex整型参数。其他属性可根据需求自行设置。

image-20230703174850486

编辑完成后,点击应用(Apply)按钮,在其旁边的下拉框中选择预览对象(Preview Object),然后后续可在预览(Preview)窗口中查看效果。

image-20230703100133527

动画参数(Animation Parameter)窗口的参数实例值(Parameter Instance Value)中输入0则会播放输入到混合姿势0(Blend Pose 0)引脚的动画,输入1则会播放输入到混合姿势1(Blend Pose 1)引脚的动画。

Preview

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

image-20230703175012352

配置组合体

在组合体编辑器中点击资产细项(Asset Details),将默认动作(Default Action)设置为所创建的动画树test_tree,然后点击保存(Save)

image-20230627141036082

输入设置

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

image-20230627141316661

项目设置(Project Settings)窗口中点击输入设置(Input Settings),点击组合映射列表(Combination Mapping List)栏中的 image-20230627142225380 按钮添加一个新的组合映射。

image-20230627142452193

在新创建的组合映射中,输入组合名称(Combination Name),并在键名(Key Name)中指定一个按键。

image-20230703175258896

创建角色

在组件编辑器中创建一个关卡,然后依次点击创建游戏对象(Create Game Object)-> 角色(Character)

image-20230627144219046

大纲(Hierarchy)面板中选中该角色对象,然后在观察器(Inspector)面板中选中CharacterMesh0(Inherited),从资源预览窗口中将所创建的组合体(Actor)文件拖到骨架网格体配置文件(Skeletal Mesh Config File)的插槽中。

image-20230627152057044

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

image-20230703175500815

观察器(Inspector)面板中,选中CharacterMesh0(Inherited),然后点击添加组件(Add Component),选择摄像机组件(Camera Component)

image-20230627154221191

image-20230627154241835

添加完成:

image-20230703180033275

调整所创建的摄像机到合适位置和角度。

image-20230703175554073

观察器(Inspector)面板中,选中LCharacter(Instance),将自动持有玩家(Auto Possess Player)设置为玩家0(Player 0)

image-20230628093048703

为角色绑定脚本

观察器(Inspector)面板中选中LCharacter(Instance),然后点击添加组件(Add Component)按钮,选择脚本组件(Script Component)

image-20230627154306436

image-20230627154341148

添加完成:

image-20230627154457338

为该角色绑定脚本。编写一个脚本并将其保存在项目资源中的脚本文件夹中。在大纲(Hierarchy)面板中选中LCharacter,然后在观察器(Inspector)面板中选中LScript,从资源预览窗口中将脚本拖入到脚本文件(Script File)插槽中。

image-20230703175700483

绑定完成:

image-20230628093355038

脚本

以下脚本仅供参考:

robot_character.lua

--script template

require("public_attr")

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

--获取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

--walk
function on_enable_walk_pressed(owner)
local actor = character_get_actor(owner)
if not nx_is_valid(actor) then
return
end

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
if actor:GetAnimTreeValue(action_index, "WalkIndex") == 0 then
actor:SetAnimTreeValue(action_index, "WalkIndex", 1)
else
actor:SetAnimTreeValue(action_index, "WalkIndex", 0)
end
end
end


function get_object_by_tag(lscene, tag_name, class_type_name)
--local lscene = nx_value("lscene")
if not nx_is_valid(lscene) then
return nx_null()
end

if tag_name == nil then
return nx_null()
end

local tag_table = lscene:QueryObjectListByTag(tag_name, class_type_name)
local tag_count = #tag_table
if tag_count == 0 then
return nx_null()
elseif tag_count == 1 then
return tag_table[1]
elseif tag_count > 1 then
for i = 1, tag_count do
nx_log("info, get_object_by_tag, "
..nx_string(i) .." : "..nx_string(tag_table[i].StringTag))
end
return nx_null()
end
end

function input_comp_init_bind(component)
local owner = component.GameObjectOwner

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

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

input_comp:AddCombinationBinding("EnableWalk", IE_Pressed, true, false, true, "InputActionEvent_EnableWalk_Pressed")

nx_callback(owner, "InputActionEvent_EnableWalk_Pressed", "on_enable_walk_pressed")
end
end
end

--use this for initialization
function on_begin_play(component)
input_comp_init_bind(component)
nx_callback(component, "on_tick", "tick")
end

function tick(component, delta_time)
if not nx_is_valid(component) then
return
end

local lscene = component.Scene

local owner = component.GameObjectOwner
local actor = character_get_actor(owner)
local target_pawn = get_object_by_tag(lscene, "Pawn_0", "LCharacter")
if not nx_is_valid(target_pawn) then
return
end
end

public_attr.lua

--资源管理器:全局变量

MODEL_PATH = "mdl\\"
MODEL_PATH_DX9 = ""
ACTOR_PATH = "ini\\actor\\"
ACTOR_PATH_DX9 = "ini\\actor\\"
LIGHT_PATH = "ini\\light\\"
LIGHT_PATH_DX9 = "ini\\light\\"
EFFECT_PATH = "ini\\effect\\"
PARTICLE_PATH = "ini\\particle\\"
SOUND_PATH = "snd\\"
REVERB_PATH = "reverb\\"
TRIGGER_PATH = "ini\\trigger\\"
PROBE_PATH = "ini\\light_probe\\"
VOLUME_FOG_PATH = "ini\\volume_fog\\"
MATERIAL_PATH = ""

--资源类型定义
TYPE_MODEL = "model"
TYPE_ACTOR = "actor"
TYPE_LIGHT = "light"
TYPE_EFFECT = "effect"
TYPE_PARTICLE = "particle"
TYPE_SOUND = "sound"
TYPE_REVERB = "reverb"
TYPE_TRIGGER = "trigger"
TYPE_PROBE = "light_probe"
TYPE_VOLUME_FOG = "volume_fog"
TYPE_DECAL = "decal"
TYPE_GROUP = "group"
TYPE_RIPPLE = "ripple"
TYPE_SNOW = "snow"
TYPE_RAIN = "rainlayer"
TYPE_UI3D = "ui3d"

--动画资源类型
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

TYPE_LIST = {
"model",
"actor",
"light",
"effect",
"particle",
"decal",
"sound",
"reverb",
"trigger",
"light_probe",
"volume_fog",
"ripple",
"snow",
"rainlayer",
}

FORM_TREE_BROWSER = "common_form\\form_tree_browser"
SEARCH_PATH = "ini\\common_form\\form_tree_browser\\"
SEARCH_CONFIG = SEARCH_PATH .. "form_put_visual.ini"
SEARCH_CONFIG_TEMP = "cache\\common_form\\form_tree_browser\\form_put_visual_temp.ini"
GROUP_CONFIG = "ter\\visual_group.ini"

--获取visual_put文件
function get_search_file()
local ini = nx_create("IniDocument")

ini.FileName = nx_resource_path() .. SEARCH_CONFIG

if not ini:LoadFromFile() then
nx_destroy(ini)
return 0
end

local file = ini:ReadString("SEARCH_CONFIG", "search_file", "form_put_visual.ini")

nx_destroy(ini)

return nx_resource_path() .. SEARCH_PATH .. file, file
end

运行

点击运行按钮后,按5键可切换角色动画。

Preview02