언리얼 엔진/C++

언리얼엔진 C++ Foot IK

mane 2022. 1. 2. 01:45
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);
	}

Settings

728x90
반응형