UE5 通过接口实现角色描边效果

发布时间:2024年01月11日

接口不能够被实例化,不能够在内部书写函数的逻辑和设置属性,只能够被继承使用。它能够让不同的类实现有相同的函数,继承接口的类必须实现接口的函数。
并且,我们可以在不同的类里面的函数实现也不同,比如A类描边是红色,B类的描边是绿色的,描边的调用都使用一个函数调用。

创建接口类

在这里插入图片描述
右键添加c++类,在常见类中找到Unreal接口,创建一个Enemy的接口类

// 版权归暮志未晚所有。

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "EnemyInterface.generated.h"

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UEnemyInterface : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class AURA_API IEnemyInterface
{
	GENERATED_BODY()

	// 向此类添加接口函数(虚函数),继承此接口的类都将需要继承并实现这些函数。
public:
	virtual void HighlightActor() = 0; //高亮
	virtual void UnHighlightActor() = 0; //取消高亮
};

在接口类EnemyInterface.h中,我们增加了两个虚函数,继承此接口的类需要实现高亮函数和取消高亮函数

类实现接口

在这里插入图片描述
接着让敌人类继承接口
在这里插入图片描述
如果你只继承,不实现相关函数,会发现编译时提示报错。

// 版权归暮志未晚所有。

#pragma once

#include "CoreMinimal.h"
#include "Character/CharacterBase.h"
#include "Interaction/EnemyInterface.h"
#include "Enemy.generated.h"

/**
 * 
 */
UCLASS()
class AURA_API AEnemy : public ACharacterBase, public IEnemyInterface
{
	GENERATED_BODY()
	
public:
	virtual void HighlightActor() override; //高亮
	virtual void UnHighlightActor() override; //取消高亮

	UPROPERTY(BlueprintReadOnly) //蓝图可读
	bool bHighlighted = false; //是否高亮
};

我们需要在类里面继承函数,并在cpp里面定义相关逻辑。这里先定义了一个变量,用来获取当前角色是否需要高亮

// 版权归暮志未晚所有。


#include "Character/Enemy.h"

void AEnemy::HighlightActor()
{
	bHighlighted = true;
}

void AEnemy::UnHighlightActor()
{
	bHighlighted = false;
}

在cpp中,高亮将此值设置为true,取消高亮设置为false。

通过鼠标拾取设置敌人是否高亮

设置敌人高亮,我们可以通过在帧更新里面,通过获取鼠标拾取到的对象,对对象进行判断是否设置高亮。
在这里插入图片描述
在playercontroller中,我们覆盖帧更新回调,鼠标位置追踪拾取函数,以及两个变量去记录当前鼠标拾取到的内容。

//帧更新
void APlayerControllerBase::PlayerTick(float DeltaTime)
{
	Super::PlayerTick(DeltaTime);

	CursorTrace();
}

帧更新里面,只需要增加对鼠标帧更新的调用。

//鼠标位置追踪
void APlayerControllerBase::CursorTrace()
{
	FHitResult CursorHit;
	GetHitResultUnderCursor(ECC_Visibility, false, CursorHit); //获取可视的鼠标命中结果
	if(!CursorHit.bBlockingHit) return; //如果未命中直接返回

	LastActor = ThisActor;
	ThisActor = Cast<IEnemyInterface>(CursorHit.GetActor());

	/**
	 * 射线拾取后,会出现的几种情况
	 * 1. LastActor is null   ThisActor is null 不需要任何操作
	 * 2. LastActor is null   ThisActor is valid 高亮ThisActor
	 * 3. LastActor is valid   ThisActor is null 取消高亮LastActor
	 * 4. LastActor is valid   ThisActor is valid LastActor != ThisActor 取消高亮LastActor 高亮ThisActor
	 * 5. LastActor is valid   ThisActor is valid LastActor == ThisActor 不需要任何操作
	 */

	if(LastActor == nullptr)
	{
		if(ThisActor != nullptr)
		{
			//case 2
			ThisActor->HighlightActor();
		} // else case 1
	}
	else
	{
		if(ThisActor == nullptr)
		{
			//case 3
			LastActor->UnHighlightActor();
		}
		else
		{
			if(LastActor != ThisActor)
			{
				//case 4
				LastActor->UnHighlightActor();
				ThisActor->HighlightActor();
			} //else case 5
		}
	}
	
}

而鼠标位置追踪拾取函数,首先就是先通过函数获取可视的内容,对拾取的内容判断是否继承至IEnemyInterface,然后根据情况进行高亮和非高亮的设置。

在蓝图中根据变量设置可视效果

首先,我需要先在debug模式下测试设置高亮是否有效果,有了变量bHighlighted后,我们可以在敌人的蓝图中获取它的变量,如果为true,我们将在敌人身上添加一个球代表它需要高亮。
在这里插入图片描述
在敌人的事件图表中,帧更新中,增加对Hightlighted的判断,如果为true,则在敌人位置创建一个球
在这里插入图片描述
为了能够被鼠标拾取到,我们需要将敌人模型的检测相应可视设置为阻挡。
在这里插入图片描述
运行点击~ 输入show Collision将会显示所有的碰撞体,再输入一次,将隐藏掉所有没必要的碰撞体显示。
在这里插入图片描述
接下来放置几个敌人进行测试,会发现鼠标悬浮在谁身上,就会生成一个球。

使用后处理实现对模型的描边

在ue里面实现描边有多种方法,大家经常使用的方法就是使用后处理描边。
在这里插入图片描述
首先在场景内添加一个后处理体积
在这里插入图片描述
将后处理体积影响范围设置为无限
在这里插入图片描述
然后在后期处理材质这里,将材质添加进来
在这里插入图片描述
后处理材质逻辑大概如此,这里不再展开将了,原理就是通过卷积的方式,采样进行比对,分析出描边区域,然后根据设置的颜色显示。需要用到自定义深度功能。
在这里插入图片描述
在项目设置里面开启基于模版的自定义深度
在这里插入图片描述

在材质中,如果自定义深度为250,那么它的模型周围会出现描边效果,那么,最后一步,我们将需要描边的模型的自定义深度开启,并设置为250,则实现当前效果。
在这里插入图片描述
在前面,我们在敌人的基类里面实现了设置高亮以及取消高亮,只要我们在代码中实现,对自定义深度通道修改以及自定义深度模板值的修改,就可以实现当前的高亮效果。

// 版权归暮志未晚所有。


#include "Character\EnemyBase.h"

#include "Aura/Aura.h"

AEnemyBase::AEnemyBase()
{
	GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block); //设置可视为阻挡
}

void AEnemyBase::HighlightActor()
{
	GetMesh()->SetRenderCustomDepth(true);
	GetMesh()->SetCustomDepthStencilValue(CUSTOM_DEPTH_RED);
	Weapon->SetRenderCustomDepth(true);
	Weapon->SetCustomDepthStencilValue(CUSTOM_DEPTH_RED);
}

void AEnemyBase::UnHighlightActor()
{
	GetMesh()->SetRenderCustomDepth(false);
	Weapon->SetRenderCustomDepth(false);
}


设置角色的模型和武器的模型的自定义深度和自定义深度模版值,为了方便以后迭代修改,红色的值直接定义在了CUSTOM_DEPTH_RED宏中。
并且,为了爆炸角色模型能够被鼠标拾取到,我们直接在构造时直接修改了设置可见性的拾取。

文章来源:https://blog.csdn.net/qq_30100043/article/details/135519324
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。