1、cameracomponent的修改

void UCameraComponent::GetCameraView(float DeltaTime, FMinimalViewInfo& DesiredView)
{//xr的不管if (GEngine && GEngine->XRSystem.IsValid() && GetWorld() && GetWorld()->WorldType != EWorldType::Editor ){IXRTrackingSystem* XRSystem = GEngine->XRSystem.Get();auto XRCamera = XRSystem->GetXRCamera();if (XRCamera.IsValid()){if (XRSystem->IsHeadTrackingAllowedForWorld(*GetWorld())){const FTransform ParentWorld = CalcNewComponentToWorld(FTransform());XRCamera->SetupLateUpdate(ParentWorld, this, bLockToHmd == 0);if (bLockToHmd){FQuat Orientation;FVector Position;if (XRCamera->UpdatePlayerCamera(Orientation, Position)){SetRelativeTransform(FTransform(Orientation, Position));}else{ResetRelativeTransform();}}XRCamera->OverrideFOV(this->FieldOfView);}}}//是否用pawn的controllrotation 默认是trueif (bUsePawnControlRotation){const APawn* OwningPawn = Cast<APawn>(GetOwner());const AController* OwningController = OwningPawn ? OwningPawn->GetController() : nullptr;if (OwningController && OwningController->IsLocalPlayerController()){//GetViewRotation()函数里面其实获得是controller的rotationconst FRotator PawnViewRotation = OwningPawn->GetViewRotation();if (!PawnViewRotation.Equals(GetComponentRotation())){SetWorldRotation(PawnViewRotation);}}}//还有offset功能默认是开启的if (bUseAdditiveOffset){FTransform OffsetCamToBaseCam = AdditiveOffset;FTransform BaseCamToWorld = GetComponentToWorld();FTransform OffsetCamToWorld = OffsetCamToBaseCam * BaseCamToWorld;DesiredView.Location = OffsetCamToWorld.GetLocation();DesiredView.Rotation = OffsetCamToWorld.Rotator();}else{DesiredView.Location = GetComponentLocation();DesiredView.Rotation = GetComponentRotation();}DesiredView.FOV = bUseAdditiveOffset ? (FieldOfView + AdditiveFOVOffset) : FieldOfView;DesiredView.AspectRatio = AspectRatio;DesiredView.bConstrainAspectRatio = bConstrainAspectRatio;DesiredView.bUseFieldOfViewForLOD = bUseFieldOfViewForLOD;DesiredView.ProjectionMode = ProjectionMode;DesiredView.OrthoWidth = OrthoWidth;DesiredView.OrthoNearClipPlane = OrthoNearClipPlane;DesiredView.OrthoFarClipPlane = OrthoFarClipPlane;// See if the CameraActor wants to override the PostProcess settings used.DesiredView.PostProcessBlendWeight = PostProcessBlendWeight;if (PostProcessBlendWeight > 0.0f){DesiredView.PostProcessSettings = PostProcessSettings;}// If this camera component has a motion vector simumlation transform, use that for the current view's previous transformDesiredView.PreviousViewTransform = FMotionVectorSimulation::Get().GetPreviousTransform(this);
}
//并没有调用super
void ULyraCameraComponent::GetCameraView(float DeltaTime, FMinimalViewInfo& DesiredView)
{check(CameraModeStack);//如果DetermineCameraModeDelegate有bind的cameramode就添加到CameraModeStack中UpdateCameraModes();FLyraCameraModeView CameraModeView;//CameraModeStack开始更新CameraModeStack->EvaluateStack(DeltaTime, CameraModeView);//在父类中component的rotation被动的跟随controller的rotation//但是在lyra中是多个cameramode共同blend后的ControlRotation再主动的影响pc的rotation//这样做有啥好处呢?// Keep player controller in sync with the latest view.if (APawn* TargetPawn = Cast<APawn>(GetTargetActor())){if (APlayerController* PC = TargetPawn->GetController<APlayerController>()){//把CameraModeView的ControlRotation强制更新pc的rotationPC->SetControlRotation(CameraModeView.ControlRotation);}}// Apply any offset that was added to the field of view.CameraModeView.FieldOfView += FieldOfViewOffset;FieldOfViewOffset = 0.0f;// Keep camera component in sync with the latest view.SetWorldLocationAndRotation(CameraModeView.Location, CameraModeView.Rotation);FieldOfView = CameraModeView.FieldOfView;// Fill in desired view.DesiredView.Location = CameraModeView.Location;DesiredView.Rotation = CameraModeView.Rotation;DesiredView.FOV = CameraModeView.FieldOfView;DesiredView.OrthoWidth = OrthoWidth;DesiredView.OrthoNearClipPlane = OrthoNearClipPlane;DesiredView.OrthoFarClipPlane = OrthoFarClipPlane;DesiredView.AspectRatio = AspectRatio;DesiredView.bConstrainAspectRatio = bConstrainAspectRatio;DesiredView.bUseFieldOfViewForLOD = bUseFieldOfViewForLOD;DesiredView.ProjectionMode = ProjectionMode;// See if the CameraActor wants to override the PostProcess settings used.DesiredView.PostProcessBlendWeight = PostProcessBlendWeight;if (PostProcessBlendWeight > 0.0f){DesiredView.PostProcessSettings = PostProcessSettings;}// 并没有cameracomponent的offset功能
}

