IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 【AdvancedLocomotionSystemV】第二篇 C++ 实现镜头跟随人物缓慢移动 -> 正文阅读

[游戏开发]【AdvancedLocomotionSystemV】第二篇 C++ 实现镜头跟随人物缓慢移动

效果展示

请添加图片描述
上篇那样做,镜头和人物走着走着就会跑偏,所以这章完成镜头时刻紧跟着角色。
首先要将更新镜头位置的这个函数删除,之后会换成C++的代码。
在这里插入图片描述

创建接口

接口的使用我在之前的文章中讲过了, 所以这里就不讲啦。【【UE4 C++】如何使用C++接口
在这里插入图片描述
命名为:ALS_Camera

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "ALS_Camera.generated.h"

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UALS_Camera : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class ALSVLEARNDEMO_API IALS_Camera
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:

	/**
	 * @brief 返回Actor的Transform变量
	 * 包含所在位置、旋转、缩放等信息。
	 */
	UFUNCTION(BlueprintNativeEvent)
	FTransform Get3PPivotTarget();

	virtual FTransform Get3PPivotTarget_Implementation();

	/**
	 * @brief 获得摄像机的一些视场角属性,视场角越大视野就越大。
	 * @param TP_FOV 第三人称视场角
	 * @param FP_FOV 第一人称市场角
	 * @return 是否是右边位置。
	 */
	UFUNCTION(BlueprintNativeEvent)
	bool GetCameraParameters(float& TP_FOV, float& FP_FOV);

	virtual bool GetCameraParameters_Implementation(float& TP_FOV, float& FP_FOV);
};

源文件这边就默认定义一下就好了。
注释中有说到这个源文件的主要作用就是为任何非纯虚函数添加默认功能。

#include "ALS_Camera.h"

// Add default functionality here for any IALS_Camera functions that are not pure virtual.
FTransform IALS_Camera::Get3PPivotTarget_Implementation()
{
	return {};
}

bool IALS_Camera::GetCameraParameters_Implementation(float& TP_FOV, float& FP_FOV)
{
	return false;
}

在角色类中进行接口的实现

在角色的基类中继承接口,并重新实现接口函数。

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Interfaces/ALS_Camera.h"
#include "ALSVLearnDemoCharacter.generated.h"

UCLASS(config=Game)
class AALSVLearnDemoCharacter : public ACharacter, public IALS_Camera // 继承接口
{
	GENERATED_BODY()

public:
	
	……
	……
	……

	/
	/// 摄像机相关变量、函数

	UPROPERTY(Category="Camera System", EditInstanceOnly, BlueprintReadWrite)
	float ThirdPersonFOV;

	UPROPERTY(Category="Camera System", EditInstanceOnly, BlueprintReadWrite)
	float FirstPersonFOV;

	UPROPERTY(Category="Camera System", EditInstanceOnly, BlueprintReadWrite)
	bool bRightShoulder;

	/
	/// 接口相关变量、函数

	// 重载接口
	virtual bool GetCameraParameters_Implementation(float& TP_FOV, float& FP_FOV) override;
};

就是将参数传到接口中。

// Copyright Epic Games, Inc. All Rights Reserved.

#include "ALSVLearnDemoCharacter.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/Controller.h"

//
// AALSVLearnDemoCharacter

AALSVLearnDemoCharacter::AALSVLearnDemoCharacter()
{
	……
	……
	……

	ThirdPersonFOV = 90.f;
	FirstPersonFOV = 90.f;
}


……
……
……


bool AALSVLearnDemoCharacter::GetCameraParameters_Implementation(float& TP_FOV, float& FP_FOV)
{
	TP_FOV = ThirdPersonFOV;
	FP_FOV = FirstPersonFOV;
	return bRightShoulder;
}

然后再到ALS_AnimMan_Character角色中将另一个函数进行重载实现。

#pragma once

#include "CoreMinimal.h"
#include "../ALSVLearnDemoCharacter.h"
#include "ALS_AnimMan_Character.generated.h"

/**
 * 
 */
UCLASS()
class ALSVLEARNDEMO_API AALS_AnimMan_Character : public AALSVLearnDemoCharacter
{
	GENERATED_BODY()
public:
	
	//
	/// 接口相关函数

	virtual FTransform Get3PPivotTarget_Implementation() override;
};

源文件:

#include "ALS_AnimMan_Character.h"

FTransform AALS_AnimMan_Character::Get3PPivotTarget_Implementation()
{
	// 使用具体的两个插槽计算角色的中心点更加精准。
	// 比如说胶囊体不会缩小,当角色蹲下的时候,我们获取人物的位置的时候并不会发生改变,
	// 			但如果是根据骨骼位置然后求中心点的话,这个位置就会跟着发生改变。
	const FVector Location = (GetMesh()->GetSocketLocation(TEXT("head")) + GetMesh()->GetSocketLocation(TEXT("root")))
		/ 2.f;
	
	return FTransform(GetActorRotation(), Location, FVector(1.f, 1.f, 1.f));
}

添加摄像机移动逻辑

重载UpdateViewTargetInternal更新摄像机位置。

