ue5 lyra camera
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相关推荐
- ue5 lyra探索分析1
问题1: 这个地图的worldsetting中并没有指定gamemode,那么游戏运行的时候角色的类型是怎么指定的呢? 有人说在projectsetting中有一个全局的gamemode 但是这个角色 ...
- ue5 lyra的角色动画系统 持续更新中。。。。
框架两方面 1.先说动画蓝图 基础角色用了A动画蓝图( ABP_Mannequin_Base),A继承了一个接口AI, 在A中写了整个的动画逻辑比如locomotion,上半身特定动画融合,挨枪子的动 ...
- ue5 lyra探索分析2 持续更新中
探索 看看角色走到 front end 发生了什么 当角色触碰到 光效的时候会走到这里 先看看谁碰的我 是pawn的话继续往下走 如果pawn的controller合法 如果这个pawn是local ...
- UE5 Lyra游戏内容制作学习总纲
Lyra,或者说Lyra Starter Game,是一个由虚幻引擎提供的演示项目,旨在向游戏开发人员展示虚幻引擎5的新功能和技术. 简单来看,这个项目是一个第三人称射击对战游戏,让玩家使用各种枪械武 ...
- UE5 Lyra中的UI层级与资产管理
一.外部接入接口:UGameUIManagerSubsystem 主要用来从GameInstance获取玩家的加入退出和销毁通知,并传入UGameUIPolicy DefaultUIPolicyCla ...
- 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 * ...
- UE5 官方案例Lyra 全特性详解 9.蓝图消息系统
UE5 官方案例Lyra 全特性详解 0.前言 1.消息监听蓝图节点 1.1 监听限定 1.2 消息输出 2. 广播消息蓝图节点 3.其他相关蓝图节点 4. 后续更新 0.前言 最近在和三个小伙伴一起 ...
- UE5 官方案例Lyra 全特性详解 11.背包系统Inventory System 0
UE5 官方案例Lyra 全特性详解 0. 前言 1. 前置声明 2. 修复背包游戏体验不加载的问题 2.1 通过输出日志的警告找到问题根源 2.2 修复资源加载的问题 3. 交互按钮不起作用 4. ...
- UE5 官方案例Lyra 全特性详解 7.资源管理
UE5 官方案例Lyra 全特性详解 0.前言 1.资源管理 1.1大文件GLF 1.2 地图资源管理 1.3 玩法资源 2.后续 0.前言 原本这一篇是要讲防御塔的AI逻辑,但是由于防御塔动画蓝图还 ...
最新文章
- Failed to load module script: The server responded with a non-JavaScript MIME type of “text/plain“.
- 软件测试2019:第七次作业—— 用户体验测试
- kafka内存不断增加_分布式发布订阅消息系统Kafka 为什么快
- Metasploit Framework命令汇总
- C++中如何表示2进制,8进制、16进制变量
- 李宏毅机器学习2021】机器学习模型的可解释性 (Explainable ML)
- 开源-一步步实现cnblogs博客采集工具-实现过滤设置对话框
- python中tolist()命令
- linux 执行命令详细步骤,Linux命令行使用教程
- linux su root 限制,Linux禁止普通用户su至root
- 【LaTex】各种空格的实现(相对quad、qquad、\,、\:、\;、\!、endspace、thinspace、negthinspace绝对vspace和hspace膨胀hfill、vfill)
- W10无法联网,右下角WIFI图标消失;经过网络重置后,网络适配器也全部丢失。
- 这是我网店的链接欢迎来看看
- 广搜4 ——Cheese
- 关于 网易云音乐 我喜欢的音乐 排序无法改为添加时间 排序无法还原 的问题
- java中的逻辑结构
- 通用串行总线控制器显示感叹号
- sql语句choose/when/otherwise使用注意
- 宝宝生活点滴(10.1-10.20)
- C# 山寨版完整版QQ
热门文章
- Java复习总结之快速区分值传递和引用传递
- KMP算法——很详细的讲解
- 计算机视觉技术英语论文,【毕业论文】外文翻译--计算机视觉技术在工业中的应用.doc...
- 为什么网站排名上不去
- 2022最新素材解析网站源码搭建和原理,附带PHP小例子。
- Java - 拷贝亿赛通项目
- git fork的使用
- 服务器win10虚拟内存设置方法,win10虚拟内存怎么设置最好_win10虚拟内存设置多少好-win7之家...
- 三个大傻大闹你的脑袋,如何让他们胜过一个诸葛亮?
- 4、CSS立体盒子动画——复仇者联盟