UE中的TEXT()
UE中使用TEXT()包含字串後,將字串轉換為寬字元,其將被處理為支援Unicode和跨平臺相容性,而普通型別的字串為一個窄字元型別,可能在跨平臺出現問題。
最主要的問題是在FString的建構函式中是接受TCHAR的
所以對於FString FName FTEXT的構造需要傳入TEXT("xxxx")。
TEXT()是一個宏定義
透過比較平臺的TCHAR型別,來決定將字串x轉換為u或者L型別
eg
主要是當我在使用UKismetSystemLibrary::K2_SetTimer(this, TEXT("AutoClimb"), 0.01f, true, 0.0f, 0.0f)時,該函式是藍圖中的該節點
最開始沒有使用TEXT來包含函式名,其會報錯
LogBlueprintUserMessages: Warning: SetTimer passed a bad function (AutoClimb) or object (None)
K2_SetTimer中函式名字是FName的型別引數,如果只傳入"AutoClimb",應該是"AutoClimb"由於編碼問題無法被正確處理為反射系統中儲存的函式名,所以導致在使用SetTimer被呼叫時,導致UE的反射系統沒有辦法找到函式而報錯
這裡只是猜測,待補充
當然K2_SetTimer可以利用GetWorldTimerManager().SetTimer代替
IK
使用UE中的FABRIK和Two Bone IK 匹配腳的位置
IK:逆向運動學
FK:正向運動學
是兩種用來確定骨骼位置的方式,如果將整個骨骼簡化為RootBone-->JointBone-->EndBone。
那麼FK就是透過調整RB,JB,EB的位置來最終實現EB在正確位置
而IK就是直接操作EB,透過EB的位置和其與RB,JB的幾何約束反向求解RB,JB的位置
Two Bone IK
在UE中TBIK發生在ComponentSpace所以當在動畫藍圖中使用TBIK時,UE會自動將骨骼從LocalSpace轉換為ComponentSpace。
而為了能夠透過EndBone求解出RB和JB,需要一個平面來放置JB,即JB的移動會在這個平面內。所以在TwoBoneIK的節點上要求我們傳入一個JointTarget,一般來說該Target可以是一個經驗定值即可
- 透過射線檢測求得腳部位置的偏移
可以透過新增骨骼插槽來求解骨骼位置,然後從腳部位置EndBone發出射線來求解與地面的接觸點。
FVector SocketLocation = CharacterRef->GetMesh()->GetSocketLocation(SocketName);
FVector ActorLocation = CharacterRef->GetActorLocation();
float FootTraceOffset;
FVector Start = { SocketLocation.X,SocketLocation.Y,ActorLocation.Z };
FVector End = { SocketLocation.X,SocketLocation.Y,SocketLocation.Z - CapsuleComponent->GetUnscaledCapsuleHalfHeight() };
FHitResult Hit;
ETraceTypeQuery Visible = UEngineTypes::ConvertToTraceType(ECC_Visibility);
bool IsHit = UKismetSystemLibrary::LineTraceSingle(
GetWorld(),
Start,
End,
Visible,
false,
TArray<AActor*>{},
EDrawDebugTrace::None,
Hit,
true
);
當返回為true,說明檢測到了地面,現在就需要求解腳部位置的偏移量。這是為了對應在TwoBoneIK中選擇Effector的LocationSpace選擇Bone Space。
注意到Mesh的節點即計算其高度的節點實際上是在兩腳之間
所以當計算腳部偏移時,應當使用當前檢測到位置減去Mesh節點的位置才是正確的偏移量
而由於膠囊體的存在導致整體的骨骼由於碰撞無法下沉,所以還需要使用到
該節點將設定從pelvis骨骼下沉一段距離HipOffset,而由於下沉了HipOffset所以需要在腳部偏移量的位置進行補償
float Z = (HitLocation - CharacterRef->GetMesh()->GetComponentLocation()).Z;
//5.0f為測試引數,需根據實際情況進行調整
FootTraceOffset = Z - IKHipOffset + 5.0f;
到這裡,腳部的偏移已經求解完成,使用它至於在將其賦值給TwoBoneIK節點中的Effector引數的X值即可,因為在插槽的座標系X軸是豎直方向的。並且右腳的X還是反向的
//Animation Blueprint
LeftFootLocationIK.X = XClimbComp->GetIKLeftFootOffset();
RightFootLocationIK.X = XClimbComp->GetIKRightFootOffset() * (-1.0f);
- HipOffset
前面說到為了使得骨骼下層,需要求解HipOffset,HipOffset其實就是左右腳的差值,這是由於如果補償HipOffset,由於膠囊體碰撞,骨骼將被限制在高處的臺階
其次為了避免出現左右腳Hit位置高度差過大,而導致的骨骼拉扯問題,還需要對HipOffset的大小進行限制
當過大就不再進行HipOffset,說明再走一步可能就掉下去了
float target = abs((RightFootLocation - LeftFootLocation).Z);
if (target != 0.0f)target = UKismetMathLibrary::SelectFloat((-1.0f * target), 0.0f, (target < CapsuleComponent->GetUnscaledCapsuleHalfHeight() / 2.0f));
IKHipOffset = UKismetMathLibrary::FInterpTo(
IKHipOffset,
target,
UGameplayStatics::GetWorldDeltaSeconds(this),
20.0f
);
那麼整個在動畫藍圖中的節點使用情況就如下所示