#pragma once

#include "CoreMinimal.h"
#include "Camera/PlayerCameraManager.h"
#include "ALS_CameraManager.generated.h"

class UALS_PlayerCameraBehavior;
/**
 * 
 */
UCLASS()
class ALSVLEARNDEMO_API AALS_CameraManager : public APlayerCameraManager
{
	GENERATED_BODY()

public:
	AALS_CameraManager();
	
	UFUNCTION(BlueprintCallable)
	void OnPossess(APawn* NewPawn);

	// 更新摄像机位置的函数
	virtual void UpdateViewTargetInternal(FTViewTarget& OutVT, float DeltaTime) override;
	
	/**
	 * @brief 自定义摄像机的信息
	 * @param Location 摄像机的位置
	 * @param Rotation 摄像机的旋转值
	 * @param FOV 摄像机镜头所覆盖的位置
	 */
	UFUNCTION(BlueprintCallable)
	void CustomCameraBehavior(FVector& Location, FRotator& Rotation, float& FOV);
	
	/**
	 * @brief 获取摄像机曲线的值
	 */
	UFUNCTION(BlueprintCallable)
	float GetCameraBehaviorParam(FName CurveName);

	/**
	 * @brief 计算轴无关延迟
	 * @param CurrentLocation 目前位置
	 * @param TargetLocation  目标位置
	 * @param CameraRotation  摄像机位置
	 * @param LagSpeeds  延迟速度
	 * @return 延迟之后的位置
	 */
	UFUNCTION(BlueprintCallable)
	FVector CalculateAxisIndependentLag(FVector CurrentLocation, FVector TargetLocation, FRotator CameraRotation, FVector LagSpeeds);
	
	
	/**
	 * @brief 摄像机将要旋转到的旋转度  也就相当于当前摄像机的旋转值
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	FRotator TargetCameraRotation;

	/**
	 * @brief 摄像机将要移动到的位置 相当于当前摄像机的位置
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	FVector TargetCameraLocation;

	/**
	 * @brief 平滑目标锚点信息
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	FTransform SmoothedPivotTarget;

	/**
	 * @brief 设置锚点位置信息
	 */
	UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	FVector PivotLocation;
	
	
	/// 组件相关属性
	
	UFUNCTION(Category="Components", BlueprintCallable)
	USkeletalMeshComponent* GetCameraBehaviorComp() const { return CameraBehaviorComp; }
	
	///
	/// 对一些类的引用

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	APawn* ControllerPawn;

	UPROPERTY()
	UALS_PlayerCameraBehavior* PlayerCameraBehavior;
	
private:
	/**
	 * @brief 添加摄像机骨骼,这样的话,人物运行状态机的时候摄像机也会进行状态机,这样就会有一个相对高的匹配度。
	 */
	UPROPERTY(Category="Components", VisibleAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess = "true"))
	USkeletalMeshComponent* CameraBehaviorComp;
};

源文件:

// Fill out your copyright notice in the Description page of Project Settings.


#include "ALS_CameraManager.h"

#include "ALS_PlayerCameraBehavior.h"
#include "ALSVLearnDemo/Interfaces/ALS_Camera.h"
#include "Kismet/KismetMathLibrary.h"

AALS_CameraManager::AALS_CameraManager()
{
	CameraBehaviorComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CameraBehaviorComp"));
	CameraBehaviorComp->SetupAttachment(RootComponent);
}

/**
 * @brief 摄像机创建了之后,控制器会给他一个所控制的对象,如果这个对象具有 ”ALS_Character“ 标签的话,使用自己定义的摄像机移动逻辑。没有就用父类的。
 */
void AALS_CameraManager::UpdateViewTargetInternal(FTViewTarget& OutVT, float DeltaTime)
{
	if (!IsValid(OutVT.Target)) return;
	
	if (OutVT.Target->ActorHasTag(TEXT("ALS_Character")))
	{
		CustomCameraBehavior(OutVT.POV.Location, OutVT.POV.Rotation, OutVT.POV.FOV);
	}
	else
	{
		Super::UpdateViewTargetInternal(OutVT, DeltaTime);
	}
}

void AALS_CameraManager::OnPossess(APawn* NewPawn)
{
	ControllerPawn = NewPawn;

	//
	/// 第二篇更新: 引用动画实例,将玩家控制器、控制的Pawn放入蓝图设置。

	PlayerCameraBehavior = Cast<UALS_PlayerCameraBehavior>(CameraBehaviorComp->GetAnimInstance());
	
	//
}

