赞
踩
效果图:
第一步,创建C++ Basic Code
第二步,定义键盘和鼠标输入的映射
第三步,修改 Rendering 中的 Custom Depth - Stencil Pass
第四步,找到GlobalPostProcessVolume [如果没有的话自行拖放一个PostProcessVolume组件]
将 unbound 勾选上
再修改 Blendables 为 PPI_OutlineColored
完整代码如下:
- // 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;
- };
- // 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;
- }
- }
- }
- // 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;
-
- };
- // 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);
- }
- }
- }
-
- 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")
- };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。