100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > [UE] 在虚幻中使用动画序列和分层骨骼混合简单实现角色看向

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

时间:2020-06-10 10:26:26

相关推荐

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

做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; }

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。