c++蓝图实现摄像机靠近角色时,角色消失

766 阅读4分钟

c++蓝图实现摄像机靠近角色时,角色消失,防止遮挡视线

以虚幻4自带的ThirdPersonCharacter为例

1. 对材质处理

打开虚幻4自带的ThirdPersonCharacter所使用的材质蓝图

image.png

将输出结点的蓝图断开 添加以下结点

image.png

目的是将透明度开放出来,让其他组件可读取和写入

2.创建组件

蓝图方式

创建一个Actor Component 并创建两个函数和两个变量(因为所使用的材质有两个)

image.png

其中两个变量的类型是 Material Instance Dynamic

Fade_BeginPlay:

有一个输入,无输出
输入mesh类型为Primitive Component

image.png

image.png

为了截图清楚 凑到一起了 所以线条很乱
其中 Create Dynamic Material Instance 中的 parent 分别是所使用的两个材质名

Fade_EventTick:
两个输入 无输出

image.png

image.png

功能实现可以参考c++代码来理解 详见c++注释

c++方式

创建c++类的Actor Component

.h文件

/**************************************************************************

Copyright:聚集地

Author: 赣榆乌鸦Nevermore

Date:2021-07-27

Description:当摄像机与character距离过近时   character渐隐  以防遮挡实现

		*** 注意使用本函数需要的"Opacity"变量需要手动在材质蓝图中设置,详见M_Male_Body蓝图里中文注释的部分 ***

					是蓝图AC_FadeWhenCameraClose的c++化尝试
					尝试用c++编写该组件   目前宣告失败      -7.27-成功啦!!!!我们是冠军!!!!
**************************************************************************/


#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "AC_FadeWhenCameraIsClose.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class PROJECT_63_API UAC_FadeWhenCameraIsClose : public UActorComponent
{
	GENERATED_BODY()

public:	
	// Sets default values for this component's properties
	UAC_FadeWhenCameraIsClose();

protected:
	// Called when the game starts
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

	
	//动态材质
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category ="Nevermore|Material" )
	UMaterialInstanceDynamic* PlayerBodyMaterial;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Nevermore|Material")
	UMaterialInstanceDynamic* PlayerChestLogoMaterial;


	/*
	和公开属性类似,使用宏 UFUNCTION 即可。UFUNCTION() 负责将C++函数公开给反射系统。
	**BlueprintCallable ** 选项将其公开给蓝图虚拟机。
	每一个公开给蓝图的函数都需要一个与之关联的类别(Category),这样右键点击快捷菜单的功能才能正确生效。
	*/

	UFUNCTION(BlueprintCallable, Category = "Nevermore|BPFunc_Lib")
	virtual void Fade_BeginPlay(UPrimitiveComponent* mesh);

	UFUNCTION(BlueprintCallable, Category = "Nevermore|BPFunc_Lib")
	virtual void Fade_EventTick(FVector CameraLocation, FVector Location);
		
};

.cpp文件

/**************************************************************************

Copyright:聚集地

Author: 赣榆乌鸦Nevermore

Date:2021-07-27

Description:当摄像机与character距离过近时   character渐隐  以防遮挡实现

			*** 注意使用本函数需要的"Opacity"变量需要手动在材质蓝图中设置,详见M_Male_Body蓝图里中文注释的部分 ***

					是蓝图AC_FadeWhenCameraClose的c++化尝试
					尝试用c++编写该组件   目前宣告失败      -7.27-成功啦!!!!我们是冠军!!!!
**************************************************************************/

#include "AC_FadeWhenCameraIsClose.h"
#include "Components/PrimitiveComponent.h"
#include "Kismet/KismetMaterialLibrary.h"
#include "Kismet/KismetMathLibrary.h"
#include"Kismet/KismetStringLibrary.h"
#include"Kismet/KismetSystemLibrary.h"


// Sets default values for this component's properties
UAC_FadeWhenCameraIsClose::UAC_FadeWhenCameraIsClose()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
}


// Called when the game starts
void UAC_FadeWhenCameraIsClose::BeginPlay()
{
	Super::BeginPlay();

	// ...
	
}


// Called every frame
void UAC_FadeWhenCameraIsClose::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// ...
}


/**************************************************
@brief   : 创建两个动态材质,替换character本身使用的材质,这样就取得了对character材质的控制权
				可由蓝图的BeginPlay调用
@author  : Nevemore
@input   :
					mesh:character的网格体
@output  :
@time    : 2021-07-27

@AD: 可以用数组方式将他改得更有普遍性,不过现在用不到,我懒得优化了
**************************************************/
//目前宣告失败 -成功啦!!!!!我们是冠军!!!
void UAC_FadeWhenCameraIsClose::Fade_BeginPlay(UPrimitiveComponent* mesh) {

	
	//这里的动态材质创建方式与蓝图不同,更具有普遍性,是通过数字来获取材质
	UMaterialInstanceDynamic* t1 = mesh->CreateDynamicMaterialInstance(0);
	UMaterialInstanceDynamic* t2 = mesh->CreateDynamicMaterialInstance(1);

	PlayerBodyMaterial = t1;
	PlayerChestLogoMaterial = t2;

	if (IsValid(mesh)) {
		//将创建的动态材质重新赋予character
		mesh->SetMaterial(0, PlayerBodyMaterial);
		mesh->SetMaterial(1, PlayerChestLogoMaterial);
	}

}


/**************************************************
@brief   : 距离过近时character 隐身
@author  : Nevemore
@input   :
					CameraLocation:摄像机的位置
					Location:character的位置
@output  :
@time    : 2021-07-27

@AD: 
**************************************************/
void UAC_FadeWhenCameraIsClose::Fade_EventTick(FVector CameraLocation, FVector Location){
	//计算出两者之间的差值
	float t1= UKismetMathLibrary::Vector_Distance(CameraLocation, Location);
	//返回从一个范围映射到另一个范围的值
	//以此代码为例
	//当t1的值在50-90之间时,就会返回一个0.3-1的相应的值
	float t2= UKismetMathLibrary::MapRangeClamped(t1, 50.000000, 90.000000, 0.300000, 1.000000);
	
	//将t2转成string打印到屏幕
	FString t3= UKismetStringLibrary::Conv_FloatToString(t2);
	UKismetSystemLibrary::PrintString(this, t3, true, true, FLinearColor(1.000000, 0.244451, 0.435678, 1.000000), 0.000000);

	//当动态材质存在时,改变材质蓝图中名为 "Opacity"的变量值
	//注意 "Opacity"变量需要手动在材质蓝图中设置,详见M_Male_Body蓝图里中文注释的部分
	if (IsValid(PlayerBodyMaterial) && IsValid(PlayerChestLogoMaterial)) {
		PlayerBodyMaterial->UMaterialInstanceDynamic::SetScalarParameterValue(FName(TEXT("Opacity")), t2);
		PlayerChestLogoMaterial->UMaterialInstanceDynamic::SetScalarParameterValue(FName(TEXT("Opacity")), t2);
	}
}

3.在蓝图中调用

把要用的component装上

image.png

然后调用

image.png

image.png

其中mesh和Follow Camera 直接从components里拖进去就可以

4. 演出效果

远距离

image.png 距离过近

image.png