UE5切换关卡函数OpenLevel,输入模式结构体,UI界面

1.输入模式结构体

  • FInputModeGameOnly:玩家只能与游戏世界交互,UI 不可交互。
  • FInputModeGameAndUI:玩家可以与游戏世界和 UI 同时交互。
  • FInputModeUIOnly:玩家只能与 UI 交互,无法与游戏世界进行互动。

        FInputModeGameOnly构造函数,默认设置输入模式为仅游戏输入模式,鼠标光标会隐藏,所有输入都会被传递到游戏。没有额外的设置函数,FInputModeGameOnly 只会设置输入为游戏模式,不需要额外的配置。

  FInputModeGameAndUI:构造函数,默认设置输入模式为游戏和 UI 模式。在此模式下,玩家可以同时与游戏和 UI 交互。

        FInputModeUIOnly:构造函数,默认设置输入模式为仅 UI 输入模式。在此模式下,玩家只能与 UI 进行交互,游戏输入会被禁用

        函数SetWidgetToFocus(TSharedPtr<SWidget> InWidgetToFocus) 参数是某个UI界面的指针,作用是将只关注这个InWidgetToFocus界面

        函数SetLockMouseToViewportBehavior(EMouseLockMode InMouseLockMode)设置鼠标模式,EMouseLockMode这个枚举中有注释

        这两个函数可能只会在FInputModeGameAndUI,和FInputModeUIOnly使用。

2.OpenLevel函数,切换关卡

#include "Kismet/GameplayStatics.h"

UGameplayStatics::OpenLevel(
    const UObject* WorldContextObject,    // 一般是UWorld指针,或者是APlayerController指针。UWorld指针可以通过GetWorld()函数获得 , APlayerController看你在哪个类中,查询具体的获得方式,一般是UWorld
    FName LevelName,            //切换到哪个关卡的名字
    bool bAbsolute = true,    //是否是绝对路径 ,一般是默认值,第二个参数给地图的名字即可
    FString Options = FString(TEXT(""))    // 不知到是干什么用的,
)

3.UI界面

        1.创建自UserWidget的子类,(UE中还有一个HUD也是于UI相关的类,我的理解是如果想显示角色的血量,子弹数等比较小的UI使用HUD,如果是游戏初始界面使用UserWidget)

        2.类中代码 , MenuSetup函数设置为蓝图可以调用的函数,使用AddToViewport显示UI界面,设置FInputModeUIOnly,我在点击按钮后设置了游戏模式函数是Button0Printf,在Initilize函数中绑定,Button0是按钮的名字,要和UE中的UI编辑器中的名字一样,SetGameModel函数中设置FInputModeGameOnly InputModeData;SetInputMode(InputModeData);两行。在是地图的关卡蓝图中调用menuSetup函数,中间的界面是create widget选择Class需要创建这个UI类的蓝图类,在切换关卡后如果角色不可以操作可以查看输入模式结构体有没有重新设置成FInputModeGameOnly或者FInputModeGameAndUI

class JUMP_API UStartUserWidget : public UUserWidget
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable)
	void MenuSetup();

protected:
	virtual bool Initialize() override;

public:
	UPROPERTY(meta = (BindWidget))
	UButton* Button0;

private:
	UFUNCTION()
	void Button0Printf();
};

void UStartUserWidget::MenuSetup()
{
	AddToViewport();
	SetVisibility(ESlateVisibility::Visible);/* 设置可见性 */
	bIsFocusable = true;/* 设置聚焦模式 */

	UWorld* World = GetWorld();
	if (World)
	{
		APlayerController* PlayerController = World->GetFirstPlayerController();
		if (PlayerController)
		{
			FInputModeUIOnly InputModeData;
			InputModeData.SetWidgetToFocus(TakeWidget());/* 设置只关注与小部件 */
			InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);/* 设置鼠标光标锁定 */
			PlayerController->SetInputMode(InputModeData);//设置模式集中于界面
			PlayerController->SetShowMouseCursor(true);/* 看到光标 */
		}
	}
}

bool UStartUserWidget::Initialize()
{
	if (!Super::Initialize())
	{
		return false;
	}

	if (Button0)
	{
		Button0->OnClicked.AddDynamic(this, &UStartUserWidget::Button0Printf);//绑定回调函数
	}

	return true;
}

void UStartUserWidget::Button0Printf()
{
	
	UWorld* World = GetWorld();
	if (World)
	{
		UGameplayStatics::OpenLevel(World, FName(TEXT("JumpMap")));
		AJumpCharacterController* PlayerController = Cast<AJumpCharacterController>(World->GetFirstPlayerController());
		if (PlayerController)
		{
			PlayerController->SetGameModel();
		}
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("World pointer is nullptr"));
	}
}

 4.关于UE中父类容器的概念

        父类容器的概念通常是指 一个类或对象包含并管理其他对象或数据的结构,比如UWorld中管理这很多AActor。使用GetOuter()函数可以返回当前类的父类容器,父类容器绝对不是当前类的父类。

5.如果Cast后编译器报错可以先将Cast后的类的头文件include

