알고 있자! (본수업에서 사용했던 것에서는 다른) - 나중에 중요하게 쓰임
Rotation이 외적식으로 3개축을 구하는 방식 공간을 만드는 것 (decal은 공간이 없는데.)
FRotator FVector4::ToOrientationRotator() const
{
FRotator R;
// Find yaw.
R.Yaw = FMath::Atan2(Y,X) * (180.f / PI);
// Find pitch.
R.Pitch = FMath::Atan2(Z,FMath::Sqrt(X*X+Y*Y)) * (180.f / PI);
// Find roll.
R.Roll = 0;
Arctan2 사용해 볼것이다.
2벡터를 알 수 있다면 내각을 구하는 것은 문제가 되지 않는다.
평면상의 직선을 하나 알고 있고, 수직이 되는 방향을 하나 알고 있는 것이다. (x 하고 y만 알고있는 상태)
내각 cos 세타를 구할려면. x하고 y 값이 있다면 그곳테 tan 가 있다. tan를 가지고 내각을 구하는 방법이 있는데, tan에 대비되는 값 arctan 이 있다. 아크탄젠트를 이용해서 코사인 각을 구할 수 있다.
atan : 파라미터 1개를 받는다
atan2 : 파라미터 2개를 받는다.(보통 이걸 많이 쓴다)
그러면 roll이라는 것은 어떻게 방향이 생성이 되나?
위에서 오른쪽으로 가니까 (y, z)으로 간다 - x 가 먼저 시작해야하니까 회전축이
Yaw.
정면에서 오른쪽 (y, x)
Pitch
(X,Z) 이건 주의 해야한다.
전방에서 위로 가는 식으로 생각하게 되지만., Pitch각은 회전되어있다. 기본적으로 (뒤집은 값을) 이상태 에서 한번더 뒤집어 준다. - Pitch (x, z) 로 들어간다.
다렉에서도 회전식이 항등식 에서 pitch 기준 잡기 나름이지만 , 저렇게 sin이 아래로 마이너스로 내려오게 된다. 일반적으로 그래서 pitch값 구할 때는 항상 뒤집어 줘야 한다.
//사용했던
float roll = UKismetMathLibarary::DeAtan2(Hit.ImpactNormal.Y, Hit.ImpactNormal.Z);
float pitch = - UKismetMathLibarary::DeAtan2(Hit.ImpactNormal.X, Hit.ImpactNormal.Z);
float yaw = UKismetMathLibarary::DeAtan2(Hit.ImpactNormal.Y, Hit.ImpactNormal.X);
CBullet.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CBullet.generated.h"
UCLASS()
class U2110_03_API ACBullet : public AActor
{
GENERATED_BODY()
private:
UPROPERTY(EditDefaultsOnly, Category = "Impact")
class UMaterialInstanceConstant* Decal;
UPROPERTY(EditDefaultsOnly, Category = "Impact")
class UParticleSystem* Particle;
private:
UPROPERTY(VisibleDefaultsOnly)
class UCapsuleComponent* Capsule;
UPROPERTY(VisibleDefaultsOnly)
class UStaticMeshComponent* Mesh;
UPROPERTY(VisibleDefaultsOnly)
class UProjectileMovementComponent* Projectile;
public:
ACBullet();
void Shoot(const FVector& InDirection);
protected:
virtual void BeginPlay() override;
private:
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
};
이런 충돌체에 대한 오류를 주의하자. 이펙트 텍스쳐 메터리얼등 위치가 이상하게잡히면. 이런식으로 나오지 않는 경우가 생긴다. 지금. 충돌체가. 중간에 있어서. 앞에 붙어야 나오는데 생기지 않았던 것 , 충돌이 시작된 지점이 아니라. 정확히 닿아야 한다.
CBullet.cpp
#include "CBullet.h"
#include "Global.h"
#include "Components/CapsuleComponent.h"
#include "Components/StaticMeshComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Materials/MaterialInstanceConstant.h"
#include "Particles/ParticleSystem.h"
#include "Components/DecalComponent.h"
ACBullet::ACBullet()
{
CHelpers::CreateComponent<UCapsuleComponent>(this, &Capsule, "Capsule");
CHelpers::CreateComponent<UStaticMeshComponent>(this, &Mesh, "Mesh", Capsule);
CHelpers::CreateActorComponent<UProjectileMovementComponent>(this, &Projectile, "Projectile");
Capsule->SetRelativeRotation(FRotator(90, 0, 0));
Capsule->SetCapsuleHalfHeight(50);
Capsule->SetCapsuleRadius(2);
Capsule->SetCollisionProfileName("BlockAllDynamic");
UStaticMesh* mesh;
CHelpers::GetAsset<UStaticMesh>(&mesh, "StaticMesh'/Game/Meshes/Sphere.Sphere'");
Mesh->SetStaticMesh(mesh);
Mesh->SetRelativeScale3D(FVector(1, 0.025f, 0.05f));
Mesh->SetRelativeRotation(FRotator(90, 0, 0));
Projectile->InitialSpeed = 2e+4f; //2 * 10 ^ 4
Projectile->MaxSpeed = 2e+4f; //2 * 10 ^ 4
Projectile->ProjectileGravityScale = 0;
CHelpers::GetAsset<UMaterialInstanceConstant>(&Decal, "MaterialInstanceConstant'/Game/Weapons/M_Decal_Inst.M_Decal_Inst'");
CHelpers::GetAsset<UParticleSystem>(&Particle, "ParticleSystem'/Game/Weapons/Particle/VFX_Impact_Default.VFX_Impact_Default'");
}
void ACBullet::BeginPlay()
{
Super::BeginPlay();
Capsule->OnComponentHit.AddDynamic(this, &ACBullet::OnHit);
}
void ACBullet::Shoot(const FVector& InDirection)
{
Projectile->Velocity = InDirection * Projectile->InitialSpeed;
}
void ACBullet::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
FRotator rotation = Hit.ImpactNormal.Rotation();
if (!!Decal)
{
UDecalComponent* decal = UGameplayStatics::SpawnDecalAtLocation(GetWorld(), Decal, FVector(5), Hit.ImpactPoint, rotation, 10);
decal->SetFadeScreenSize(0);
}
if (!!Particle)
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), Particle, Hit.ImpactPoint, rotation);
}
Destroy();
}