728x90
반응형
언리얼엔진 C++ Foot IK 입니다.
애님인스턴스에 작성 후 애님블루프린트에서 사진처럼 설정해주시면 됩니다.
DeltaTime(Tick)이 작동하는 함수에 넣어주시면 됩니다.
(단, 기본 마네킹 스켈레탈메시와 크기, 본이 같을 경우 정상 작동합니다.)
Unreal Engine C++ IK.
You can fill it out on AnimInstance and set it up like a picture in AnimBlueprint. And
You can put it in the function that Delta Time (Tick) works.
(However, if the size is the same as the basic mannequin skeleton mesh, it works normally.)
.h
void FootIK(float DeltaTime)
TTuple<bool, float> CapsuleDistance(FName SocketName,ACharacter* Char)
TTuple<bool,float,FVector> FootLineTrace(FName SocketName, ACharacter* Char)
-------------------
UPROPERTY()
class ACharacter* Character;
UPROPERTY()
TArray<AActor*> IgnoreActors;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "IK", meta = (AllowPrivateAccess = "true"))
float Displacement;
UPROPERTY(EditAnywhere,BlueprintReadOnly,Category = "IK", meta = (AllowPrivateAccess = "true"))
float IKInterpSpeed;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "IK", meta = (AllowPrivateAccess = "true"))
FRotator RRot;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "IK", meta = (AllowPrivateAccess = "true"))
FRotator LRot;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "IK", meta = (AllowPrivateAccess = "true"))
float RIK;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "IK", meta = (AllowPrivateAccess = "true"))
float LIK;
void FootIK(float DeltaTime)
.cpp
Character = Cast<ACharacter>(TryGetPawnOwner());
if(Character && !Character->GetCharacterMovement()->IsFalling()) // No Falling
{
IgnoreActors.Emplace(Char);
TTuple<bool,float> Foot_R = CapsuleDistance("ik_foot_r",Character);
TTuple<bool,float> Foot_L = CapsuleDistance("ik_foot_l",Character);
if(Foot_L.Get<0>() || Foot_R.Get<0>())
{
const float Selectfloat = UKismetMathLibrary::SelectFloat(Foot_L.Get<1>(),Foot_R.Get<1>(),Foot_L.Get<1>() >= Foot_R.Get<1>());
Displacement = FMath::FInterpTo(Displacement,(Selectfloat - 98.f) * -1.f,DeltaTime,IKInterpSpeed);
TTuple<bool, float, FVector> FootTrace_R = FootLineTrace("ik_foot_r",Character);
TTuple<bool, float, FVector> FootTrace_L = FootLineTrace("ik_foot_l",Character);
const float Distance_R = FootTrace_R.Get<1>();
const FVector FootRVector(FootTrace_R.Get<2>());
const FRotator MakeRRot(UKismetMathLibrary::DegAtan2(FootRVector.X,FootRVector.Z)*-1.f,0.f,UKismetMathLibrary::DegAtan2(FootRVector.Y,FootRVector.Z));
RRot = FMath::RInterpTo(RRot,MakeRRot,DeltaTime,IKInterpSpeed);
RIK = FMath::FInterpTo(RIK,(Distance_R - 110.f) / - 45.f,DeltaTime,IKInterpSpeed);
const float Distance_L = FootTrace_L.Get<1>();
const FVector FootLVector(FootTrace_L.Get<2>());
const FRotator MakeLRot(UKismetMathLibrary::DegAtan2(FootLVector.X,FootLVector.Z)*-1.f,0.f,UKismetMathLibrary::DegAtan2(FootLVector.Y,FootLVector.Z));
LRot = FMath::RInterpTo(LRot,MakeLRot,DeltaTime,IKInterpSpeed);
LIK = FMath::FInterpTo(LIK,(Distance_L - 110.f) / - 45.f,DeltaTime,IKInterpSpeed);
}
}
else
{
LRot = FMath::RInterpTo(LRot,FRotator::ZeroRotator,DeltaTime,IKInterpSpeed);
LIK = FMath::FInterpTo(LIK,0.f,DeltaTime,IKInterpSpeed);
RRot = FMath::RInterpTo(RRot,FRotator::ZeroRotator,DeltaTime,IKInterpSpeed);
RIK = FMath::FInterpTo(RIK,0.f,DeltaTime,IKInterpSpeed);
}
TTuple<bool, float> CapsuleDistance(FName SocketName,ACharacter* Char)
.cpp
const FVector WorldLocation{Char->GetMesh()->GetComponentLocation()};
const FVector BreakVector{WorldLocation+FVector(0.f,0.f,98.f)};
const FVector SocketLocation{Char->GetMesh()->GetSocketLocation(SocketName)};
const FVector Start{SocketLocation.X,SocketLocation.Y,BreakVector.Z};
const FVector End{Start - FVector(0.f,0.f,151.f)};
FHitResult HitResult;
UKismetSystemLibrary::LineTraceSingle(
this,
Start,
End,
ETraceTypeQuery::TraceTypeQuery1,
false,
IgnoreActors,
EDrawDebugTrace::ForOneFrame,
HitResult,
false);
const bool Result(HitResult.bBlockingHit);
return MakeTuple(Result,HitResult.Distance);
TTuple<bool,float,FVector> FootLineTrace(FName SocketName, ACharacter* Char)
.cpp
const FVector SocketLocation{Char->GetMesh()->GetSocketLocation(SocketName)};
const FVector RootLocation(Char->GetMesh()->GetSocketLocation("root"));
const FVector Start{SocketLocation.X,SocketLocation.Y,RootLocation.Z};
FHitResult HitResult;
UKismetSystemLibrary::LineTraceSingle(
this,
Start + FVector(0.f,0.f,105.f),
Start + FVector(0.f,0.f,-105.f),
ETraceTypeQuery::TraceTypeQuery1,
false,
IgnoreActors,
EDrawDebugTrace::None,
HitResult,
false);
const bool Result(HitResult.bBlockingHit);
if(HitResult.bBlockingHit)
{
return MakeTuple(Result,HitResult.Distance,HitResult.Normal);
}
else
{
return MakeTuple(Result,999.f,FVector::ZeroVector);
}
728x90
반응형
'언리얼 엔진 > C++' 카테고리의 다른 글
언리얼엔진 C++ 가비지컬렉션 (0) | 2022.01.03 |
---|---|
언리얼엔진 C++ 반환 값이 2개 이상일 경우에 사용하는 TTuple (0) | 2022.01.02 |
언리얼엔진 Enum (0) | 2021.12.29 |
언리얼엔진 구조체 c++ (0) | 2021.12.29 |
언리얼엔진 Assert (0) | 2021.12.29 |