<think>嗯,用户现在的问题是,如何调用函数来获取FAntContactInfo,并且想要实现输入一个位置,然后获取该位置最近的敌人的位置。首先,我需要确认用户对FAntContactInfo的理解是否正确,以及他们是否在使用特定的游戏引擎,比如虚幻引擎(Unreal Engine),因为之前的对话中提到过这个结构体可能属于某个引擎。 用户之前的问题中,我介绍了FAntContactInfo可能属于游戏引擎的结构体,比如虚幻引擎,所以现在用户可能是在使用虚幻引擎的情况下进行开发。需要进一步确认这一点,但假设他们使用的是UE,因为例子中提到了TArray和AActor等UE特有的类。 接下来,用户想知道如何调用函数来获取FAntContactInfo。在UE中,常见的碰撞检测方法包括射线检测(Line Trace)、球形检测(Sphere Trace)、胶囊体检测等。这些函数通常属于UKismetSystemLibrary或者UWorld类的成员函数。例如,LineTraceSingleByChannel可以返回一个FHitResult结构体,其中包含碰撞信息。但用户提到的FAntContactInfo可能是一个特定的结构体,可能在某个插件或自定义模块中使用,或者可能是我之前提到的例子中的假设结构体。如果是这样,可能需要用户检查他们的引擎文档或代码库中的具体定义。 用户还希望输入一个位置,并获取最近的敌人的位置。这通常涉及到两个步骤:检测周围的所有敌人,然后计算距离最近的敌人。检测敌人可以通过碰撞检测或标签系统(如给敌人添加特定的标签,然后遍历所有带有该标签的Actor)。 可能用户对UE中的碰撞检测流程不太熟悉,需要分步骤说明。例如,首先使用OverlapMultiByChannel或SphereOverlapActors来检测周围一定范围内的所有Actor,然后过滤出敌人,再计算距离最近的敌人。 需要注意的是,用户可能混淆了FAntContactInfo和UE中的标准结构体如FHitResult。如果是这样,需要指出正确的结构体,并调整示例代码。 另外,用户可能需要一个具体的代码示例,展示如何实现这个功能。例如,使用SphereOverlapActors来获取所有附近的Actor,然后过滤出敌人,并找到最近的。 还需要考虑性能优化,比如使用距离平方而不是实际距离来减少计算量,以及如何处理多个敌人的情况。 总结来说,用户的需求可以分为两部分:正确调用碰撞检测函数获取碰撞信息,以及处理这些信息找到最近的敌人。需要根据用户使用的引擎或框架提供相应的函数名称和示例代码,同时解释每个步骤的作用和注意事项。</think>好的!**关键在于用引擎的碰撞检测函数扫描周围物体,并筛选出“敌人”类别**。以下是分步指南(以虚幻引擎为例,其他引擎逻辑类似): --- ### **步骤 1️⃣:选择检测形状** 根据需求选择检测区域形状: | 函数名(虚幻引擎示例) | 适用场景 | |------------------------------|---------------------| | `SphereOverlapActors` | 球形区域检测(范围固定) | | `BoxOverlapActors` | 立方体区域检测 | | `CapsuleOverlapActors` | 胶囊体区域检测(适合角色周围) | ```cpp // 示例:球形检测 TArray<AActor*> 覆盖到的所有物体; UKismetSystemLibrary::SphereOverlapActors( GetWorld(), // 当前关卡的世界对象 检测中心位置, // 用户输入的坐标(FVector类型) 检测半径, // 比如500单位 UEngineTypes::ConvertToObjectType(ECC_Pawn), // 检测Pawn类型物体(敌人通常是Pawn) nullptr, // 可选:过滤特定类(比如只检测 EnemyClass) TArray<AActor*>(), // 可选:忽略某些Actor(比如自己) 覆盖到的所有物体 // 输出:存储所有检测到的物体 ); ``` --- ### **步骤 2️⃣:过滤敌人并计算最近距离** ```cpp AActor* 最近的敌人 = nullptr; float 最近距离平方 = 最大值; // 比如 FLT_MAX for (AActor* 物体 : 覆盖到的所有物体) { // 判断是否为敌人(方法1:标签系统) if (物体->ActorHasTag("Enemy")) { // 方法2:直接类型判断(如果敌人有特定类,比如AEnemyCharacter) // if (物体->IsA(AEnemyCharacter::StaticClass())) // 计算距离平方(比实际距离计算更快) float 当前距离平方 = FVector::DistSquared(检测中心位置, 物体->GetActorLocation()); if (当前距离平方 < 最近距离平方) { 最近距离平方 = 当前距离平方; 最近的敌人 = 物体; } } } ``` --- ### **步骤 3️⃣:获取敌人位置** ```cpp if (最近的敌人 != nullptr) { FVector 敌人位置 = 最近的敌人->GetActorLocation(); // 使用位置(比如显示到UI或传给其他逻辑) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("最近敌人位置:X=%.2f, Y=%.2f, Z=%.2f"), 敌人位置.X, 敌人位置.Y, 敌人位置.Z)); } else { // 提示无敌人 } ``` --- ### **性能优化技巧 ⚡:** 1. **减少检测频率**:不要每帧检测,用定时器(如每0.2秒检测一次) 2. **分层检测**:先粗略筛选(大半径),再精细计算(小半径) 3. **空间划分**:用网格或四叉树管理敌人位置(适用于大量敌人场景) --- ### **可能遇到的问题 ❓:** - **检测不到敌人**:检查碰撞通道(Collision Channel)是否设置正确 - **误检测到非敌人**:用`FilterClass`参数或更精确的标签过滤 - **距离计算错误**:确保传入的位置是**世界坐标**(而非局部坐标) 需要我解释如何用其他形状(如射线或立方体)检测吗?或者如何自定义`FAntContactInfo`结构体? 😄
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值