UE4入门序列04(UE中的网络使用,C++及蓝图举例)


使用Unreal引擎制作游戏或VR产品的时候,需要遵循Unreal引擎已经约定好的框架;
Unreal引擎非常复杂,本人是基于Application的应用层面来使用Unreal封装好的功能;
在制作一款联网端游的时候遇到了网络的问题,特此记录一下,个人的经验分享!


#1 Unreal 的框架简介
#2 Unreal 中的网络框架
#3 Unreal 属性同步,蓝图和C++
#4 Unreal 属性同步,Notify方式
#5 Unreal 中基于Actor同步
#6 Unreal 中使用RPC同步


#1 Unreal 的框架简介
Unreal中默认使用的框架在GameMode的设置中列举出来了
UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第1张图片

  1. GameModeOverride 游戏模式
    The GameModeBase defines the game being played. It governs the game rules, scoring, what actors
    are allowed to exist in this game type, and who may enter the game.
    It is only instanced on the server and will never exist on the client.
    A GameModeBase actor is instantiated when the level is initialized for gameplay in C++ UGameEngine::LoadMap().
    The class of this GameMode actor is determined by (in order) either the URL ?game=xxx,
    the GameMode Override value set in the World Settings, or the DefaultGameMode entry set in the game’s Project Settings.
    简介:每个关卡都可以设置一个游戏模式
    作用:设置游戏的规则
    网游:只存在于服务器中
    单机:每个关卡都有

  2. Default Pawn Class 默认的控制
    Pawn is the base class of all actors that can be possessed by players or AI.
    They are the physical representations of players and creatures in a level.
    简介:游戏默认的操作控制
    作用:封装好了游戏的各种控制
    网游:由服务器复制到各个客户端
    单机:自由控制切换

  3. HUD Class 游戏UI
    Base class of the heads-up display. This has a canvas and a debug canvas on which primitives can be drawn. It also contains a list of simple hit boxes that can be used for simple item click detection.
    A method of rendering debug text is also included.Provides some simple methods for rendering text, textures, rectangles and materials which can also be accessed from blueprints.
    简介:游戏战斗时的UI
    作用:可以绘制各种UI,血条、伤害数字等
    网游:和服务没有关系
    单机:自由控制显示

  4. Player Controller Class 玩家控制器
    PlayerControllers are used by human players to control Pawns.
    ControlRotation (accessed via GetControlRotation()), determines the aiming
    orientation of the controlled Pawn.
    In networked games, PlayerControllers exist on the server for every player-controlled pawn,
    and also on the controlling client’s machine. They do NOT exist on a client’s
    machine for pawns controlled by remote players elsewhere on the network.
    简介:游戏玩家的控制器
    作用:设置游戏的输入
    网游:服务器及客户端同步
    单机:每个关卡都有

  5. Game State Class 游戏状态
    GameState is a subclass of GameStateBase that behaves like a multiplayer match-based game.
    It is tied to functionality in GameMode.
    简介:游戏进行的状态
    作用:管理当前游戏的状态
    网游:服务器及客户端同步
    单机:每个关卡都有

  6. Player State Class 玩家状态
    A PlayerState is created for every player on a server (or in a standalone game).
    PlayerStates are replicated to all clients, and contain network game relevant information about the player, such as playername, score, etc.
    简介:游戏玩家的状态
    作用:管理当前玩家的状态
    网游:服务器及客户端同步
    单机:每个关卡都有

  7. Spectator Class 观战控制
    SpectatorPawns are simple pawns that can fly around the world, used by
    PlayerControllers when in the spectator state.
    简介:游戏玩家观战
    作用:控制当前玩家的观战
    网游:和服务没有关系
    单机:一般来说不需要

UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第2张图片
UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第3张图片


#2 Unreal 中的网络框架

Unreal中的服务器分为两种:监听服务器(局域网对战)和专用服务器(独立云服务器),两种服务器的游戏在制作的过程中差不多,打包的方式不一样;
制作测试的时候可以使用Unreal提供的便捷功能:
UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第4张图片
可以设置测试开启的玩家数量和网络模式

  1. Play Offline 单机运行
  2. Play As Listen Server 监听服务器
  3. Play As Client 专用服务器(默认会开启一个服务器)
    其中学习的时候使用监听服务器,可以区别服务器和客户端,使用HasAuthority()方法;
    项目使用专用服务器,开启的全是客户端。

