UE5数字孪生系列笔记(三)

C++创建Pawn类玩家

  • 创建一个GameMode蓝图用来加载我们自定义的游戏Mode
  • 新建一个Pawn的C++,MyCharacter类作为玩家,新建一个相机组件与相机臂组件,box组件作为根组件
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "MyCharacter.generated.h"

UCLASS()
class CITYTWIN_API AMyCharacter : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	AMyCharacter();

	//box作为根组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class UBoxComponent* CollisionBox;

	//相机组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class UCameraComponent* FollowCamera;

	//相机臂组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class USpringArmComponent* CameraBoom;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};

  • 声明创建组件,硬编码一些基本属性
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyCharacter.h"
#include "Components/BoxComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"

// Sets default values
AMyCharacter::AMyCharacter()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
	CollisionBox->SetupAttachment(GetRootComponent());

	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(CollisionBox);
	CameraBoom->TargetArmLength = 1500.f;
	CameraBoom->bUsePawnControlRotation = false;
	CameraBoom->bEnableCameraLag = true;//摄像机臂平滑
	CameraBoom->bEnableCameraRotationLag = true;//启用相机旋转延迟
	CameraBoom->bDoCollisionTest = false;//关闭摄像机臂碰撞

	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
	FollowCamera->SetupAttachment(CameraBoom);
	FollowCamera->bUsePawnControlRotation = false;
}

// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}
  • 创建这个Pawn类的蓝图进行之前登录页面动画的视角旋转方向问题的解决
  • 首先将蓝图生成对齐到视角
    在这里插入图片描述
  • 将Pawn类自动接收玩家0
    在这里插入图片描述
  • 然后删除PlayerStart
    在这里插入图片描述
  • 运行结果
    请添加图片描述

移动增强输入系统

  • 在项目建立.cs文件中添加这个模块
    在这里插入图片描述
  • 绑定增强输入系统操作
  • MyCharacter.h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "../../../../UE_5.2.1/UE_5.2/Engine/Plugins/EnhancedInput/Source/EnhancedInput/Public/InputActionValue.h"
#include "MyCharacter.generated.h"

UCLASS()
class CITYTWIN_API AMyCharacter : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	AMyCharacter();

	//box作为根组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class UBoxComponent* CollisionBox;

	//相机组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class UCameraComponent* FollowCamera;

	//相机臂组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class USpringArmComponent* CameraBoom;

	//绑定映射
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputMappingContext* MappingContext;

	//移动绑定
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputAction* LeftButtonAction;


protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	//鼠标按下操作事件
	void LeftMouseDown(const FInputActionValue& value);
	void LeftMouseUp(const FInputActionValue& value);

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};

  • MyCharacter.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyCharacter.h"
#include "Components/BoxComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"

// Sets default values
AMyCharacter::AMyCharacter()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
	CollisionBox->SetupAttachment(GetRootComponent());

	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(CollisionBox);
	CameraBoom->TargetArmLength = 1500.f;
	CameraBoom->bUsePawnControlRotation = false;
	CameraBoom->bEnableCameraLag = true;//摄像机臂平滑
	CameraBoom->bEnableCameraRotationLag = true;//启用相机旋转延迟
	CameraBoom->bDoCollisionTest = false;//关闭摄像机臂碰撞

	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
	FollowCamera->SetupAttachment(CameraBoom);
	FollowCamera->bUsePawnControlRotation = false;
}
// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{
	Super::BeginPlay();
	APlayerController* PlayerController = Cast<APlayerController>(Controller);
	if (PlayerController)
	{
		UEnhancedInputLocalPlayerSubsystem* Subsystem =
			ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
		if (Subsystem)
		{
			Subsystem->AddMappingContext(MappingContext, 0);
		}
	}
}
void AMyCharacter::LeftMouseDown(const FInputActionValue& value)
{
}

void AMyCharacter::LeftMouseUp(const FInputActionValue& value)
{
}
// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	UEnhancedInputComponent* EnhancedInputConponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
	if (EnhancedInputConponent)
	{
		EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Started, this, &AMyCharacter::LeftMouseDown);
		EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::LeftMouseUp);

	}
}

