美文网首页
关于CameraComponent/SpringArmCompo

关于CameraComponent/SpringArmCompo

作者: 小小謨 | 来源:发表于2019-05-22 15:43 被阅读0次

    笔者最近正在从头开始搭建一个多人射击游戏,用于熟悉UE4 DS的方方面面,以及设计/性能优化等方面的课题,做些零碎的笔记。

    1.关于CameraComponent/SpringArmComponent的创建时机。

    很多时候,在Character构造函数里创建静态Compoennt变成了习以为常,尤其官方示例也是这么实现(笔者之前测试用工程https://github.com/tomlooman/EpicSurvivalGameSeries/tree/Section-4也是在构造函数中实现,如图)。

    image

    但是,静态组件会在Actor生成时自动创建,那么思考下,在所有的客户端包括服务端,对所有的Character都创建SpringArmComponent和CameraComponent是否合理,也即是说,如果有100个人同时在游戏(假设均在你的同步范围内),那么你本地创建了100个无用的SpringArmComponent和CameraComponent(真可怕),所以考虑两个组件的创建时机(也可以指所有组件都应该考虑他的创建时机)变得很有必要。

    然后思考,在其他非ROLE_AutonomousProxy客户端,肯定是不需要创建这两个组件,但是在服务器是否需要呢?我在上一篇CharacterMovement优化思路中简单提到一句 相关性剪裁,函数定义如下。

    bool AActor::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const

    其中变量 SrcLocation 是需要视点坐标的,如果服务器没有CameraComponent,SrcLocation是否准确?答案是没问题的,进一步查看SrcLocation的来源,如图,来自 FNetViewer,

    image

    查看 FNetViewer,发现 FNetViewer 为保存网络相关性检查使用的相关信息,其中 ViewLocation 即视点位置,进一步查询ViewLocation来源,如图所示,测试工程结果来自于CameraManager 中的CameraCachePrivate(当然,在其他情况下,也可能来自于其他数值,可自行查看FNetViewer::FNetViewer(UNetConnection* InConnection, float DeltaSeconds)构造函数)。

    image image

    继续查看CameraCachePrivate的来源,堆栈比较深,不一一截图,如图,最终来自ServerUpdateCamera_Implementation,这是客户端给服务器的同步请求,所以PlayerController会自动完成视点同步。

    image image

    罗里吧嗦扯了一大堆,就是一句话,服务器也不需要创建CameraComponent/SpringArmComponent(当然话不能说绝对,具体情况再分析)。笔者修改测试工程,如下所示,只在ROLE_AutonomousProxy创建CameraComponent/SpringArmComponent。

    
    void ASCharacter::BeginPlay()
    {
    Super::BeginPlay();
      if (Role == ROLE_AutonomousProxy)
      {
        CameraBoomComp = NewObject<USpringArmComponent>(this,"CameraBoom");
        CameraBoomComp->RegisterComponent();
        CameraBoomComp->SocketOffset = FVector(0, 35, 0);
        CameraBoomComp->TargetOffset = FVector(0, 0, 55);
        CameraBoomComp->bUsePawnControlRotation = true;
        CameraBoomComp->AttachToComponent(GetRootComponent(),FAttachmentTransformRules::KeepRelativeTransform);
        CameraComp = NewObject<UCameraComponent>(this, "Camera");
        CameraComp->RegisterComponent();
        CameraComp->AttachToComponent(CameraBoomComp,FAttachmentTransformRules::KeepRelativeTransform);
      }
    }
    

    2.关于Pawn::SetupPlayerInputComponent 和 APlayerController::SetupInputComponent

    其实如果使用UE4 DS,Pawn::SetupPlayerInputComponent 和 APlayerController::SetupInputComponent 都可以进行输入绑定,但是由于笔者之前用UE4和其他服务端做过MMO,遇到过小坑,特意在这里进行记录,加深理解。
    先看Pawn::SetupPlayerInputComponent 的调用来源,在使用UE4 DS时,APawn::PawnClientRestart()中为Pawn创建InputComponent,再进行输入响应绑定,APawn::PawnClientRestart()只有ROLE_AutonomousProxy客户端来回收到启动通知。但在使用其他服务端时,由于没有权限初始化,会给所以玩家对象调用Pawn::SetupPlayerInputComponent,产生输入冲突,导致玩家输入对其他本地模拟玩家的行为产生影响。
    再看APlayerController::SetupInputComponent,在Channel打开时进行输入绑定,此时可能玩家pawn并没有生成,如果在APlayerController::SetupInputComponent中绑定输入响应,需要对Pawn的状态进行判断。
    另外,笔者以为,在客户端,APlayerController是唯一的,玩家Pawn可能存在很多个,把和Pawn无关的输入(如界面等输入相应)写在APlayerController中,和Pawn有关的输入写在Pawn中,比较清晰,也可以无脑全放在APlayerController中,将响应逻辑(如果需要)写在Pawn中。

    相关文章

      网友评论

          本文标题:关于CameraComponent/SpringArmCompo

          本文链接:https://www.haomeiwen.com/subject/mqjuzqtx.html