#3 Unreal 属性同步,蓝图和C++
这种同步的属性无论是否有变化,数据一直在同步,比较耗网络资源

  • 蓝图同步设置,基于Actor中的属性(必须要到Actor层级的继承才有网络同步)
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第5张图片
  • 创建的属性需要设置为复制,表示这个变量是Server所有权
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第6张图片
  • 蓝图测试,Actor和关卡蓝图,Replicated的变量有特殊标志
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第7张图片
  • 关卡蓝图测试
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第8张图片
    以下是C++中使用属性复制功能:
  • 创建C++ Actor类
// HowTo_ReplicateProps.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "HowTo_ReplicateProps.generated.h"

UCLASS()
class TUTORIALSDEMO_API AHowTo_ReplicateProps : public AActor
{
     
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AHowTo_ReplicateProps();

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

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	//Step1. 标记为Replicated
	UPROPERTY(Replicated, VisibleAnywhere)
	int32 ReplicateValue = 100;

	//Step2. 通过这个方法设置为 DOREPLIFETIME(AHowTo_ReplicateProps, ReplicateValue);
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};

// HowTo_ReplicateProps.cpp

#include "HowTo_ReplicateProps.h"
#include "Net/UnrealNetwork.h"

// Sets default values
AHowTo_ReplicateProps::AHowTo_ReplicateProps()
{
     
	bReplicates = true;
 	// 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 AHowTo_ReplicateProps::BeginPlay()
{
     
	Super::BeginPlay();
	
	// 模拟服务器修改了值
	if (HasAuthority())
	{
     
		ReplicateValue = 500;
	}
}

// Called every frame
void AHowTo_ReplicateProps::Tick(float DeltaTime)
{
     
	Super::Tick(DeltaTime);

	if (HasAuthority())
	{
     
		GLog->Logf(TEXT("Server - %d"), ReplicateValue);
	}
	else
	{
     
		GLog->Logf(TEXT("Client - %d"), ReplicateValue);
	}
}

void AHowTo_ReplicateProps::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
     
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(AHowTo_ReplicateProps, ReplicateValue);
}


  • 直接将Actor拖拽到场景中或创建基于Actor的蓝图类进行测试,看日志输出

#4 Unreal 属性同步,Notify方式
这种方式同步的属性数据只有在变化之后才会接收到通知

  • 蓝图设置,基于Actor层级的设置同样开启网络复制功能
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第9张图片
  • 设置网络同步的方式为ReplicateNotify,会自动生成一个函数OnRep_xxx
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第10张图片
    在这里插入图片描述
  • 设置测试输出,在OnRep_xxx里面设置
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第11张图片
  • 模拟服务器修改了数值
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第12张图片
    以下是C++中使用属性复制通知功能:
  • 创建C++ Actor类
// HowTo_PropReplicateNotify.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "HowTo_PropReplicateNotify.generated.h"

UCLASS()
class TUTORIALSDEMO_API AHowTo_PropReplicateNotify : public AActor
{
     
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	AHowTo_PropReplicateNotify();
	void TimerInterval();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(VisibleAnywhere, ReplicatedUsing=OnRep_ReplicateValue)
	int32 ReplicateValue = 100;

	UFUNCTION()
	void OnRep_ReplicateValue();
};

// HowTo_PropReplicateNotify.cpp


#include "HowTo_PropReplicateNotify.h"
#include "Net/UnrealNetwork.h"


// Sets default values
AHowTo_PropReplicateNotify::AHowTo_PropReplicateNotify()
{
     
	bReplicates = true;
	// 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;
}

void AHowTo_PropReplicateNotify::TimerInterval()
{
     
	if (HasAuthority())
	{
     
		ReplicateValue = FMath::Rand();
	}
}

// Called when the game starts or when spawned
void AHowTo_PropReplicateNotify::BeginPlay()
{
     
	Super::BeginPlay();
	
	FTimerHandle TimerHandle;
	GetWorldTimerManager().SetTimer(TimerHandle, this, &AHowTo_PropReplicateNotify::TimerInterval, 1, true);
}

void AHowTo_PropReplicateNotify::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
     
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(AHowTo_PropReplicateNotify, ReplicateValue);
}

// Called every frame
void AHowTo_PropReplicateNotify::Tick(float DeltaTime)
{
     
	Super::Tick(DeltaTime);
}

void AHowTo_PropReplicateNotify::OnRep_ReplicateValue()
{
     
	if (HasAuthority())
	{
     
		GLog->Logf(TEXT("Server - %d"), ReplicateValue);
	}
	else
	{
     
		GLog->Logf(TEXT("Client - %d"), ReplicateValue);
	}
}



