Melee Component Manual
Overview
The Melee Collision Component provides the collision detection feature on the motion trajectory of the character's weapon when playing the character's attack action.
Melee Collision Components
Adding Melee Collision Components
Select an object in the Hierarchy panel, then in the Inspector panel, click Add Component and select Melee Collision Component to add one.
After adding:
Properties
In the Inspector panel, select LMeleeCollision and the relevant properties of this component will be displayed below.
Debug
Debug is used to turn on or turn off the collision detection debugging information, which includes the weapon collider's motion trajectory, impact points, etc.
Property | Description |
---|---|
Direction Of Weapons | Used to display the direction of Weapons. Generally, the direction of a weapon is taken from one of the axis vectors of the weapon model's coordinate system. The weapon's axis vector can be switched in the Main Axis property in Weapons -> Advance, with Detailed Collision enabled. ![]() |
Collision Result | When enabled, the position at which the collision is generated during the collision detection process is displayed as a blue geometry. |
Collision Trajectory | Can be enabled only when Collision Result is enabled. When enabled, the motion trajectory of the weapon during the Melee weapon collision detection process will be displayed in the scene as a gray geometry. |
Exist Time | Used to set the display time of the Collision Result geometry and the Collision Trajectory geometry. |
Ignore Raycast Result | When enabled, only the impact point will be left when the raycast illuminates on an object in the scene, and a red ball will be drawn at the impact point. |
Ignore Overlap Result | When enabled, the motion trajectory of the collider is no longer displayed in the scene. |
Ignore Sweep Result | When enabled, the green line, the start and end position of the sweep detection are no longer drawn when objects collide in the scene. |
Ignore Detailed Collision Data | Enable/disable accurate collision detection. If disabled, the specific impact point of the collision detection will be calculated when accurate detection is performed. If enabled, it will only determine if any object is hit, and will not record the specific position where collisions occur. |
Damage Event
Damage Event is used to calculate damage in game logic, including damage and impact.
Property | Description |
---|---|
Generate Damage Event | When enabled, the game logic can get the detailed damage information. |
Damage Degree | The amount of damage caused. |
Momentum | The amount of impact force caused. |
Ignore Game Object
Add or delete the game object that needs to be ignored.
Property | Description |
---|---|
Ignore Game Object | Select the Game Object (the Game Object in the current Level) to be ignored , and this Game Object does not perform collision detection in the game. |
Buttons
Button | Description |
---|---|
Add a new Ignore Game Object. | |
Delete the current Ignore Game Object. | |
Delete all Ignore Game Objects. | |
Copy the current Ignore Game Object. |
Weapons
Add weapons. Select the colliders to be involved in the detection and the collision detection trigger method.
Property | Description |
---|---|
Collider Component | The component that needs to be involved in the Melee weapon collision detection. Select the collider in this component to act as a weapon to perform collision detection. |
Bone Name | The bone selected in the Collider Component that acts as a weapon. |
Collider Index | Select the collider to be involved in the Melee weapon collision detection under the current bone. |
Interpolation Number | Select the interpolation number. Interpolation Number: In the process of animation playback, there may be the case that the collider's displacement between frames is too large. In this case, an appropriate Interpolation Number needs to be selected to fill the collider's displacement between frames (If the weapon collider is too small or the speed of the attack action is too fast, the Interpolation Number needs to be increased, otherwise there is a probability of missing detection). |
Weapon Group | Notify all Weapons in the corresponding group to turn on collision detection when the event is triggered. |
Valid | Whether the weapon is effective. Check it to take effect and uncheck it to not take effect. |
Trigger Mode | Select the trigger mode.
|
Detailed Collision | Enable the raycast collision to record impact points where collisions with weapons and raycasts occur. |
Main Axis | Adjust the raycast direction. |
Script
Add the Script File.
Property | Description |
---|---|
Script File | Script File name. Select the script file to bind to. |
Specified Skeletal Mesh | After selecting any LSkeletalMeshComponent component in the current object, the current Melee component will perform collision detection according to the animation playback of the selected LSkeletalMeshComponent. |
Quick Start
The following is an example of using Melee.
Creating Actors
Refer to Assembling Actors to create an Actor containing animations assets SK_Avatar_tpose, Avatar_Attack and Avatar_Walk.
Adding Collision Detection Events to Animations
Click one of the animation assets in the Actor Editor to open the Animation Editor.
In Asset Browser of the Animation Editor, select Avatar_Attack, right-click it to open the shortcut menu, then select Convert Skeleton To AnimSeq, enter the name in the pop-up window and click the OK button to complete the conversion. This animation sequence asset will be used to add the collision detection event.
Double-click the converted animation sequence asset, right-click the Notify track and click Add Notify -> Collision Detection Notify to add a Collision Detection Notify.
After adding:
Select appropriate frames of the Notify as its start and end based on the model's action position in the Viewport. Refer to Adjusting State Notifies to adjust the Notify.
Right-click the created Collision Detection Notify and set Trigger Weight in the pop-up Notify window. It determines whether to trigger the Notify when blending animations, and the Notify will be triggered only when the current animation blending degree exceeds the set value. When Trigger Weight is set to 0, the Melee weapon collision detection will be performed during the Notify triggering period, even if the character is not playing an attack action.
Select the Collision Detection Notify, then in the Details Panel, click the button to add a Weapon Group and set it to be notified. If no specific Weapon Group is set, then all Weapons in the Melee Collision Component will be notified.
After setting, click File (in the Menu bar) -> Save All.
Configuring Animation Trees
Create an Animation Tree, then create a State Machine node as well as the Animation Parameter to be used, and set the state transition conditions. The state graph is shown below:
Note: For details of this step, please refer to Character Quick Start -> Adding State Machine Nodes.
The Animation Tree associated with the idle state:
The Animation Tree associated with the walk state:
In the Slot Manager, create a slot named MeleeSlot.
Add a Slot "MeleeSlot" node to the Animation Tree and connect the nodes together as shown below.
For how to create slots and add Slot nodes, please refer to Animation Trees -> Slot Nodes.
After editing, click the Save button.
Configuring Actors
In the Actor Editor, click Asset Details, then set Default Action to the created Animation Tree, and click the Save button after setting.
Creating Ragdolls
Refer to Ragdoll Editor to create a Ragdoll resource for SK_Melee_Demo.actor, and add a Rigidbody to the bone hand_r.
Creating Characters
Create a Level and click Create Game Object -> Character to create a Character object.
In the Inspector panel, select CharacterMesh0(Inherited), and drag the .actor to be used from the Project panel into Skeletal Mesh Config File.
After dragging:
In the Inspector panel, select ColliderCylinder(Inherited) and CharacterMesh0(Inherited), then adjust the position of the Character's capsule and mesh respectively, so that the capsule wraps around the Character as much as possible and the feet of the Character's skin are on the ground. The capsule also needs to be above the ground.
Add a Spring Arm Component and a Camera Component to the Character and adjust the position and angle of the camera component to the appropriate values.
Select LCharacter(Instance) in the Inspector panel and set Auto Possess Player to Player 0.
Adding Melee Collision Components
Select the created Character object in the Hierarchy panel, and add a Melee Collision Component to the object (Refer to Adding Melee Collision Components).
Set the properties of the Melee Collision Component in the lower part of the Inspector panel.
Configure the damage in Damage Event and decide whether to enable Generate Damage Event as needed. If Damage Event is enabled, then configure the appropriate Damage Degree and Momentum.
Game Objects to be ignored can be added in Ignore Game Object.
Click the button in the Weapons title bar to add a weapon entry, then set Collider Component to CharacterMesh0, Bone Name to hand_r, and Trigger Mode to Collision Detection Notify , and check Detailed Collision. The detailed configuration is shown below:
After configuring each property, check Direction Of Weapons, Collision Result and Collision Trajectory in Debug, and set Exist Time to 0.5.
Creating Walls
Drag a model from the Project panel into the Level as a wall, and adjust its Position and Scale to the appropriate values.
Binding Scripts
Select the created Character object in the Hierarchy panel, then in the Inspector panel, click the Add Component button and select Script Component to add one.
Right-click a blank space in the Resource Preview window to open the Shortcut Menu and select Script File to create one.
Drag the created Script File into the Script File of the Script Component (LScript).
After dragging:
Script Files
The following is the reference script melee_character_demo.lua.
Refer to the on_setup_input_component() function in the following script to bind a callback to the Character.
Refer to the on_leftclick_pressed() function in the following script to blend the Attack animation in the callback function.
--script template
require("public_attr")
local IE_Pressed = 0 --Key pressed
local IE_Released = 1 --Key released
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
---------------------
--default callbacks--
---------------------
--use this for initialization
function on_begin_play(component)
local owner = component.GameObjectOwner
if nx_is_valid(owner) then
nx_bind_script(owner, nx_current())
nx_callback(owner, "on_setup_input_component", "on_setup_input_component")
nx_callback(owner, "on_velocity_changed", "on_velocity_changed")
local input_comp = owner.InputComponent
if nx_is_valid(input_comp) then
on_setup_input_component(owner, input_comp)
end
end
nx_callback(component, "on_tick", "tick")
end
--use this for release
function on_end_play(component)
end
--setup input component
function on_setup_input_component(pawn, input_comp)
if nx_find_custom(input_comp, "binded") and input_comp.binded then
return
end
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")
input_comp:AddCombinationBinding("LeftClick", IE_Pressed, true, false, true, "InputActionEvent_LeftClick_Pressed")
nx_callback(pawn, "InputAxisEvent_MoveForward", "on_moveforward")
nx_callback(pawn, "InputAxisEvent_MoveRight", "on_moveright")
nx_callback(pawn, "InputAxisEvent_Turn", "on_turn")
nx_callback(pawn, "InputAxisEvent_LookUp", "on_lookup")
nx_callback(pawn, "InputAxisEvent_AdjustCameraDis", "on_adjust_camera_dis")
nx_callback(pawn, "InputActionEvent_LeftClick_Pressed", "on_leftclick_pressed")
input_comp.binded = true
end
--Get the 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
--Get the 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
--Moving forward callback
function on_moveforward(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end
--Get the controller Angel Y
local controller = owner.Controller
if nx_is_valid(controller) then
local yaw = controller.AngleY
--Get the forward vector
local x, y, z = nx_function("ext_angle_get_forward_vector", 0.0, yaw, 0.0)
--Add movement input
owner:AddMovementInput(x, y, z, axis_value)
end
return 1
end
--Move right callback
function on_moveright(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end
--Get the controller Angel Y
local controller = owner.Controller
if nx_is_valid(controller) then
local yaw = controller.AngleY
--Get the right vector
local x, y, z = nx_function("ext_angle_get_right_vector", 0.0, yaw, 0.0)
--Add movement input
owner:AddMovementInput(x, y, z, axis_value)
end
return 1
end
--Left and right rotation (rotate around the Y-axis) callback
function on_turn(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end
owner:AddControllerYawInput(axis_value)
return 1
end
--Up and down rotation (rotate around the X-axis) callback
function on_lookup(owner, axis_value)
if not nx_is_valid(owner) then
return 0
end
owner:AddControllerPitchInput(-axis_value)
return 1
end
--Mouse wheel callback
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_leftclick_pressed(owner)
local actor = character_get_actor(owner)
if not nx_is_valid(actor) then
return
end
actor:BlendAction("Attack", false, false, true, 1.0, false, "MeleeSlot", true)
end
--Velocity change callback
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
function set_tree_state(actor, state_name, enable)
if not nx_is_valid(actor) then
return
end
-- Set state machine variables
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
actor:SetAnimTreeValue(action_index, state_name, enable)
end
end
end
-- Toggle ragdoll
function toggle_ragdoll(owner, key_name)
local actor = character_get_actor(owner)
if not nx_is_valid(actor) then
return
end
nx_set_value("default_actor", actor)
local mesh_component = owner.MeshComponent
if not nx_is_valid(mesh_component) then
return
end
-- Record mesh_component
actor.mesh_component = mesh_component
local enable_ragdoll = not mesh_component.SimulatePhysics
if (enable_ragdoll) then
mesh_component.SimulatePhysics = enable_ragdoll
set_tree_state(actor, "IsDead", true)
else
local capsule = owner.CapsuleComponent
if nx_is_valid(capsule) then
-- Record capsule
actor.capsule = capsule
end
-- Save Snapshot
actor:SavePoseSnapshot("finalpose")
mesh_component.SimulatePhysics = enable_ragdoll
-- Notify blended snapshot
set_tree_state(actor, "IsStopped", true)
-- Play the getup action
actor:BlendAction("GetUp_Back_montage", false, false, true, 1.0)
set_tree_state(actor, "IsDead", false)
-- Pause for 2 frames
nx_pause(0)
nx_pause(0)
-- Notify no more blended snapshot
set_tree_state(actor, "IsStopped", false)
end
end
function tick(component, delta_time)
update_capsule_location()
end
-- Update capsule location in ragdoll state
function update_capsule_location()
local actor = nx_value("default_actor")
if not nx_is_valid(actor) then
return
end
if not nx_find_custom(actor, "mesh_component") then
return
end
local mesh_component = actor.mesh_component
if not nx_is_valid(mesh_component) then
return
end
if mesh_component.SimulatePhysics then
if not nx_find_custom(actor, "capsule") then
return
end
local capsule = actor.capsule
if not nx_is_valid(capsule) then
return
end
local x, y, z = actor:GetNodeWorldPosition("pelvis")
capsule:SetPosition(x, capsule.PositionY, z)
end
end
public_attr.lua
--Resource Manager: Global Variables
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 = ""
--Resource Type Definitions
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"
--Animation Resource Types
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"
--Get the visual_put file
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
Debugging
Click the PIE button. Move the character to the wall and left-click to make the character play the attack action with his right hand colliding with the wall.
- Collision Trajectory in Grey : The motion trajectory during the Melee weapon collision detection.
- Collision Trajectory in Blue: There are collisions in the weapon motion trajectory rough detection.
- Raycast Detection in Red: The impact points where raycasts collide with objects in the scene.
- Sweep Detection in Green: When the weapon (hand_r's collider) collides with objects in the scene, the collider shape is drawn at the start point and end point and connected with a green line (Not displayed when the collider is a sphere).
When the collider is a box:
When the collider is a sphere:
When Weapons -> Trigger Mode -> Detailed Collision is enabled, the yellow line in the box below represents the orientation of the weapon's raycast axis vector.
In each of the following debugs, the selected collider is a box.
Turning off Collision Trajectory
Uncheck Collision Trajectory in Debug.
Turning off Collision Result
Uncheck Collision Result in Debug.
Turning off Raycast Detection
Check Ignore Raycast Result in Debug.
Turning off Motion Trajectory
Check Ignore Overlap Result in Debug.
Turning off Sweep Detection
Check Ignore Sweep Result in Debug.