[UE] 在虚幻中使用动画序列和分层骨骼混合简单实现角色看向

本文介绍了在Unreal Engine 4 (UE4) 中实现NPC角色头部转向的方法,包括使用骨骼分层混合动画和C++组件。通过计算角色与目标的夹角,将角度映射到动画序列位置,使角色能根据摄像机或玩家方向调整视线。同时,创建了一个C++组件,该组件负责计算角色与目标的相对方向,并调整动画播放位置,确保角色正确看向目标。当目标位于角色后方时,角色不会进行转向操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         做ue demo 骨骼动画作业时想到的功能,记录一下。实现效果如下:角色会看向摄像机方向。NPC会看向玩家方向。本期动画素材使用了ue商店中的AdvancedLocomotionSystemV。

 实现步骤

        首先实现了身体部分的正常的动画状态机:包括站立,走路,下蹲,跳跃等。

         因为角色头部转向是与身体运动分开的。所以需要再新建一个动画状态,专门用来处理头部转向,并使用骨骼分层混合将他们合并起来。在设置混合指定骨骼时,选中对应的骨骼(这里是“Head”),并设置对应的权重。

        观察素材中给的人物转头动画。实际上是一个additive的动画序列(30帧1秒),动画播放位置的不同(float数值0到1)对应了人物从左向右看。那么我们只需要计算出对应的目标与自身角色的夹角,并将夹角大小映射为浮点型[0,1]的数值范围即可。

                 如何使用浮点数量化两个夹角大小呢?容易想到使用使用两个单位向量的点乘判断大小。我们。因为等于1时对应动画位置是向右看,点乘两个重叠的单位向量大小也正好为1,所以我们只需取角色的局部右方向对目标方向进行点乘即可。

 

         新建一个C++组件,搭载到角色Actor上,负责计算自己与需要看向目标的方向夹角,lookAtPoint为需要播放的动画位置点(float数值0-1对应看向的左到右,0.5时代表玩家看向自己的正前方)

        使用transform.right(即actor->GetActorLocation())与角色看的方向的单位向量的点乘判断夹角来赋值给动画.如果点乘结果更接近1,说明角色更看向右边,对应的动画序列位置为1.点乘结果更接近-1,说明角色更看向左边,对应的动画序列位置为0.得到关系: 动画序列位置 = (点乘结果 + 1) * 0.5f

        同时,使用transform.forward,判断目标是否在角色前面.如果与方向向量点乘结果<0,说明目标在角色后面,则角色不需要进行看向操作(动画序列位置为0.5)

class SKEPROJECT_API UMyAnimCompoment : public UActorComponent
{
public:        
        UPROPERTY(EditAnywhere, BlueprintReadWrite)
                float lookAtPoint; //暴露给动画蓝图进行编辑
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Follow Target")
                AActor* target;    //需要看向的目标
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Follow Target")
                bool targetIsPlayer;
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Follow Target")
                bool targetIsCamera;

protected:
        virtual void BeginPlay() override;
        UActorComponent* cylinderCollider;
}
void UMyAnimCompoment::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
        Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

        if (target == nullptr)
        {
                GLog->Log("target Not Set");
                return;
        }

        //得到角色的胶囊碰撞体
        UPrimitiveComponent* collider = GetOwner()->FindComponentByClass<UPrimitiveComponent>(); //得到自己的胶囊碰撞体
        
        FVector selfpos = collider->GetComponentLocation(); //得到自己的位置
        FVector tarPos = target->GetActorLocation();        //得到目标的位置
        FVector direction = (tarPos - selfpos).GetSafeNormal(); //得到自己到目标方向的单位向量

        //使用局部右方向,使用点乘判断自己与目标方向的夹角,返回[-1,1]
        //这里的局部右方向要用GetForwardVector()??可能和原本组件自带的旋转有关
        float dir = FVector::DotProduct(-collider->GetForwardVector(), direction);
        //将点乘[-1,1]的结果映射回动画播放中需要用到的[0,1]的范围
        dir = (dir + 1) * 0.5f; 
        
        //判断目标是否在角色前,如果目标在角色后面就不需要角色看向了
        bool isForward = (FVector::DotProduct(collider->GetRightVector(), direction) > 0); 

        //得到动画混合结果(0为最左,0.5为中间,1为最右)
        lookAtPoint = isForward ? dir : 0.5f; 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值