获取鼠标位置坐标与鼠标移动后的差量

  • 使用GetMousePosition函数来获取鼠标的坐标点
  • MyCharacter.h中新建一个函数专门用来获取鼠标的坐标点的函数
	//鼠标的坐标点
	FVector2D MousePos = FVector2D::ZeroVector;

void GetMousePosition();
  • MyCharacter.cpp中实现此方法
void AMyCharacter::GetMousePosition()
{
	
	GetWorld()->GetFirstPlayerController()->GetMousePosition(MousePos.X, MousePos.Y);
	
	//打印鼠标信息到屏幕
	GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, FString::Printf(TEXT("%f,%f"), MousePos.X, MousePos.Y));
}

  • 获取鼠标变化差量,当我们鼠标变化时,我们要获取到这个变化的差量值,我们可以定义两个变量,一个变量存储用来作为变化之前的绝对位置减去变化之后的当前绝对位置,然后另外两个变量来存储变化之后当前的绝对位置
	//鼠标的坐标点
	FVector2D MousePos = FVector2D::ZeroVector;
	
	//记录的鼠标变化差量
	FVector2D MouseVariationDifference = FVector2D::ZeroVector;

	//记录变化之后的鼠标坐标
	float MouseX = 0.f;
	float MouseY = 0.f;

void AMyCharacter::GetMousePosition()
{

	//获取当前鼠标移动坐标
	GetWorld()->GetFirstPlayerController()->GetMousePosition(MousePos.X, MousePos.Y);

	//记录的鼠标变化差量
	MouseVariationDifference = MousePos - FVector2D(MouseX, MouseY);

	//记录变化后的鼠标位置
	MouseX = MousePos.X;
	MouseY = MousePos.Y;

	//打印鼠标信息到屏幕
	GEngine->AddOnScreenDebugMessage(1, 1, FColor::Red, FString::Printf(TEXT("%f,%f"), MousePos.X, MousePos.Y));
	GEngine->AddOnScreenDebugMessage(2, 1, FColor::Yellow, FString::Printf(TEXT("%f,%f"), MouseVariationDifference.X, MouseVariationDifference.Y));
}

设置滑动鼠标实现旋转视角效果

  • 通过获取的移动的鼠标差量进行鼠标滑动移动视角
  • 新建一个鼠标视角移动速度变量,用来控制鼠标实现视角旋转的移动速度
	//鼠标视角移动速度
	float MouseSpeed = 0.1f;
  • 新建一个鼠标视角移动函数,函数逻辑
  • ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed):Pitch是虚幻中的抬头与低头,在直角坐标系中用来Y来描述
  • ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f):Yaw是摇头转向,在直角坐标系中用来X来描述,实践中得乘以-1使用,估计是因为虚幻默认以右方向为正方向的原因
	//鼠标移动视角移动事件
	void MouseMove();
	
void AMyCharacter::MouseMove()
{
	FRotator ActorRotator = GetActorRotation();
	FRotator NewActorRotator = FRotator(ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed),
		ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
	SetActorRotation(NewActorRotator);
}
  • 调用函数
// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	//获取鼠标坐标
	GetMousePosition();
	//鼠标移动视角
	MouseMove();

}
  • 运行结果
    请添加图片描述

鼠标左键视觉拖动效果

  • 将滑动鼠标实现旋转视角效果设置为鼠标左键按下后才能实现
  • 添加一个布尔变量用来标识是否要开启鼠标旋转视角事情
	//标识鼠标左键是否按下
	bool bIsMouseLeftDown = false;

void AMyCharacter::MouseMove()
{
	if (bIsMouseLeftDown)
	{
		FRotator ActorRotator = GetActorRotation();
		//限制一下视角度数带来的错误
		FRotator NewActorRotator = FRotator(FMath::Clamp((ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed)),-80.f,-10.f),
			ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
		SetActorRotation(NewActorRotator);
		
	}
}

void AMyCharacter::LeftMouseDown(const FInputActionValue& value)
{
	bIsMouseLeftDown = true;
}

void AMyCharacter::LeftMouseUp(const FInputActionValue& value)
{
	bIsMouseLeftDown = false;
}

鼠标右键视角移动效果

  • 添加右键的输入操作
    在这里插入图片描述
  • 新建右键是否按下的标识布尔变量,创建右键操作的输入行为,即绑定函数
	//移动绑定
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputAction* RightButtonAction;
	//标识鼠标右键是否按下
	bool bIsMouseRightDown = false;


// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	UEnhancedInputComponent* EnhancedInputConponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
	if (EnhancedInputConponent)
	{
		EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Started, this, &AMyCharacter::LeftMouseDown);
		EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::LeftMouseUp);
		EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Started, this, &AMyCharacter::RightMouseDown);
		EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::RightMouseUp);
	}
}

void AMyCharacter::RightMouseDown(const FInputActionValue& value)
{
	bIsMouseRightDown = true;
}

void AMyCharacter::RightMouseUp(const FInputActionValue& value)
{
	bIsMouseRightDown = false;
}

  • 新建鼠标右键移动速度变量,编写鼠标右键移动逻辑
	//鼠标右键移动速度
	float MouseRightSpeed = 100.f;

void AMyCharacter::MouseMove()
{
	if (bIsMouseLeftDown)
	{
		FRotator ActorRotator = GetActorRotation();
		//限制一下视角度数带来的错误
		FRotator NewActorRotator = FRotator(FMath::Clamp((ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed)),-80.f,-10.f),
			ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
		SetActorRotation(NewActorRotator);
	}
	if (bIsMouseRightDown)
	{
		FVector SpeedMove = FVector(MouseVariationDifference.Y * MouseRightSpeed,
			-1.0 * MouseRightSpeed * MouseVariationDifference.X, 0);
		AddActorLocalOffset(SpeedMove);
		//限制z轴
		FVector Location = GetActorLocation();
		FVector NewLocation = FVector(Location.X, Location.Y, 4520);
		SetActorLocation(NewLocation);
	}
}

鼠标中键控制摄像机臂长度,缩放地图效果

  • 新建鼠标中键的操作行为,添加一个鼠标中键移动速度变量,然后在鼠标中键操作事件中完成逻辑,逻辑是获取相机臂的长度,用获取鼠标滚轮的量值乘以鼠标中键移动速度变量被获取的相机臂原长度减去
	//移动绑定
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputAction* MiddleButtonAction;
	
	//鼠标中键移动速度
	float MouseMiddleSpeed = 1000.f;

void AMyCharacter::MiddleMouseSlide(const FInputActionValue& value)
{
	float Axis = value.Get<float>();
	float CameraArm = CameraBoom->TargetArmLength;
	//限制相机臂长度
	CameraBoom->TargetArmLength = FMath::Clamp((CameraArm - Axis * MouseMiddleSpeed), 1000.f, 30000.f);
}
  • 运行结果
    请添加图片描述

源码

MyCharacter.h

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "../../../../UE_5.2.1/UE_5.2/Engine/Plugins/EnhancedInput/Source/EnhancedInput/Public/InputActionValue.h"
#include "MyCharacter.generated.h"



UCLASS()
class CITYTWIN_API AMyCharacter : public APawn
{
	GENERATED_BODY()

public:
	// Sets default values for this pawn's properties
	AMyCharacter();

	//box作为根组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class UBoxComponent* CollisionBox;

	//相机组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class UCameraComponent* FollowCamera;

	//相机臂组件
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
	class USpringArmComponent* CameraBoom;

	//绑定映射
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputMappingContext* MappingContext;

	//移动绑定
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputAction* LeftButtonAction;

	//移动绑定
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputAction* RightButtonAction;

	//移动绑定
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
	class UInputAction* MiddleButtonAction;

	//鼠标的坐标点
	FVector2D MousePos = FVector2D::ZeroVector;

	//记录的鼠标变化差量
	FVector2D MouseVariationDifference = FVector2D::ZeroVector;

	//记录变化之后的鼠标坐标
	float MouseX = 0.f;
	float MouseY = 0.f;

	//鼠标视角移动速度
	float MouseSpeed = 0.1f;
	//鼠标右键移动速度
	float MouseRightSpeed = 100.f;
	//鼠标中键移动速度
	float MouseMiddleSpeed = 1000.f;

	//标识鼠标左键是否按下
	bool bIsMouseLeftDown = false;
	//标识鼠标右键是否按下
	bool bIsMouseRightDown = false;


protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	//鼠标按下操作事件
	void LeftMouseDown(const FInputActionValue& value);
	void LeftMouseUp(const FInputActionValue& value);
	void RightMouseDown(const FInputActionValue& value);
	void RightMouseUp(const FInputActionValue& value);
	void MiddleMouseSlide(const FInputActionValue& value);

