ue4描边
效果圖:
?
第一步,創建C++ Basic Code
?
第二步,定義鍵盤和鼠標輸入的映射
?
第三步,修改 Rendering 中的 Custom Depth - Stencil Pass
?
第四步,找到GlobalPostProcessVolume [如果沒有的話自行拖放一個PostProcessVolume組件]?
?
將 unbound 勾選上
?
再修改 Blendables 為 PPI_OutlineColored
?
?
完整代碼如下:
MyPlayer.h
?
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "GameFramework/Character.h"
#include "MyPlayer.generated.h"
UCLASS()
class OUTLINECPLUSPLUS_API AMyPlayer : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMyPlayer();
void MoveForward(float val);
void MoveRight(float val);
void LookYaw(float val);
void LookPitch(float val);
void Use();
class AInteractableActor* FindFocusedActor();
void HandleHighlight();
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick( float DeltaSeconds ) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
UPROPERTY(EditDefaultsOnly)
float InteractionDistance = 300.f; // 交互的范圍
class AInteractableActor* FocusedActor;
// 用于 LineTraceSingleByChannel
FCollisionQueryParams TraceParams;
};
?
MyPlayer.cpp
?
?
?
// Fill out your copyright notice in the Description page of Project Settings.
#include "InteractableActor.h"
#include "MyPlayer.h"
// Sets default values
AMyPlayer::AMyPlayer()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
TraceParams = FCollisionQueryParams(FName(TEXT("TraceParams")), false, this);
TraceParams.bTraceComplex = false;
TraceParams.bTraceAsyncScene = false;
TraceParams.bReturnPhysicalMaterial = false;
}
// Called when the game starts or when spawned
void AMyPlayer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyPlayer::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
if (Controller && Controller->IsLocalController())
{
HandleHighlight();
}
}
// Called to bind functionality to input
void AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
InputComponent->BindAxis("MoveForward", this, &AMyPlayer::MoveForward);
InputComponent->BindAxis("MoveRight", this, &AMyPlayer::MoveRight);
InputComponent->BindAxis("LookYaw", this, &AMyPlayer::LookYaw);
InputComponent->BindAxis("LookPitch", this, &AMyPlayer::LookPitch);
InputComponent->BindAction("Use", IE_Pressed, this, &AMyPlayer::Use);
}
// 前后移動
void AMyPlayer::MoveForward(float val)
{
FRotator Rotation(0, GetActorRotation().Yaw, 0); // Roll, Yaw, Pitch
FVector forward = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
AddMovementInput(forward, val);
}
// 左右移動
void AMyPlayer::MoveRight(float val)
{
FRotator Rotation(0, GetActorRotation().Yaw, 0); // Roll, Yaw, Pitch
FVector right = FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);
AddMovementInput(right, val);
}
// 左右轉向
void AMyPlayer::LookYaw(float val)
{
AddControllerYawInput(val);
}
// 上下轉向
void AMyPlayer::LookPitch(float val)
{
// 注意方向相反
AddControllerPitchInput(val);
}
// 按 E 鍵與激活對象進行交互
void AMyPlayer::Use()
{
AInteractableActor* Interactable = FindFocusedActor();
if (Interactable)
{
// OnInteract_Implementation
Interactable->OnInteract(this);
}
}
AInteractableActor* AMyPlayer::FindFocusedActor()
{
if (!Controller)
{
return nullptr;
}
FVector Location;
FRotator Rotation;
FHitResult Hit(ForceInit);
Controller->GetPlayerViewPoint(Location, Rotation);
FVector Start = Location;
FVector End = Start + (Rotation.Vector() * InteractionDistance);
// 通過 “射線拾取” 選定對象
GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Camera, TraceParams);
if (Hit.bBlockingHit) // 擊中
{
// 獲取當前被擊中的對象的引用
AInteractableActor* MyCastActor = Cast<AInteractableActor>(Hit.GetActor());
if (MyCastActor)
{
return MyCastActor;
}
}
return nullptr;
}
void AMyPlayer::HandleHighlight()
{
AInteractableActor* NewHighlight = FindFocusedActor();
if (NewHighlight)
{
// 如果當前描邊和新激活的對象不是同一個
if (FocusedActor != NewHighlight)
{
if (FocusedActor)
{
// 當前描邊對象取消描邊
FocusedActor->OnEndFocus();
}
// 描邊新激活對象
NewHighlight->OnBeginFocus();
FocusedActor = NewHighlight;
}
}
else
{
if (FocusedActor)
{
// 取消描邊
FocusedActor->OnEndFocus();
FocusedActor = nullptr;
}
}
}
?
?
?
InteractableActor.h
?
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "GameFramework/Actor.h"
#include "OutlineCPlusPlus.h"
#include "InteractableActor.generated.h"
UCLASS()
class OUTLINECPLUSPLUS_API AInteractableActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AInteractableActor();
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick( float DeltaSeconds ) override;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Interaction)
void OnInteract(AActor* Caller) ;
virtual void OnInteract_Implementation(AActor* Caller);
void OnBeginFocus();
void OnEndFocus();
private:
UPROPERTY(EditDefaultsOnly)
uint32 bCanInteract : 1;
TArray<UMeshComponent*> Meshes;
UPROPERTY(EditDefaultsOnly)
EStencilColor Color = EStencilColor::SC_Green;
};
?
InteractableActor.cpp
?
?
?
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyPlayer.h"
#include "InteractableActor.h"
// Sets default values
AInteractableActor::AInteractableActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void AInteractableActor::BeginPlay()
{
Super::BeginPlay();
for (UActorComponent* Mesh : GetComponentsByClass(UMeshComponent::StaticClass()))
{
UMeshComponent* thisMesh = Cast<UMeshComponent>(Mesh);
if (thisMesh)
{
Meshes.Push(thisMesh);
}
}
}
// Called every frame
void AInteractableActor::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
}
void AInteractableActor::OnInteract_Implementation(AActor* Caller)
{
AMyPlayer* Player = Cast<AMyPlayer>(Caller);
if (Player)
{
GEngine->AddOnScreenDebugMessage(-1,
5.f,
FColor::Red,
FString::Printf(TEXT("Now deleting the interactable actor! "))
);
// 銷毀自己
Destroy();
}
}
void AInteractableActor::OnBeginFocus()
{
if (bCanInteract)
{
for (UMeshComponent* Mesh : Meshes)
{
Mesh->SetRenderCustomDepth(true);
Mesh->SetCustomDepthStencilValue((uint8)Color);
}
}
}
void AInteractableActor::OnEndFocus()
{
if (bCanInteract)
{
for (UMeshComponent* Mesh : Meshes)
{
Mesh->SetRenderCustomDepth(false);
}
}
}
?
?
?
顏色 的 Enum?
?
UENUM(BlueprintType)
enum class EStencilColor : uint8
{
SC_Green = 250 UMETA(DisplayName = "Green"),
SC_Blue = 251 UMETA(DisplayName = "Blue"),
SC_Red = 252 UMETA(DisplayName = "Red"),
SC_White = 253 UMETA(DisplayName = "White")
};
?
總結
- 上一篇: zabbix mysql 监控
- 下一篇: 美业多门店管理系统,智慧门店数字化方案