ue4 联机同步上限

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ue4 联机同步上限相关的知识,希望对你有一定的参考价值。

参考技术A 上线是16人。
1、网络同步蓝图要继承Character(开始的时候可以使用ThirdPersonCharacter测试),如果继承Pawn,需要自己写客户端向服务端同步的代码,否则会出现一个客户端移动不能同步到服务端和其他客户端
2、新建一个TestGameMode,SpawnActor的时候选择自定义的TestCharacter,截图里面测试的是第三人称角色。在WordSettings里面GameMode选择自定义的TestGameMode
3、在Play下拉列表里MultiPlayer options选择玩家最大数量,截图里面设置的是4。这时候直接点Play,会出现4个窗口,移动任何一个窗口里面的人物,其他三个窗口里面会跟着动
4、打包之后,新建四个快捷方式,在每个快捷方式的“目标”处添加参数(右键快捷方式-属性),例如作为server的要添加?listen(你要是问为什么要加问号?而不是减号-,可以在UE4源码中精准搜索"listen",包括引号,找到蛛丝马迹)
客户端添加127.0.0.1 -game,前一个表示server的IP(本机是127.0.0.1),后一个-game我也说不明白,反正要是不加就不对。client2和client3与client1一样配置。
5、接下来你可以按照任意顺序启动游戏

UE4 多线程

  UE4中使用多线程的有两种方式,一种方式就是使用FRunnable和FRunnableThread,另一种方式是Task Graph System。Task Graph System有时会占用游戏线程的时间,适合用在简单的计算或者需要开多个线程的情况。FRunnable适用于复杂运算。但是当创建太多线程后,有可能达到CPU的上限,这些线程就会为了抢占CPU的时间而彼此阻碍。UE4提供了FQueuedThreadPool来限制最大的线程数量。

  这种方式需要定义一个类继承自FRunnable,并且实现Init,Run,Stop,Exit。还需要一个FRunnableThread对象来创建和销毁线程。

  具体代码:

#pragma once

#include "CoreMinimal.h"
#include "Runnable.h"
#include "RunnableThread.h"

class TESTTARRAY_API AudioRecordThread : public FRunnable
{
public:
    AudioRecordThread(FString threadName);
    ~AudioRecordThread();

    //暂停线程
    void PauseThread();
    //继续线程
    void ContinueThread();
    //停止线程
    void StopThread();

    bool IsThreadPaused();
    bool IsThreadKilled();

private:
    FRunnableThread* Thread;
    FThreadSafeCounter StopTaskCounter;
    FCriticalSection m_mutex;
public:
    //override Frunnable Function
    virtual bool Init() override;
    virtual uint32 Run() override;
    virtual void Stop() override;
    virtual void Exit() override;

private:
    FThreadSafeBool m_Kill;
    FThreadSafeBool m_Pause;
};

 

#include "AudioRecordThread.h"
#include "Engine.h"


AudioRecordThread::AudioRecordThread(FString threadName) : StopTaskCounter(0)
{
    m_Kill = false;
    m_Pause = false;
    Thread = FRunnableThread::Create(this, *threadName, 0, TPri_BelowNormal);
}

AudioRecordThread::~AudioRecordThread()
{
    if (Thread)
    {
        delete Thread;
        Thread = nullptr;
    }
}

void AudioRecordThread::PauseThread()
{
    m_Pause = true;
}

void AudioRecordThread::ContinueThread()
{
    m_Pause = false;
}

void AudioRecordThread::StopThread()
{
    Stop();
    if (Thread)
    {
        Thread->WaitForCompletion();
    }
}
//需要注意的是在其他线程不能对UObject进行操作,不能使用TimerManager,不能使用DrawDebugLine。

bool AudioRecordThread::IsThreadPaused()
{
    return (bool)m_Pause;
}

bool AudioRecordThread::IsThreadKilled()
{
    return (bool)m_Kill;
}

bool AudioRecordThread::Init()
{
    GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadInit"));
    return true;
}

uint32 AudioRecordThread::Run()
{
    //使用该函数Sleep
    FPlatformProcess::Sleep(0.03);
    while (StopTaskCounter.GetValue() == 0 && !m_Kill)
    {
        if (m_Pause)
        {
            GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadPause"));
            if (m_Kill)
            {
                return 0;
            }
        }
        else
        {
            GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadLoop"));

            m_mutex.Lock();
            //需要同步处理的内容

            m_mutex.Unlock();

            FPlatformProcess::Sleep(0.01);
        }
    }
    return 0;
}

void AudioRecordThread::Stop()
{
    StopTaskCounter.Increment();
    m_Kill = true;
    m_Pause = false;
    GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadStop"));
}

void AudioRecordThread::Exit()
{
    GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Yellow, TEXT("AudioRecordThreadExit"));
}

 

  创建线程:   

m_AudioRecordThread = new AudioRecordThread("AudioRecordThread1");

 

,  构造函数中会用FRunnableThread::Create来创建线程。

  停止线程:

    if (m_AudioRecordThread)
    {
        m_AudioRecordThread->StopThread();
        delete m_AudioRecordThread;
        m_AudioRecordThread = nullptr;
    }

  在StopThread中会调用Stop来控制相关状态量完成线程循环,Thread->WaitForCompletion(),会使调用StopThread的线程即主线程悬挂,当线程循环完成后继续,继续后删除m_AudioRecordThread对象。需要注意的是这样停止线程会调用两次Stop函数,所以Stop中最好只执行控制线程循环停止的状态量。

  使用FPlatformProcess::Sleep(0.03)来等待,避免线程占用过多的资源。

  线程锁:

    使用m_mutex.Lock();和m_mutex.Unlock();包裹住需要同步的代码即可。

  需要注意的是在其他线程不能对UObject进行操作,不能使用TimerManager,不能使用DrawDebugLine。要在游戏线程执行代码可以这样用:

#include "Async.h"
...
AsyncTask(ENamedThreads::GameThread, []() {
     // code to execute on game thread here
 });

   另外我这里使用多线程是做录音相关功能,用到了AudioClient.h这个头文件,因为这个文件用到了windows的东西,所以用在UE4里会报错,所以需要把这个头文件放到CPP里包含,用到的struct使用前置声明。

  

以上是关于ue4 联机同步上限的主要内容,如果未能解决你的问题,请参考以下文章

UE4网络同步

npx 上限同步与 npx 上限复制

ue4网络同步笔记

UE4学习案例——多人网络中同步信息的方法

UE4学习案例——多人网络中同步信息的方法

UE4学习案例——多人网络中同步信息的方法