BehaviourPuppet ,属于 RootMotion PuppetMaster 插件的一部分。PuppetMaster 是一个用于实现角色物理动画和布娃娃效果的插件,允许开发者将角色的动画与物理模拟结合起来,实现更真实的角色行为。BehaviourPuppet
是 PuppetMaster 的一个核心行为类,负责处理角色的物理碰撞、失去平衡、恢复平衡等逻辑。
主要功能
BehaviourPuppet
的主要功能包括:
- 角色状态的切换:控制角色在正常状态(Puppet)、失去平衡状态(Unpinned)和恢复状态(GetUp)之间的切换。
- 碰撞处理:当角色与物体发生碰撞时,根据碰撞的力度和角色的状态,决定是否让角色失去平衡。
- 自动恢复:当角色失去平衡后,自动触发恢复逻辑,让角色从地面站起来。
- 肌肉控制:控制角色的肌肉(Muscle)在不同状态下的物理行为,如碰撞抗性、恢复速度等。
- 事件触发:在角色失去平衡、恢复平衡等关键时刻触发事件,方便开发者进行自定义处理。
代码结构
代码的主要部分可以分为以下几个模块:
1. 状态管理
-
State
枚举定义了角色的三种状态:-
Puppet
:角色处于正常状态,受动画控制。 -
Unpinned
:角色失去平衡,完全由物理模拟控制。 -
GetUp
:角色正在从失去平衡状态恢复,逐渐回到正常状态。
-
2. 碰撞处理
-
OnCollision
和OnCollisionImpulse
事件用于处理角色肌肉与物体的碰撞。 -
collisionThreshold
定义了碰撞的最小力度阈值,低于该阈值的碰撞会被忽略。 -
collisionResistance
控制角色对碰撞的抗性,值越小,角色越容易被撞倒。
3. 自动恢复
-
canGetUp
控制角色是否可以在失去平衡后自动恢复。 -
getUpDelay
定义了角色在失去平衡后等待恢复的时间。 -
maxGetUpVelocity
控制角色在恢复时允许的最大速度。
4. 肌肉属性
-
MuscleProps
结构定义了每个肌肉的属性,如碰撞抗性、恢复速度、最小/最大映射权重等。 -
MusclePropsGroup
结构允许为不同的肌肉组设置不同的属性。
5. 事件系统
-
onLoseBalance
、onRegainBalance
等事件在角色失去平衡或恢复平衡时触发,开发者可以通过这些事件实现自定义逻辑。
核心方法
-
OnFixedUpdate
:在物理更新时调用,处理角色的碰撞、状态切换、肌肉恢复等逻辑。 -
OnLateUpdate
:在每帧的最后调用,处理角色的动画混合和状态切换。 -
SetState
:切换角色的状态,如从Puppet
切换到Unpinned
或GetUp
。 -
MoveTarget
和RotateTarget
:控制角色的目标位置和旋转,用于在角色失去平衡时调整其位置。
使用场景
- 角色物理动画:当角色受到外力(如被击中、摔倒)时,自动切换到物理模拟状态,实现真实的布娃娃效果。
- 自动恢复:角色在摔倒后,自动从地面站起来,恢复到正常状态。
-
自定义碰撞处理:通过
OnCollision
和OnCollisionImpulse
事件,开发者可以自定义角色与物体的碰撞效果。
示例用法
假设你有一个角色,当它被击中时,你希望它失去平衡并摔倒,然后自动站起来。你可以通过以下步骤实现:
- 将
BehaviourPuppet
脚本添加到角色的PuppetMaster
组件中。 - 配置
BehaviourPuppet
的参数,如collisionThreshold
、getUpDelay
等。 - 在代码中监听
onLoseBalance
和onRegainBalance
事件,实现自定义逻辑。
void Start() {
BehaviourPuppet puppet = GetComponent<BehaviourPuppet>();
puppet.onLoseBalance += OnLoseBalance;
puppet.onRegainBalance += OnRegainBalance;
}
void OnLoseBalance() {
Debug.Log("角色失去平衡!");
}
void OnRegainBalance() {
Debug.Log("角色恢复平衡!");
}
要实现角色被击飞的效果,你可以利用 BehaviourPuppet
的物理模拟功能,并通过代码施加外力来击飞角色。以下是实现击飞效果的步骤和代码示例:
如果需要实现击飞效果
1. 理解击飞的原理
击飞效果的实现主要依赖于以下两点:
- 施加外力:通过给角色的肌肉(Muscle)施加一个瞬间的力或冲量,使其飞出去。
- 调整物理参数:确保角色的物理属性(如质量、碰撞抗性等)能够支持击飞效果。
2. 实现击飞的步骤
(1) 确保角色处于物理模拟状态
- 角色在被击飞时,应该处于
Unpinned
状态(即完全由物理模拟控制)。 - 你可以通过调用
BehaviourPuppet
的SetState
方法将角色切换到Unpinned
状态。
(2) 施加外力
- 使用
Rigidbody.AddForce
或Rigidbody.AddExplosionForce
方法给角色的肌肉施加一个力。 - 你可以选择给角色的某个特定肌肉(如躯干或臀部)施加力,或者给所有肌肉施加力。
(3) 调整物理参数
- 确保角色的肌肉质量、碰撞抗性等参数适合击飞效果。
- 你可以在
BehaviourPuppet
的MuscleProps
中调整collisionResistance
和regainPinSpeed
等参数。
3. 代码实现
以下是一个实现击飞效果的示例代码:
using UnityEngine;
using RootMotion.Dynamics;
public class CharacterKnockback : MonoBehaviour
{
public PuppetMaster puppetMaster; // 角色的 PuppetMaster 组件
public BehaviourPuppet behaviourPuppet; // 角色的 BehaviourPuppet 组件
public float knockbackForce = 50f; // 击飞的力
public Vector3 knockbackDirection = Vector3.up + Vector3.forward; // 击飞的方向
void Start()
{
// 确保引用了 PuppetMaster 和 BehaviourPuppet
if (puppetMaster == null) puppetMaster = GetComponent<PuppetMaster>();
if (behaviourPuppet == null) behaviourPuppet = GetComponent<BehaviourPuppet>();
}
// 触发击飞效果
public void Knockback(Vector3 direction, float force)
{
// 将角色切换到 Unpinned 状态
behaviourPuppet.SetState(BehaviourPuppet.State.Unpinned);
// 给所有肌肉施加力
foreach (Muscle muscle in puppetMaster.muscles)
{
if (muscle.joint != null)
{
// 施加力
muscle.rigidbody.AddForce(direction.normalized * force, ForceMode.VelocityChange);
}
}
Debug.Log("角色被击飞!");
}
// 示例:按下空格键触发击飞
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Knockback(knockbackDirection, knockbackForce);
}
}
}
4. 参数调整
-
knockbackForce
:控制击飞的力度。值越大,角色飞得越远。 -
knockbackDirection
:控制击飞的方向。你可以根据需要调整方向向量。 -
collisionResistance
:在BehaviourPuppet
中调整碰撞抗性,确保角色容易被击飞。 -
regainPinSpeed
:调整角色恢复平衡的速度,确保角色在被击飞后不会立即恢复。
5. 优化击飞效果
- 击飞方向:可以根据攻击的方向动态计算击飞方向。例如,根据攻击者的位置和角色的位置计算方向向量。
- 局部击飞:如果只想击飞角色的某个部位(如上半身),可以只给特定的肌肉施加力。
- 击飞动画:在击飞时播放一个动画,增强视觉效果。
6. 动态计算击飞方向
如果你希望根据攻击者的位置动态计算击飞方向,可以使用以下代码:
public void KnockbackFromPosition(Vector3 attackerPosition, float force)
{
// 计算击飞方向(从攻击者指向角色)
Vector3 direction = (transform.position - attackerPosition).normalized;
direction.y = 0.5f; // 添加一些垂直分量,让角色飞起来
// 调用击飞方法
Knockback(direction, force);
}
7. 示例场景
假设你有一个敌人攻击角色的场景,你可以在敌人攻击时调用 KnockbackFromPosition
方法:
public class EnemyAttack : MonoBehaviour
{
public CharacterKnockback characterKnockback; // 角色的击飞脚本
public float attackForce = 30f; // 攻击的力度
void Attack()
{
// 假设敌人攻击时调用这个方法
Vector3 attackerPosition = transform.position; // 敌人的位置
characterKnockback.KnockbackFromPosition(attackerPosition, attackForce);
}
}
8. 注意事项
-
角色质量:确保角色的肌肉质量(
Rigidbody.mass
)适合击飞效果。质量过大会导致角色飞不起来。 - 碰撞检测:确保角色的碰撞器(Collider)和物理材质(Physic Material)设置正确,避免角色卡住或穿模。
- 性能优化:如果角色有很多肌肉,频繁施加力可能会影响性能。可以通过限制施加力的肌肉数量来优化。
通过以上方法,你可以实现一个逼真的击飞效果,并根据需要调整力度、方向和物理参数。