void AALS_CameraManager::CustomCameraBehavior(FVector& Location, FRotator& Rotation, float& FOV)
{
	//
	/// 第二篇更新:  自定义摄像机移动方式

	IALS_Camera* CameraInterface = Cast<IALS_Camera>(ControllerPawn);
	if (!CameraInterface) return;
	
	// 使用接口函数,获取轴心位置、 第一、三人称镜头所覆盖的范围
	// FOV是指镜头所能覆盖的范围,
	const FTransform PivotTarget = CameraInterface->Execute_Get3PPivotTarget(ControllerPawn);
	float TP_FOV, FP_FOV;
	CameraInterface->Execute_GetCameraParameters(ControllerPawn, TP_FOV, FP_FOV);

	// 更新摄像机目标旋转度的值
	const FRotator CurrentRotation = GetCameraRotation();
	const FRotator TargetRotation = GetOwningPlayerController()->GetControlRotation();
	TargetCameraRotation = FMath::RInterpTo(CurrentRotation, TargetRotation, GetWorld()->DeltaTimeSeconds,
	                                        GetCameraBehaviorParam(TEXT("RotationLagSpeed")));

	// 添加了 PivotLagSpeed 值之后,摄像机左右移动时会有一个平滑过渡的效果,向左向右移动,人物停止移动之后镜头得过一会才会停止。
 	// 更新平滑目标平滑锚点位置信息 
	const FVector LagLocation = CalculateAxisIndependentLag(SmoothedPivotTarget.GetTranslation(),
	                                                        PivotTarget.GetTranslation(),
	                                                        TargetCameraRotation,
	                                                        FVector(GetCameraBehaviorParam(TEXT("PivotLagSpeed_X")),
	                                                                GetCameraBehaviorParam(TEXT("PivotLagSpeed_Y")),
	                                                                GetCameraBehaviorParam(TEXT("PivotLagSpeed_Z"))));
	SmoothedPivotTarget = FTransform(PivotTarget.GetRotation(), LagLocation, FVector(1.f, 1.f, 1.f));

	// 设置局部轴心偏移
	FVector ForwardVector = SmoothedPivotTarget.GetRotation().GetForwardVector() * GetCameraBehaviorParam(TEXT("PivotOffset_X"));
	FVector RightVector = SmoothedPivotTarget.GetRotation().GetRightVector() * GetCameraBehaviorParam(TEXT("PivotOffset_Y"));
	FVector UpVector = SmoothedPivotTarget.GetRotation().GetUpVector() * GetCameraBehaviorParam(TEXT("PivotOffset_Z"));
	PivotLocation = SmoothedPivotTarget.GetTranslation() + ForwardVector + RightVector + UpVector;

	// CameraOffset 存储的是摄像机与对象之间的位置偏差值。 就相当于之前用的角色后面跟随的摄像头的相对位置。
	// 设置局部摄像机偏移位置
	ForwardVector = TargetCameraRotation.Vector() * GetCameraBehaviorParam(TEXT("CameraOffset_X"));
	RightVector = UKismetMathLibrary::GetRightVector(TargetCameraRotation) * GetCameraBehaviorParam(TEXT("CameraOffset_Y"));
	UpVector = UKismetMathLibrary::GetUpVector(TargetCameraRotation) * GetCameraBehaviorParam(TEXT("CameraOffset_Z"));
	TargetCameraLocation = PivotLocation + ForwardVector + RightVector + UpVector;

	// step 6 TODO DEBUG


	Location = TargetCameraLocation;
	Rotation = TargetCameraRotation;
	FOV = TP_FOV;

	//
}

float AALS_CameraManager::GetCameraBehaviorParam(FName CurveName)
{
	if (PlayerCameraBehavior)
	{
		return PlayerCameraBehavior->GetCurveValue(CurveName);
	}
	return 0.f;
}

FVector AALS_CameraManager::CalculateAxisIndependentLag(FVector CurrentLocation, FVector TargetLocation,
                                                        FRotator CameraRotation, FVector LagSpeeds)
{
	// 获取摄像头的横向旋转角度
	const FRotator CameraRotationYaw(0.f, CameraRotation.Yaw, 0.f);

	const FVector CurrentLocation_UnRotateVector = CameraRotationYaw.UnrotateVector(CurrentLocation);
	const FVector TargetLocation_UnRotateVector = CameraRotationYaw.UnrotateVector(TargetLocation);

	FVector Location;
	Location.X = FMath::FInterpTo(CurrentLocation_UnRotateVector.X, TargetLocation_UnRotateVector.X,
	                              GetWorld()->DeltaTimeSeconds, LagSpeeds.X);
	Location.Y = FMath::FInterpTo(CurrentLocation_UnRotateVector.Y, TargetLocation_UnRotateVector.Y,
	                              GetWorld()->DeltaTimeSeconds, LagSpeeds.Y);
	Location.Z = FMath::FInterpTo(CurrentLocation_UnRotateVector.Z, TargetLocation_UnRotateVector.Z,
	                              GetWorld()->DeltaTimeSeconds, LagSpeeds.Z);

	return CameraRotationYaw.RotateVector(Location);
}

函数设计思路讲解:
请添加图片描述
在函数里面为什么要加UnrotatorVector 和 RotatorVector,想了好久都不知道为什么,如果有大佬知道这个希望您能够在评论区评论一下。

编译运行之后将摄像机骨骼加载进去。
在这里插入图片描述

创建动画蓝图

先创建一个UAnimInstance的C++类:ALS_PlayerCameraBehavior
先放在一边,之后会用到。

右键
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
修改参数,运行就完成啦!

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-10-20 12:48:49  更:2021-10-20 12:49:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 0:58:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码