	//鼠标移动视角移动事件
	void MouseMove();

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

	void GetMousePosition();
};

MyCharacter.cpp

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


#include "MyCharacter.h"
#include "Components/BoxComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "Engine/Engine.h"

// Sets default values
AMyCharacter::AMyCharacter()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
	CollisionBox->SetupAttachment(GetRootComponent());

	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(CollisionBox);
	CameraBoom->TargetArmLength = 1500.f;
	CameraBoom->bUsePawnControlRotation = false;
	CameraBoom->bEnableCameraLag = true;//摄像机臂平滑
	CameraBoom->bEnableCameraRotationLag = true;//启用相机旋转延迟
	CameraBoom->bDoCollisionTest = false;//关闭摄像机臂碰撞

	FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
	FollowCamera->SetupAttachment(CameraBoom);
	FollowCamera->bUsePawnControlRotation = false;
}

// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{
	Super::BeginPlay();
	APlayerController* PlayerController = Cast<APlayerController>(Controller);
	if (PlayerController)
	{
		UEnhancedInputLocalPlayerSubsystem* Subsystem =
			ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
		if (Subsystem)
		{
			Subsystem->AddMappingContext(MappingContext, 0);
		}
	}
}

void AMyCharacter::LeftMouseDown(const FInputActionValue& value)
{
	bIsMouseLeftDown = true;
}

void AMyCharacter::LeftMouseUp(const FInputActionValue& value)
{
	bIsMouseLeftDown = false;
}

void AMyCharacter::RightMouseDown(const FInputActionValue& value)
{
	bIsMouseRightDown = true;
}

void AMyCharacter::RightMouseUp(const FInputActionValue& value)
{
	bIsMouseRightDown = false;
}


void AMyCharacter::MiddleMouseSlide(const FInputActionValue& value)
{
	float Axis = value.Get<float>();
	float CameraArm = CameraBoom->TargetArmLength;
	//限制相机臂长度
	CameraBoom->TargetArmLength = FMath::Clamp((CameraArm - Axis * MouseMiddleSpeed), 1000.f, 30000.f);
}

void AMyCharacter::MouseMove()
{
	if (bIsMouseLeftDown)
	{
		FRotator ActorRotator = GetActorRotation();
		//限制一下视角度数带来的错误
		FRotator NewActorRotator = FRotator(FMath::Clamp((ActorRotator.Pitch + (MouseVariationDifference.Y * MouseSpeed)),-80.f,-10.f),
			ActorRotator.Yaw + (MouseVariationDifference.X * MouseSpeed * -1.f), ActorRotator.Roll);
		SetActorRotation(NewActorRotator);
	}
	if (bIsMouseRightDown)
	{
		FVector SpeedMove = FVector(MouseVariationDifference.Y * MouseRightSpeed,
			-1.0 * MouseRightSpeed * MouseVariationDifference.X, 0);
		AddActorLocalOffset(SpeedMove);
		//限制z轴
		FVector Location = GetActorLocation();
		FVector NewLocation = FVector(Location.X, Location.Y, 4520);
		SetActorLocation(NewLocation);
	}
}


// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	//获取鼠标坐标
	GetMousePosition();
	//鼠标移动视角
	MouseMove();

}

// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	UEnhancedInputComponent* EnhancedInputConponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
	if (EnhancedInputConponent)
	{
		EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Started, this, &AMyCharacter::LeftMouseDown);
		EnhancedInputConponent->BindAction(LeftButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::LeftMouseUp);
		EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Started, this, &AMyCharacter::RightMouseDown);
		EnhancedInputConponent->BindAction(RightButtonAction, ETriggerEvent::Completed, this, &AMyCharacter::RightMouseUp);
		EnhancedInputConponent->BindAction(MiddleButtonAction, ETriggerEvent::Triggered, this, &AMyCharacter::MiddleMouseSlide);

	}
}