C++中的ReplciateNotify只在客户端之间进行传输数据,一般用于专用服务器对客户端进行数据的分发,不能用于局域网里面


#5 Unreal 中基于Actor同步

Actor的同步会复制服务器的生成的对象到客户端,如果服务器有而客户端没有,如果有碰撞,则会出现空气墙,Unreal的人物移动是在服务器计算的,如果服务器发现有碰撞,则无法通过

  • 蓝图设置,Actor基层才可以复制,到UObject就不可以了,Character默认开启复制
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第13张图片
  • 创建一个静态网格组件并且填充引擎自带的Cube
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第14张图片
  • 在关卡蓝图中进行测试
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第15张图片
    C++中的Actor复制只要开启了bReplicates = true;就可以了,Actor默认带网络复制功能。

#6 Unreal 中使用RPC同步
Unreal中可以使用RPC来进行通信

RPCs (Remote Procedure Calls) are functions that are called locally, but executed remotely on another machine (separate from the calling machine).
RPC functions can be very useful and allow either the client or the server to send messages to each other over a network connection.
The primary use case for these features are to do unreliable gameplay events that are transient or cosmetic in nature. These could include events that do things such as play sounds, spawn particles, or do other temporary effects that are not crucial to the Actor functioning. Previously these types of events would often be replicated via Actor properties.

RPC网络通信是Unreal中Online的主要通信网络,用于和服务器传输事件,比如播放声音,生成粒子或者游戏中的伤害数字等;用户可以手动来指定一个事件是否需要RPC到其他的客户端;
比如我这边播放了一个音效,Online的情况下需要把播放音效这个事件同步到其他的客户端,RPC就干这事;

  1. NetMulticast 网络多播,先通过服务器转发,本地也可以接收到
  2. Server 服务器事件,客户端需要服务器来进行转发
  3. Client 客户端事件,本地调用
  • 蓝图设置,通过事件来设置RPC选项
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第16张图片
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第17张图片
  • 测试蓝图
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第18张图片
  • 所有的客户端和服务器都可以同步到信息
    在这里插入图片描述
  • Client选项的测试,只会把数据同步到客户端
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第19张图片
  • Server测试,只会把数据同步到服务器
    UE4入门序列04(UE中的网络使用,C++及蓝图举例)_第20张图片
    以下是C++代码测试Unreal中RPC功能:
  • 创建C++的Actor类
// HowTo_RPC.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "HowTo_RPC.generated.h"

UCLASS()
class TUTORIALSDEMO_API AHowTo_RPC : public AActor
{
     
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AHowTo_RPC();

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

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UFUNCTION(Client, Reliable, WithValidation)
	void FunctionRPC(int32 InValue); // 定义需要RPC的方法,作用域是客户端
	void FunctionRPC_Implementation(int32 InValue); // 具体实现
	bool FunctionRPC_Validate(int32 InValue); // 验证有效
	void TimerInterval();
};

// HowTo_RPC.cpp


#include "HowTo_RPC.h"


// Sets default values
AHowTo_RPC::AHowTo_RPC()
{
     
 	// 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 AHowTo_RPC::BeginPlay()
{
     
	Super::BeginPlay();

	FTimerHandle TimerHandle;
	GetWorldTimerManager().SetTimer(TimerHandle, this, &AHowTo_RPC::TimerInterval, 5, true);
}

// Called every frame
void AHowTo_RPC::Tick(float DeltaTime)
{
     
	Super::Tick(DeltaTime);

}

void AHowTo_RPC::FunctionRPC_Implementation(int32 InValue)
{
     
	if(HasAuthority())
	{
     
		GLog->Logf(TEXT("Server - %d"), InValue);
	}
	else
	{
     
		GLog->Logf(TEXT("Client - %d"), InValue);
	}
}

bool AHowTo_RPC::FunctionRPC_Validate(int32 InValue)
{
     
	return true;
}

void AHowTo_RPC::TimerInterval()
{
     
	//!HasAuthority() = !GetWorld()->IsServer() = GetLocalRole() < ROLE_Authority
	// 这三个判定方法等同,判定服务器还是客户端
	if (!HasAuthority() || !GetWorld()->IsServer() || GetLocalRole() < ROLE_Authority)
	{
     
		FunctionRPC(500);
	}
}



你可能感兴趣的:(Unreal,Unreal)