流程方面:

每一帧都会调用ULyraCameraComponent::GetCameraView()

UpdateCameraModes()中

void ULyraCameraComponent::UpdateCameraModes()
{check(CameraModeStack);if (CameraModeStack->IsStackActivate()){//每一帧都会调用绑定在这个代理上的函数获得cameramodeif (DetermineCameraModeDelegate.IsBound()){if (const TSubclassOf<ULyraCameraMode> CameraMode = DetermineCameraModeDelegate.Execute()){CameraModeStack->PushCameraMode(CameraMode);}}}
}
//在这个component中,当pawn完成初始化的时候
//把代理和函数hook一下
void ULyraHeroComponent::OnPawnReadyToInitialize()
{if (!ensure(!bPawnHasInitialized)){// Don't initialize twicereturn;}APawn* Pawn = GetPawn<APawn>();if (!Pawn){return;}const bool bIsLocallyControlled = Pawn->IsLocallyControlled();ALyraPlayerState* LyraPS = GetPlayerState<ALyraPlayerState>();check(LyraPS);const ULyraPawnData* PawnData = nullptr;if (ULyraPawnExtensionComponent* PawnExtComp = ULyraPawnExtensionComponent::FindPawnExtensionComponent(Pawn)){PawnData = PawnExtComp->GetPawnData<ULyraPawnData>();// The player state holds the persistent data for this player (state that persists across deaths and multiple pawns).// The ability system component and attribute sets live on the player state.PawnExtComp->InitializeAbilitySystem(LyraPS->GetLyraAbilitySystemComponent(), LyraPS);}if (ALyraPlayerController* LyraPC = GetController<ALyraPlayerController>()){if (Pawn->InputComponent != nullptr){InitializePlayerInput(Pawn->InputComponent);}}if (bIsLocallyControlled && PawnData){if (ULyraCameraComponent* CameraComponent = ULyraCameraComponent::FindCameraComponent(Pawn)){//在这里代理和函数bind一下,就是说每一帧都会调用DetermineCameraMode()函数CameraComponent->DetermineCameraModeDelegate.BindUObject(this, &ThisClass::DetermineCameraMode);}}bPawnHasInitialized = true;
}
TSubclassOf<ULyraCameraMode> ULyraHeroComponent::DetermineCameraMode() const
{//有mode 就返回mode,这个mode是通过ga赋予的if (AbilityCameraMode){return AbilityCameraMode;}const APawn* Pawn = GetPawn<APawn>();if (!Pawn){return nullptr;}//如果没有技能的camera mode 就用pawndata中定义的角色默认的camera modeif (ULyraPawnExtensionComponent* PawnExtComp = ULyraPawnExtensionComponent::FindPawnExtensionComponent(Pawn)){if (const ULyraPawnData* PawnData = PawnExtComp->GetPawnData<ULyraPawnData>()){return PawnData->DefaultCameraMode;}}return nullptr;
}

void ULyraGameplayAbility::SetCameraMode(TSubclassOf<ULyraCameraMode> CameraMode)
{ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(SetCameraMode, );if (ULyraHeroComponent* HeroComponent = GetHeroComponentFromActorInfo()){HeroComponent->SetAbilityCameraMode(CameraMode, CurrentSpecHandle);ActiveCameraMode = CameraMode;}
}void ULyraHeroComponent::SetAbilityCameraMode(TSubclassOf<ULyraCameraMode> CameraMode, const FGameplayAbilitySpecHandle& OwningSpecHandle)
{if (CameraMode){AbilityCameraMode = CameraMode;AbilityCameraModeOwningSpecHandle = OwningSpecHandle;}
}

技能用完就把技能cameramode撤销

//这个是个蓝图函数在技能的end中调用
void ULyraGameplayAbility::ClearCameraMode()
{ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(ClearCameraMode, );if (ActiveCameraMode){if (ULyraHeroComponent* HeroComponent = GetHeroComponentFromActorInfo()){HeroComponent->ClearAbilityCameraMode(CurrentSpecHandle);}ActiveCameraMode = nullptr;}
}

简单来说就是有个默认的cameramode ,一旦有ga要求自己的camera mode 就会把ga 的mode添加到cameramodestack中

下面就是多个camera mode切换的时候是如何blend的

//此函数每帧都会执行
void ULyraCameraModeStack::PushCameraMode(TSubclassOf<ULyraCameraMode> CameraModeClass)
{if (!CameraModeClass){return;}//如果在instance的数组中找到已经有初始化的对象就直接返回。ULyraCameraMode* CameraMode = GetCameraModeInstance(CameraModeClass);check(CameraMode);int32 StackSize = CameraModeStack.Num();//如果要添加的cameramode 已经是在第一个了,就直接returnif ((StackSize > 0) && (CameraModeStack[0] == CameraMode)){// Already top of stack.return;}//如果第一个不等于要添加的,就for一下,如果在其他位置找到了,先remove再添加到第一个位置//假如数组中没有新来的,那么新来的weight最后值是0//如果新来的在数组里有,但是不是第一个,那么新来的weight会继承之前的weight// See if it's already in the stack and remove it.// Figure out how much it was contributing to the stack.int32 ExistingStackIndex = INDEX_NONE;float ExistingStackContribution = 1.0f;for (int32 StackIndex = 0; StackIndex < StackSize; ++StackIndex){if (CameraModeStack[StackIndex] == CameraMode){ExistingStackIndex = StackIndex;ExistingStackContribution *= CameraMode->GetBlendWeight();break;}else{ExistingStackContribution *= (1.0f - CameraModeStack[StackIndex]->GetBlendWeight());}}if (ExistingStackIndex != INDEX_NONE){CameraModeStack.RemoveAt(ExistingStackIndex);StackSize--;}else{ExistingStackContribution = 0.0f;}// Decide what initial weight to start with.const bool bShouldBlend = ((CameraMode->GetBlendTime() > 0.0f) && (StackSize > 0));const float BlendWeight = (bShouldBlend ? ExistingStackContribution : 1.0f);CameraMode->SetBlendWeight(BlendWeight);// Add new entry to top of stack.CameraModeStack.Insert(CameraMode, 0);// Make sure stack bottom is always weighted 100%.CameraModeStack.Last()->SetBlendWeight(1.0f);// Let the camera mode know if it's being added to the stack.if (ExistingStackIndex == INDEX_NONE){CameraMode->OnActivation();}
}

ue5 lyra camera相关推荐

  1. ue5 lyra探索分析1

    问题1: 这个地图的worldsetting中并没有指定gamemode,那么游戏运行的时候角色的类型是怎么指定的呢? 有人说在projectsetting中有一个全局的gamemode 但是这个角色 ...

  2. ue5 lyra的角色动画系统 持续更新中。。。。

    框架两方面 1.先说动画蓝图 基础角色用了A动画蓝图( ABP_Mannequin_Base),A继承了一个接口AI, 在A中写了整个的动画逻辑比如locomotion,上半身特定动画融合,挨枪子的动 ...

  3. ue5 lyra探索分析2 持续更新中

    探索 看看角色走到 front end 发生了什么 当角色触碰到 光效的时候会走到这里 先看看谁碰的我 是pawn的话继续往下走 如果pawn的controller合法  如果这个pawn是local ...

  4. UE5 Lyra游戏内容制作学习总纲

    Lyra,或者说Lyra Starter Game,是一个由虚幻引擎提供的演示项目,旨在向游戏开发人员展示虚幻引擎5的新功能和技术. 简单来看,这个项目是一个第三人称射击对战游戏,让玩家使用各种枪械武 ...

  5. UE5 Lyra中的UI层级与资产管理

    一.外部接入接口:UGameUIManagerSubsystem 主要用来从GameInstance获取玩家的加入退出和销毁通知,并传入UGameUIPolicy DefaultUIPolicyCla ...

  6. UE5 官方案例Lyra 全特性详解 10.进度汇报和视频推荐

    UE5 官方案例Lyra 全特性详解 0. 进度汇报 0.1 2022 Epic MegaJam概要 0.1.1 如何参赛 0.1.2 参赛资格 0.1.3 比赛时间 0.1.4 奖品 0.1.5 * ...

  7. UE5 官方案例Lyra 全特性详解 9.蓝图消息系统

    UE5 官方案例Lyra 全特性详解 0.前言 1.消息监听蓝图节点 1.1 监听限定 1.2 消息输出 2. 广播消息蓝图节点 3.其他相关蓝图节点 4. 后续更新 0.前言 最近在和三个小伙伴一起 ...

  8. UE5 官方案例Lyra 全特性详解 11.背包系统Inventory System 0

    UE5 官方案例Lyra 全特性详解 0. 前言 1. 前置声明 2. 修复背包游戏体验不加载的问题 2.1 通过输出日志的警告找到问题根源 2.2 修复资源加载的问题 3. 交互按钮不起作用 4. ...

  9. UE5 官方案例Lyra 全特性详解 7.资源管理

    UE5 官方案例Lyra 全特性详解 0.前言 1.资源管理 1.1大文件GLF 1.2 地图资源管理 1.3 玩法资源 2.后续 0.前言 原本这一篇是要讲防御塔的AI逻辑,但是由于防御塔动画蓝图还 ...

最新文章

  1. Failed to load module script: The server responded with a non-JavaScript MIME type of “text/plain“.
  2. 软件测试2019:第七次作业—— 用户体验测试
  3. kafka内存不断增加_分布式发布订阅消息系统Kafka 为什么快
  4. Metasploit Framework命令汇总
  5. C++中如何表示2进制,8进制、16进制变量
  6. 李宏毅机器学习2021】机器学习模型的可解释性 (Explainable ML)
  7. 开源-一步步实现cnblogs博客采集工具-实现过滤设置对话框
  8. python中tolist()命令
  9. linux 执行命令详细步骤,Linux命令行使用教程
  10. linux su root 限制,Linux禁止普通用户su至root
  11. 【LaTex】各种空格的实现(相对quad、qquad、\,、\:、\;、\!、endspace、thinspace、negthinspace绝对vspace和hspace膨胀hfill、vfill)
  12. W10无法联网,右下角WIFI图标消失;经过网络重置后,网络适配器也全部丢失。
  13. 这是我网店的链接欢迎来看看
  14. 广搜4 ——Cheese
  15. 关于 网易云音乐 我喜欢的音乐 排序无法改为添加时间 排序无法还原 的问题
  16. java中的逻辑结构
  17. 通用串行总线控制器显示感叹号
  18. sql语句choose/when/otherwise使用注意
  19. 宝宝生活点滴(10.1-10.20)
  20. C# 山寨版完整版QQ

热门文章

  1. Java复习总结之快速区分值传递和引用传递
  2. KMP算法——很详细的讲解
  3. 计算机视觉技术英语论文,【毕业论文】外文翻译--计算机视觉技术在工业中的应用.doc...
  4. 为什么网站排名上不去
  5. 2022最新素材解析网站源码搭建和原理,附带PHP小例子。
  6. Java - 拷贝亿赛通项目
  7. git fork的使用
  8. 服务器win10虚拟内存设置方法,win10虚拟内存怎么设置最好_win10虚拟内存设置多少好-win7之家...
  9. 三个大傻大闹你的脑袋,如何让他们胜过一个诸葛亮?
  10. 4、CSS立体盒子动画——复仇者联盟