void AMyCharacter::GetMousePosition()
{
	//获取当前鼠标移动坐标
	GetWorld()->GetFirstPlayerController()->GetMousePosition(MousePos.X, MousePos.Y);

	//记录的鼠标变化差量
	MouseVariationDifference = MousePos - FVector2D(MouseX, MouseY);

	//记录变化后的鼠标位置
	MouseX = MousePos.X;
	MouseY = MousePos.Y;

	//打印鼠标信息到屏幕
	/*GEngine->AddOnScreenDebugMessage(1, 1, FColor::Red, FString::Printf(TEXT("%f,%f"), MousePos.X, MousePos.Y));
	GEngine->AddOnScreenDebugMessage(2, 1, FColor::Yellow, FString::Printf(TEXT("%f,%f"), MouseVariationDifference.X, MouseVariationDifference.Y));*/
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/500471.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【力扣】300. 最长递增子序列(DFS+DP两种方法实现)

目录 题目传送最长递增子序列[DFS 方法]DFS方法思路图思路简述代码大家可以自行考虑有没有优化的方法 最长递增子序列[DP]方法DP方法思路图思路简述代码方案 题目传送 原题目链接 最长递增子序列[DFS 方法] DFS方法思路图 思路简述 对于序列中的每一个数字只有选择和不选择两…

C语言查找-----------BF算法KMP算法

1.问题引入 有一个主字符串&#xff0c;有一个子字符串&#xff0c;要求我们寻找子字符串在主字符串里面开始出现的位置&#xff1b; 2.BF算法 BF算法就是暴力算法&#xff0c;这个做法虽然效率不高&#xff0c;但是按照我们传统的思路依然能够得到结果&#xff0c;接下来我们…

LeetCode 523. 连续的子数组和

解题思路 相关代码 class Solution {public boolean checkSubarraySum(int[] nums, int k) {int s[] new int[nums.length1];for(int i1;i<nums.length;i) s[i]s[i-1]nums[i-1];Set<Integer> set new HashSet<>(); for(int i2;i<nums.length;i){set.ad…

filebox在线文件管理工具V1.11.1.1查分吧修改自用版免费分享[PHP]

* 基于:https://down.chinaz.com/soft/35899.htm * 查分吧 修改自用版今日对外分享(自2016年1.10版本以来一直用他云开发:Web环境即时看效果) * 也可以用于本人很多txt/csv通用查询系统的在线管理后台管理数据 * 默认登陆账号filebox密码nidemima * 修改账号密码:21-22行;获取…

Java八股文(K8S)

Java八股文のK8S K8S K8S 请解释什么是Kubernetes&#xff1f; Kubernetes是一个开源的容器编排和管理工具&#xff0c;用于自动化部署、扩展和管理容器化应用程序。 请解释Kubernetes中的Pod、Deployment和Service之间的关系。 ● Pod是Kubernetes的最小部署单元&#xff0c;…

练习 13 Web [极客大挑战 2019]Secret File

php伪协议请求&#xff0c;php代码审计 参考&#xff1a;BUUCTF__[极客大挑战 2019]Secret File_题解 没有任何上传和登录页面 查看前端源码 发现 <a id"master" href"./Archive_room.php" style"background-color:#000000;height:70px;width:20…

【java9】java9新特性值之集合不可变实例工厂方法

Java9为集合接口List、Set、Map提供了创建不可变实例的工厂方法。这些工厂方法为便利而生&#xff0c;以简单的方式创建这些集合的不可变实例。 Java9之前创建不可变集合 在Java9之前&#xff0c;创建不可变集合通常需要通过其他方式&#xff0c;比如使用Collections.unmodif…

day4 linux上部署第一个nest项目(java转ts全栈/3R教室)

背景&#xff1a;上一篇吧nest-vben-admin项目&#xff0c;再开发环境上跑通了&#xff0c;并且build出来了dist文件&#xff0c;接下来再部署到linux试试吧 dist文件夹是干嘛的&#xff1f; 一个pnpn install 直接生成了两个dist文件夹&#xff0c;前端admin项目一个&#xf…

用Kimichat快速识别出图片中的表格保存到Excel

如果有一张图片格式的表格&#xff0c;想要快速复制到Excel表格中&#xff0c;那么一般要借助于OCR工具。之前试过不少在线OCR工具&#xff0c;识别效果差强人意。其实&#xff0c;kimichat就可以非常好的完成这个任务。 下面是一张研报中的表格&#xff0c;只能以图片形式保存…

153 Linux C++ 通讯架构实战8 ,日志打印实战,设置时区,main函数中顺序调整

日志打印实战 //日志的重要性&#xff1a;供日后运行维护人员去查看、定位和解决问题&#xff1b; //新文件&#xff1a;ngx_printf.cxx以及ngx_log.cxx。 //ngx_printf.cxx&#xff1a;放和打印格式相关的函数&#xff1b; //ngx_log.cxx&#xff1a;放和日志相关…

【计算机考研】数学难,到底难在哪里?看这一篇深度分析

数一和数二的难度系数都不在一个重量级&#xff01; 数一这货&#xff0c;容量真不是数二能比的&#xff01;除了高数、线代这些常规操作&#xff0c;还要啃概率论与数理统计这本大厚书&#xff0c;简直是让人头大&#xff01; 考研数学嘛&#xff0c;大家都知道&#xff0c;…

前端是什么

1.前端的概念 1.1 前端的定义 对于网站来说&#xff0c;通常是指网站的前台部分&#xff0c;包括网站的表现层和结构层&#xff08;通俗点就是用户可以看到的部分&#xff09;。总结一下&#xff0c;浏览器、APP、应用程序的界面展现和用户交互就是前端1.2 前端的作用 前端工程…

element跑马灯/轮播图,第一页隐藏左边按钮,最后一页隐藏右边按钮(vue 开箱即用)

图示&#xff1a; 第一步&#xff1a; <el-carousel :class"changeIndex0?leftBtnNone:changeIndeximgDataList.length-1? rightBtnNone:" height"546px" :autoplay"false" change"changeNext"><el-carousel-item v-for…

Android预置应用基础

目录 一、应用预置二、应用预置分区三、编译规则3.1 Android.mk3.2 Android.bp 一、应用预置 预置指智能终端设备出厂前&#xff0c;将文件预先安装到系统中。预置对象包括应用程序、可执行文件、so库&#xff08;.so 文件&#xff09;、jar 包等。 预置方式有以下两种&#…

交换机干道链路

干道链路是用于交换机之间或交换机与路由器之间互连的物理链路。干道链路传输的数据帧都必须打上Tag&#xff0c;便于设备识别数据帧所属的VLAN。因此一条干道链路可以承载多个VLAN的数据帧&#xff0c;如图1-1所示。 图1-1 干道链路功能示意图 干道链路可以透传VLAN。换言之&…

2023年后端面试总结

备注&#xff1a;这篇文章是我在2023年年初在自己的网站上写的&#xff0c;最近在迁移技术文章&#xff0c;我感觉这个也是和咱程序员相关&#xff0c;所以今天就决定把它迁移过来。 .......................................................................分割线..........…

代码随想录算法训练营 Day31 贪心算法1

Day31 贪心算法1 理论基础 贪心算法的本质&#xff1a;找到每个阶段的局部最优&#xff0c;从而去推导全局最优 贪心的两个极端&#xff1a;要么觉得特别简单&#xff0c;要么觉得特别难 贪心无套路 不像二叉树、递归&#xff0c;有固定模式 贪心题目的思考方式 做题的时候…

HarmonyOS实战开发-使用List组件实现导航与内容联动的效果。

1 卡片介绍 使用ArkTS语言&#xff0c;实现一个导航与内容二级联动的效果。 2 标题 二级联动&#xff08;ArkTS&#xff09; 3 介绍 本篇Codelab是主要介绍了如何基于List组件实现一个导航和内容的二级联动效果。样例主要包含以下功能&#xff1a; 切换左侧导航&#xff…

SpringMVC源码分析(七)--数据绑定工厂

1.数据绑定工厂的使用 数据绑定工厂能够创建数据绑定器,将数据绑定到对象中,比如说当接收到请求时,经过http协议解析后数据刚开始都是字符串,此时我们希望将这些属性进行类型转换,并为对象赋值,示例如下: 1)先创建两个实体类Student和Teacher @Getter @Setter @ToSt…

学习鸿蒙基础(10)

目录 一、轮播组件 Swiper 二、列表-List 1、简单的List 2、嵌套的List 三、Tabs容器组件 1、系统自带tabs案例 2、自定义导航栏&#xff1a; 一、轮播组件 Swiper Entry Component struct PageSwiper {State message: string Hello Worldprivate SwCon: SwiperControl…