目录
目录
简单的菜单
创建新的c++类:
这里可能出现的报错:
如果创建了这个之后,发生大量报错,显示未知的符号
请在.bulid.cs文件中加入”UMG”这个模块。
除此之外我们还需要加几个模块进去:
接下来我们可以开始创建函数:
菜单设置:
首先是做一个设置菜单的函数:
代码:
头文件:
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "InPluginsMenu.generated.h"
/**
*
*/
UCLASS()
class MULTIPLAYERSESSIONPLUGIN_API UInPluginsMenu : public UUserWidget
{
GENERATED_BODY()
public:
//菜单设置
UFUNCTION(BlueprintCallable)
void MenuSet();
};
Cpp文件:
#include "InPluginsMenu.h"
void UInPluginsMenu::MenuSet()
{
//添加到视口
AddToViewport();
//设置可视
SetVisibility(ESlateVisibility::Visible);
//bIsFocusable设置为true是允许点击的时候受到焦点,是UserWidget里面定义的
bIsFocusable = true;
UWorld* world = GetWorld();
if (world)
{
APlayerController* playerControler = world->GetFirstPlayerController();
if (playerControler)
{
//FInputModeUIOnly 用于设置只允许ui响应用户输入的输入模式的数据结构
FInputModeUIOnly inputModeData;
//SetWidgetToFocus设置焦距
//TakeWidget()获取底层的slate部件,不存在则构造它
inputModeData.SetWidgetToFocus(TakeWidget());
//设置鼠标在视口的行为,这里是不锁定
inputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
//设置完毕输入模式的东西之后,在玩家控制器里面将设置好的输入模式设置到玩家控制器的输入模式
playerControler->SetInputMode(inputModeData);
//显示鼠标光标
playerControler->SetShowMouseCursor(true);
}
}
}
UI创建:
用户控件的创建我就不说了,懂的都懂,很简单。
记得将其父类换为自己做的c++类:
然后你可以在关卡蓝图中设置测试一下效果,当然也可以不测试,这并不影响。
C++类中创建按钮的指针:
记得在cpp文件里面添加头文件:
#include "Components/Button.h"
当然你想的话可以在下面两个函数里面添加打印,看看是否链接上了。
子系统创建
创建一个处理所有会话的子系统指针(在menu的private里面):
既然创建了这个类,在cpp中我们想要调用自然也是需要将这个类的头文件放在cpp文件里面:
#include "MultiPlayerSessionGISubsystem.h"
在这之后,我们在构造函数里面获取这个类的实例:
子系统就这样创建完毕了,接下来就是实现其他的函数了。
创建会话函数:
在此之前要添加的东西:
在这个点击函数里面加入创建函数,接下来我们要实现每一个不同的函数:
第一个是是create session的代码,因为太多就不展示图片了,直接上代码:
void UMultiPlayerSessionGISubsystem::CreateSession(int32 playerConnectNum, FString MatchType)
{
//判断会话系统是否有效
if (!mySessionInterface.IsValid())
{
return;
}
//有会话则获取现有的会话
auto ExistingSession = mySessionInterface->GetNamedSession(NAME_GameSession);
//如果现有的会话并不是空的
if (ExistingSession != nullptr)
{
//删除游戏会话
mySessionInterface->DestroySession(NAME_GameSession);
}
//在会话创建请求完成时触发委托CreateSessionCompleteDelegate,返回句柄到CreateSessionCompleteDelegateHandle,方便之后删除
CreateSessionCompleteDelegateHandle = mySessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
//
LastSessionSettings = MakeShareable(new FOnlineSessionSettings());
//判断现在的接口是不是空的,是则返回true,不是则返回false【此游戏将仅限局域网,外部玩家无法看到,是true还是false】
//直接在这里判断你是局域网还不是
LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName()=="NULL"?true:false;
//可用的连接数量是多少
LastSessionSettings->NumPublicConnections = playerConnectNum;
//是否允许加入线程
LastSessionSettings->bAllowJoinInProgress = true;
//是否允许通过玩家存在加入
LastSessionSettings->bAllowJoinViaPresence = true;
//该比赛是否在在线服务上面公开广告
LastSessionSettings->bShouldAdvertise = true;
//是否显示用户状态信息
LastSessionSettings->bUsesPresence = true;
//不同key和value的匹配,从现有会话设置中定义会话设置
LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
//获取本地的第一个玩家控制器
const ULocalPlayer* localPlayer = GetWorld()->GetFirstLocalPlayerFromController();
//*localPlayer->GetPreferredUniqueNetId() 首选唯一网格ID
//判断创建会话是否成功
if (!mySessionInterface->CreateSession(*localPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings))
{
//创建失败
//委托列表中删除委托,传入的是一个句柄(这个CreateSessionCompleteDelegateHandle在上面获取过)
mySessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
}
}
创建会话后前往大厅:
现在回到我们的菜单中:
我们实现了创建会话的函数,这样我们就可以在点击按钮之后创建一个会话:
接下来就是我们创建了一个会话之后应该要前往哪里:
但如果测试过就会发现,我们来到新的地图之后,我们仍然是处于一种无法行动的状态。
原因自然也很简单,因为我们的输入模式仍然是处于只允许ui输入的一个状态
对此我们需要做一个专门移除控件的函数
之后在哪里调用呢?
重载函数
对此我们需要重载一个函数:
然后:
变量添加
在菜单的头文件中,我们需要添加一些变量,比如说连接的人数之类的,这是为了之后更好的进行调整而准备的。
然后在菜单设置的函数中进行替换:
然后将创建会话的这里更改为自己的私有变量:
测试:
可能出现问题
打包测试发现在连接steam的情况下无法创建会话
对于这种情况,我们打开:
将这里改掉: