UE5学习笔记22-武器瞄准和武器自动开火

0、一些疑问的记录

        1.UUserWidget类和AHUD类的区别。两者都是关于界面显示的类。

       实践:

        想让界面和用户有交互使用UUserWidget,如果不要交互只是显示使用AHUD类,例如使用UUserWidget类制作开始界面,游戏开始,游戏设置,自作人员等,使用AHUD类显示准心,角色血量,武器图标等。

        理论:

  • 绘制方式

    • AHUD:通过Canvas直接在屏幕上绘制2D元素(代码驱动)。
    • UUserWidget:通过UMG系统创建基于Widget的UI,支持拖拽式设计、复杂的布局和交互。
  • 适用场景

    • AHUD:适合需要低级别控制的简单HUD,如准星、生命值、计时器等。
    • UUserWidget:适合复杂的、交互式的UI,如菜单、装备栏、对话框、设置界面等。
  • 复杂度

    • AHUD:简单的绘制系统,但对复杂UI需求不太友好。
    • UUserWidget:高度可定制和交互式,适合更复杂和丰富的用户体验。

        2.UTexture和UTexture2D和UTexture3D的区别和何时使用

        实践:

  1. UTexture2D 使用场景

    • 材质贴图:如常规的模型纹理(Albedo、Normal、Metallic等)。
    • UI图像:如按钮、背景、图标等二维界面元素。
    • 常规图像数据:如2D背景图片、纹理集等。
  2. UTexture3D 使用场景

    • 体积效果:如烟雾、云朵、火焰等,需要体积数据的效果。
    • 体积存储:如3D噪声、光照体积等。
    • 特殊材质:一些高级渲染技术和效果(如3D映射、Voxel-based渲染)。
  3. UTexture

    • 通用纹理基类:通常不会直接使用,而是作为基类为具体的纹理类型提供基础功能。

         理论:

        UTexture是纹理的基类不能直接使用

        UTexture2D表示一个二维纹理(图像)用于给模型、材质和界面元素等应用图像数据,支持多级纹理细化(Mipmaps)、压缩格式(如DXT、BC5等),可用于渲染优化

        UTexture3D表示三维纹理(体积纹理),用于存储和处理三维的纹理数据,每个数据点(Texel)不仅有二维的xy,还包括z方向的深度值

        3.FTransform:

        包含了物体的位置旋转和缩放

FTransform MyTransform;
// 设置位置 MyTransform.SetTranslation(FVector(100.0f, 200.0f, 300.0f));
// 设置旋转 MyTransform.SetRotation(FQuat(FRotator(45.0f, 0.0f, 0.0f)));
// 设置缩放 MyTransform.SetScale3D(FVector(2.0f, 2.0f, 2.0f));
// 获取位置 FVector Position = MyTransform.GetTranslation();
// 获取旋转 FRotator Rotation = MyTransform.GetRotation().Rotator();
// 获取缩放 FVector Scale = MyTransform.GetScale3D();

        4. 具有调试作用的函数

        4.1DrawDebugLine画一条线

void UKismetSystemLibrary::DrawDebugLine(const UObject* WorldContextObject,    //当前世界FVector LineStart,                    //其实位置FVector LineEnd,                      //终点位置FLinearColor LineColor = FLinearColor(1.f, 0.f, 0.f, 1.f), //颜色float Duration = 0.f,                 //持续时间float Thickness = 0.f                 //粗细
);

        5.FindLookAtRotation函数返回的旋转默认返回X轴方向的旋转

一、完成了哪些

        完成武器自动开火,武器瞄准是在界面会有准心显示,跳跃射击等动作时准心改变大小,给角色添加被击中时的动画,将角色网格体胶囊被击改成角

色模型被击,

二、准心

        1.需要通过获得当前角色控制器(PlayerController)通过类APlayController::GetHUD()函数获得当前客户端的界面,函数返回一个类AHUD类的指针,定义一个类继承自AHUD类将返回的指针转到子类类型,通过DrwaHUD()函数和DrawTexture()函数绘制准心

        角色控制器可以通过角色类指针调用Controller获得,获得的是一个AController类,定义类继承APlayerController,类APlayerController继承自AController。类APlayController和AHUD是UE5中已经存在的类。

        2.创建新的C++类分别继承自APlayController和AHUD。将玩家控制器类命名为BlasterPlayerController界面类命名为ABasterHUD(并定义对应蓝图类)

         3.类AABasterHUD代码

中间有个点 

        头文件

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "ABasterHUD.generated.h"//如上图一共五个资产文件 所以结构体中有五个UTexture2D指针USTRUCT(BlueprintType)
struct FHUDPackage
{GENERATED_BODY()
public:class UTexture2D* CrosshairsCenter;UTexture2D* CrosshairsLeft;UTexture2D* CrosshairsRight;UTexture2D* CrosshairsTop;UTexture2D* CrosshairsBottom;float CrosshairSpreed;//当人物奔跑跳跃时,准心大小改变FLinearColor CrosshairsColor;
};/*** */
UCLASS()
class BLASTER_API AABasterHUD : public AHUD
{GENERATED_BODY()public:/* 该函数会在每一帧被调用 */virtual void DrawHUD() override;private:FHUDPackage HUDPackage;//绘画准心void DrawCrosshair(UTexture2D* Texture , FVector2D ViewPointCenter , FVector2D Spreed , FLinearColor CrosshairsColor);UPROPERTY(EditAnywhere)float CrosshairSpreadMax = 16.f; //准心扩展或缩小的速度
public:FORCEINLINE void SetHUDPackage(const FHUDPackage& Package) { HUDPackage = Package; }
};

        源文件

// Fill out your copyright notice in the Description page of Project Settings.#include "ABasterHUD.h"void AABasterHUD::DrawHUD()
{Super::DrawHUD();FVector2D ViewportSize;if (GEngine){/* 获得视口大小 */GEngine->GameViewport->GetViewportSize(ViewportSize);const FVector2D ViewportCenter(ViewportSize.X / 2.0, ViewportSize.Y / 2.0);float SpreadScaled =  CrosshairSpreadMax* HUDPackage.CrosshairSpreed;if (HUDPackage.CrosshairsCenter){FVector2D Spreed(0.f, 0.f);DrawCrosshair(HUDPackage.CrosshairsCenter, ViewportCenter, Spreed, HUDPackage.CrosshairsColor);}if (HUDPackage.CrosshairsLeft){FVector2D Spreed(-SpreadScaled, 0.f);DrawCrosshair(HUDPackage.CrosshairsLeft, ViewportCenter , Spreed, HUDPackage.CrosshairsColor);}if (HUDPackage.CrosshairsRight){FVector2D Spreed(SpreadScaled, 0.f);DrawCrosshair(HUDPackage.CrosshairsRight, ViewportCenter , Spreed, HUDPackage.CrosshairsColor);}if (HUDPackage.CrosshairsTop){FVector2D Spreed(0.f , -SpreadScaled);DrawCrosshair(HUDPackage.CrosshairsTop, ViewportCenter , Spreed, HUDPackage.CrosshairsColor);}if (HUDPackage.CrosshairsBottom){FVector2D Spreed(0.f, SpreadScaled);DrawCrosshair(HUDPackage.CrosshairsBottom, ViewportCenter , Spreed, HUDPackage.CrosshairsColor);}}
}void AABasterHUD::DrawCrosshair(UTexture2D* Texture, FVector2D ViewPointCenter , FVector2D Spreed , FLinearColor CrosshairsColor)
{const float TextureWidth = Texture->GetSizeX();const float TextureHigh = Texture->GetSizeY();const FVector2D TexturePoint(ViewPointCenter.X - (TextureWidth / 2.0) + Spreed.X,ViewPointCenter.Y - (TextureHigh / 2.0) + Spreed.Y);/**void DrawTexture(UTexture* Texture,              // 1. 纹理对象float ScreenX,                  // 2. 屏幕上绘制位置的 X 坐标float ScreenY,                  // 3. 屏幕上绘制位置的 Y 坐标float ScreenW,                  // 4. 纹理的宽度(缩放后的)float ScreenH,                  // 5. 纹理的高度(缩放后的)float CoordinateX = 0.f,        // 6. 纹理UV坐标的X起始点float CoordinateY = 0.f,        // 7. 纹理UV坐标的Y起始点float CoordinateW = 1.f,        // 8. 纹理UV的宽度float CoordinateH = 1.f,        // 9. 纹理UV的高度FLinearColor TintColor = FLinearColor::White,  // 10. 颜色渲染/染色 (可以用来控制透明度)EBlendMode BlendMode = SE_BLEND_Translucent,   // 11. 混合模式 (用于控制如何混合纹理与背景)float Scale = 1.f,              // 12. 缩放比例bool bScalePosition = false,    // 13. 是否同时缩放位置float Rotation = 0.f,           // 14. 纹理旋转角度FVector2D RotPivot = FVector2D(0.5f, 0.5f)     // 15. 旋转中心点 (以纹理为中心默认旋转));*/DrawTexture(Texture,TexturePoint.X,TexturePoint.Y,TextureWidth,TextureHigh,0.f,0.f,1.f,1.f,CrosshairsColor);
}

         4.不同的武器可能会有不同的准心,所以在武器类中定义(Weapon.h)

	UPROPERTY(EditAnywhere, Category = Crosshairs)class UTexture2D* CrosshairsCenter; //静态纹理类UPROPERTY(EditAnywhere, Category = Crosshairs)class UTexture2D* CrosshairsLeft; //静态纹理类UPROPERTY(EditAnywhere, Category = Crosshairs)class UTexture2D* CrosshairsRight; //静态纹理类UPROPERTY(EditAnywhere, Category = Crosshairs)class UTexture2D* CrosshairsTop; //静态纹理类UPROPERTY(EditAnywhere, Category = Crosshairs)class UTexture2D* CrosshairsBottom; //静态纹理类

        5.编译后,打开对应的武器的蓝图,设置如下 

        6.纹理资产设置,想让纹理显示在界面上,所以是一个2D类型的纹理需要确保纹理是2D类型

         7.在游戏模式蓝图中设置对应属性(BP_xxx都是自己定义的蓝图类)

        8. 设置准心纹理

        头文件

        在战斗组件类中定义(准心会放大缩小,所以需要使用插值,函数会有时间参数(DeltaTime))

/* 准心 */
void SetHUDCrosshairs(float DeltaTime); //每帧调用
/* 准心 *//**
* HUD and Crosshairs
*/float CrosshairVelocityFactor; //行走速度
float CrosshairInAirFactor;    //是否在空中,跳跃
float CrosshairAimFactor;      //瞄准
float CrosshairShootingFactor; //蹲下
FHUDPackage HUDPackage;class ABlasterPlayerController* Controller; //可以通过这个类去获得HUD
class AABasterHUD* HUD;

         源文件

void UCombatComponent::SetHUDCrosshairs(float DeltaTime)
{if (Character == nullptr || Character->Controller == nullptr) return;Controller = Controller == nullptr ? Cast<ABlasterPlayerController>(Character->Controller) : Controller;if (Controller){HUD = HUD == nullptr ? Cast<AABasterHUD>(Controller->GetHUD()) : HUD;if (HUD){if (EquippedWeapon){HUDPackage.CrosshairsCenter = EquippedWeapon->CrosshairsCenter;HUDPackage.CrosshairsLeft = EquippedWeapon->CrosshairsLeft;HUDPackage.CrosshairsRight = EquippedWeapon->CrosshairsRight;HUDPackage.CrosshairsBottom = EquippedWeapon->CrosshairsBottom;HUDPackage.CrosshairsTop = EquippedWeapon->CrosshairsTop;}else{HUDPackage.CrosshairsCenter = nullptr;HUDPackage.CrosshairsLeft = nullptr;HUDPackage.CrosshairsRight = nullptr;HUDPackage.CrosshairsBottom = nullptr;HUDPackage.CrosshairsTop = nullptr;}// 计算准心扩展/缩小// [0 , 600] -> [0 , 1]FVector2D WalkSpeedRange(0.f, Character->GetCharacterMovement()->MaxWalkSpeed);FVector2D VeclocityMultiplierRange(0.f, 1.f);FVector Velocity = Character->GetVelocity();Velocity.Z = 0.f;/*float GetMappedRangeValueClamped(const TInterval<float>&InputRange,  // 输入范围const TInterval<float>&OutputRange, // 输出范围float Value                          // 输入的数值);*//* 函数返回的值是Velocity.Size()在映射中的值 */CrosshairVelocityFactor = FMath::GetMappedRangeValueClamped(WalkSpeedRange, VeclocityMultiplierRange, Velocity.Size());if (Character->GetCharacterMovement()->IsFalling()){CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 2.25f, DeltaTime, 2.25f);}else{CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 0.f, DeltaTime, 30.f);}if (bAiming){CrosshairAimFactor = FMath::FInterpTo(CrosshairAimFactor, 0.58f, DeltaTime, 30.f);}else{CrosshairAimFactor = FMath::FInterpTo(CrosshairAimFactor, 0.f, DeltaTime, 30.f);}CrosshairShootingFactor = FMath::FInterpTo(CrosshairShootingFactor, 0.f, DeltaTime, 40.f);HUDPackage.CrosshairSpreed =0.5f +CrosshairVelocityFactor +CrosshairInAirFactor -CrosshairAimFactor +CrosshairShootingFactor;HUD->SetHUDPackage(HUDPackage);}}
}void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{Super::TickComponent(DeltaTime, TickType, ThisTickFunction);SetHUDCrosshairs(DeltaTime);
}

        9.将武器发射子弹的方向和瞄准方向保证统一,并且只想在本地客户端上让右手骨骼和目标在同一个方向。

        9.1在角色动画类中定义右手的旋转,让右手旋转到瞄准的目标的方向,代码如下

        头文件

UPROPERTY(BlueprintReadOnly, Category = Character, meta = (AllowPrivateAccess = "true"))/** 蓝图只读 类型是Character 允许私有访问 */
FRotator RightHandRotation;UPROPERTY(BlueprintReadOnly, Category = Character, meta = (AllowPrivateAccess = "true"))/** 蓝图只读 类型是Character 允许私有访问 */
bool bLocallyControlled;

        源文件 , 注释是测试代码,第一个if判断当前是否有武器,武器指针存在,武器网格体存在,角色网格体存在,第二个if判断当前角色是否是本地控制(是否是当前客户端),不想在代理商显示

void UBlasterAnimInstance::NativeUpdateAnimation(float DeltaTime)
{Super::NativeUpdateAnimation(DeltaTime);if (bWeaponEquipped && EquippedWeapon && EquippedWeapon->GetWeaponMesh() && BlasterCharacter->GetMesh()){if (BlasterCharacter->IsLocallyControlled()){bLocallyControlled = true;FTransform RightHandTransform = EquippedWeapon->GetWeaponMesh()->GetSocketTransform(FName("Hand_R"), ERelativeTransformSpace::RTS_World);//让当前对象从当前位置朝向目标位置所需的旋转//FindLookAtRotation函数返回的旋转默认返回X轴方向的旋转FRotator LookAtRotation = UKismetMathLibrary::FindLookAtRotation(RightHandTransform.GetLocation(), RightHandTransform.GetLocation() + (RightHandTransform.GetLocation() - BlasterCharacter->GetHitTarget()));RightHandRotation = FMath::RInterpTo(RightHandRotation, LookAtRotation, DeltaTime, 30.f);//RightHandRotation = UKismetMathLibrary::FindLookAtRotation(RightHandTransform.GetLocation(), RightHandTransform.GetLocation() + (RightHandTransform.GetLocation() - BlasterCharacter->GetHitTarget()));}//FTransform MuzzleTipTransform = EquippedWeapon->GetWeaponMesh()->GetSocketTransform(FName("MuzzleFlash"), ERelativeTransformSpace::RTS_World);//FVector MuzzleX(FRotationMatrix(MuzzleTipTransform.GetRotation().Rotator()).GetUnitAxis(EAxis::X));//DrawDebugLine(GetWorld(), MuzzleTipTransform.GetLocation(), MuzzleTipTransform.GetLocation() + MuzzleX * 1000.f, FColor::Red);////DrawDebugLine(GetWorld(), MuzzleTipTransform.GetLocation(), BlasterCharacter->GetHitTarget(), FColor::Black);}
}

        动画蓝图

        将平移(Transform),缩放(Scale) ,透明度(Alpha)去掉不显示(可以根据自己需要)

        将动画/UseCachePoses节点直接连接到该节点上会有如图的效果,中间会自动生成一个节点,另一边的连线连接到正确的位置同样也有一个节点

         最后整体流程

        10. 装备武器时的视场角的缩放

        角色类偷头文件定义 (获得相机组件类指针的函数)

FORCEINLINE UCameraComponent* GetFollowCamera() const { return FollowCamera; };

        武器类头文件定义

	/***	瞄准时武器需要放大多少倍*/UPROPERTY(EditAnywhere)float ZoomedFOV = 30.f; //视场角的缩放UPROPERTY(EditAnywhere)float ZoomInterpSpeed = 20.f; // 缩放的速度

        战斗组件类中头文件

	/***	瞄准的视场角*//* 默认的视场角 没有瞄准 */float DefaultFOV;UPROPERTY(EditAnywhere, Category = Combat)float ZommedFOV = 30.f;float CurrentFOV;UPROPERTY(EditAnywhere, Category = Combat)float ZoomInterpSpeed = 20.f; // 缩放的速度void InterpFOV(float DeltaTime);FORCEINLINE float GetZoomedFOV() const { return ZoomedFOV; };
FORCEINLINE float GetZoomInterpSpeed() const { return ZoomInterpSpeed; };

        战斗组件类中源文件

void UCombatComponent::InterpFOV(float DeltaTime)
{if (EquippedWeapon == nullptr) return;if (bAiming){CurrentFOV = FMath::FInterpTo(CurrentFOV, EquippedWeapon->GetZoomedFOV(), DeltaTime, EquippedWeapon->GetZoomInterpSpeed());}else{CurrentFOV = FMath::FInterpTo(CurrentFOV, DefaultFOV, DeltaTime, ZoomInterpSpeed);}if (Character && Character->GetFollowCamera()){Character->GetFollowCamera()->SetFieldOfView(CurrentFOV);}
}void UCombatComponent::BeginPlay()
{Super::BeginPlay();if (Character){Character->GetCharacterMovement()->MaxWalkSpeed = BaseWalkSpeed;if (Character->GetFollowCamera()){DefaultFOV = Character->GetFollowCamera()->FieldOfView; //获得最开始的视场角CurrentFOV = DefaultFOV;//当前视角初始化}}
}void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{Super::TickComponent(DeltaTime, TickType, ThisTickFunction);if (Character && Character->IsLocallyControlled()){InterpFOV(DeltaTime);}
}

三、更改准心颜色,在瞄准人物时将准星变成红色

        0.没有更改准心颜色的功能将上面的代码删掉Color相关即可

        1.创建UE接口类,角色类继承该接口类

        2. 接口类使用

        2.1具体使用查看UE5官方文档,英文版使用浏览器的自动翻译Unreal Engine 中的接口 |Unreal Engine 5.4 文档 |Epic 开发者社区 (epicgames.com)icon-default.png?t=O83Ahttps://dev.epicgames.com/documentation/en-us/unreal-engine/interfaces-in-unreal-engine        2.2当前使用说明

        角色类继承了public IInteractWithCrosshairsInterface,I开头的接口类

        2.3战斗成分类中在Tick函数中 TraceHitResult时检测到的目标的结果类型时FHitResult

if (TraceHitResult.GetActor() && TraceHitResult.GetActor()->Implements<UInteractWithCrosshairsInterface>())
{HUDPackage.CrosshairsColor = FColor::Red;
}
else
{HUDPackage.CrosshairsColor = FColor::White;
}

        2.4若在测试时碰到角色在移动时摄像机贴在了当前角色身上时,可能是因为摄像机碰到了其他角色,在角色C++类的构造中添加以下代码,取消角色和摄像机的碰撞,若还会碰撞,请查看角色类蓝图中摄像机的碰撞在哪里打了√

GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);

四、当人物靠在墙边时,摄像头会紧贴在角色上,看不见前方的东西

        1.判断角色和摄像机的距离是否小于特定的值,如果小于将角色网格体隐藏,不小于显示

角色类头文件

	void HideCameraIfCharactorClose();UPROPERTY(EditAnywhere)float CameraThreadhold = 200.f;

角色类源文件

void ABlasterCharacter::HideCameraIfCharactorClose()
{if (!IsLocallyControlled()) return;if ((FollowCamera->GetComponentLocation() - GetActorLocation()).Size() < CameraThreadhold){GetMesh()->SetVisibility(false);if (Combat && Combat->EquippedWeapon && Combat->EquippedWeapon->GetWeaponMesh()){Combat->EquippedWeapon->GetWeaponMesh()->bOwnerNoSee = true;}}else{GetMesh()->SetVisibility(true);if (Combat && Combat->EquippedWeapon && Combat->EquippedWeapon->GetWeaponMesh()){Combat->EquippedWeapon->GetWeaponMesh()->bOwnerNoSee = false;}}
}

五、自定义碰撞频道

        0.我将角色骨骼设置成新的碰撞,在子弹类中定义了该类型的碰撞,这样在子弹命中人物时会判定在骨骼体上而不是网格体。之后会判断命中的身体部位是哪

        1.项目设置中设置如下没在引擎-碰撞中新建Object通道如下图

         2.在项目名.h的文件中定义,例如我的项目是Blaster

        Blaster.h

#define ECC_SkeletalMesh ECollisionChannel::ECC_GameTraceChannel1

        3.在会发生碰撞的物体中将设置碰撞的代码如下

CollisionBox->SetCollisionResponseToChannel(ECC_SkeletalMesh, ECollisionResponse::ECR_Block);

        4.设置碰撞类型,在对应蓝图中将怕碰撞预设的对象类型设置成1中的新建的对应的名字

六、 复制运动的通知函数

        1.问题描述

        当控制角色旋转是在其他客户端上会有轻微抖动问题

        2.原因

        角色蓝图中调用了RotateRootBone节点旋转骨头,在自己的客户端和服务器上,该旋转骨头会每帧调用,在其他客户端上,我们的角色在其他客户端上是代理角色,并不会每帧调用旋转骨骼的节点,所以会有抖动产生

        3.解决

        重写  virtual void OnRep_ReplicatedMovement() override;函数这是一个AActor类中关于运动的回调函数,在运动时会执行该函数

        角色类头文件

/* 解决当前旋转骨骼不是每帧调用时会在其他客户端存在抖动问题 */
void SimProxiesTurn();
/* 解决当前旋转骨骼不是每帧调用时会在其他客户端存在抖动问题 *///在AActor.h中定义,当角色移动是会调用当前回调
virtual void OnRep_ReplicatedMovement() override;蓝图中进行判断用
FORCEINLINE bool ShouldRotateRootBone() const { return bRotateRootBone; };bool bRotateRootBone;//是否进行了骨骼旋转float TimeSinceLastMovementReplication;//多长时间没有进行旋转

        角色类源文件

void ABlasterCharacter::Tick(float DeltaTime)
{Super::Tick(DeltaTime);TimeSinceLastMovementReplication += DeltaTime;//当一段时间没有移动时调用回调函数if (TimeSinceLastMovementReplication > 0.25f){OnRep_ReplicatedMovement();}CalculateA0_Pitch();
}void ABlasterCharacter::OnRep_ReplicatedMovement()
{Super::OnRep_ReplicatedMovement();//if (GetLocalRole() == ENetRole::ROLE_SimulatedProxy)//{//	SimProxiesTurn();//}SimProxiesTurn();TimeSinceLastMovementReplication = 0.f;
}void ABlasterCharacter::SimProxiesTurn()
{//处理模拟界面的转弯if (Combat == nullptr || Combat->EquippedWeapon == nullptr) return;bRotateRootBone = false;float Speed = CalculateSpeed();if (Speed > 0.f){TurningInPlace = ETurningInPlace::ETIP_NotTurning;return;}//CalculateA0_Pitch();ProxyRotationLastFrame = ProxyRotation;ProxyRotation = GetActorRotation();//计算两个角度的最小旋转角度变化在 [-180, 180] 范围内ProxyYaw = UKismetMathLibrary::NormalizedDeltaRotator(ProxyRotation, ProxyRotationLastFrame).Yaw;if (FMath::Abs(ProxyYaw) > TurnThreshold){if (ProxyYaw > TurnThreshold){TurningInPlace = ETurningInPlace::ETIP_Right;}else if (ProxyYaw < -TurnThreshold){TurningInPlace = ETurningInPlace::ETIP_Left;}else{TurningInPlace = ETurningInPlace::ETIP_NotTurning;}return;}TurningInPlace = ETurningInPlace::ETIP_NotTurning;
}float ABlasterCharacter::CalculateSpeed()
{/* 只想获得平面上xy的速度的向量,将z方向的速度置为0 */FVector Velocity = GetVelocity();Velocity.Z = 0.f;return Velocity.Size();
}

         4.蓝图中获得是否旋转骨头的bool类型变量,在动画蓝图中判断如果旋转了骨头则直接旋转没有旋转骨头就直接角色旋转

        在判断是否具有本地控制权限(FullBody就是上面的流程(使用了cache poses))

七、自动射击 

        1.使用了FTimerManager类让武器间隔一段时后再次发射子弹

         战斗类头文件

	/***	自动开火*/FTimerHandle FireTimer; //定时器类bool bCanFire = true;void StartFireTimer();void FireTimerFinished();

        战斗类源文件

void UCombatComponent::StartFireTimer()
{if (EquippedWeapon == nullptr || Character == nullptr) return;Character->GetWorldTimerManager().SetTimer(FireTimer,this,&UCombatComponent::FireTimerFinished,EquippedWeapon->FireDelay);
}void UCombatComponent::FireTimerFinished()
{if (EquippedWeapon == nullptr) return;bCanFire = true;if (bFireButtonPressed && EquippedWeapon->bAutomatic){Fire();}
}

        武器类头文件

	/***	自动开火*/UPROPERTY(EditAnywhere, Category = Combat)float FireDelay = 0.15f; //开火速率UPROPERTY(EditAnywhere, Category = Combat)bool bAutomatic = true; //武器是否自动

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

计算机人工智能前沿进展-大语言模型方向-2024-09-17

计算机人工智能前沿进展-大语言模型方向-2024-09-17 1. Large Language Models in Biomedical and Health Informatics: A Review with Bibliometric Analysis H Yu, L Fan, L Li, J Zhou, Z Ma, L Xian, W Hua, S He… - Journal of Healthcare …, 2024 生物医学和健康信息…

部分动态铜皮的孤岛无法删除。报错

(SPMHCI-1): Cannot break shape into fragments. 网上寻找了很多答案&#xff0c;都不太理想&#xff0c;不是我想要的方法。 终于功夫不负有心人&#xff0c;在Cadence官方论坛找到了蛛丝马迹。 Breaking Static shape into fragments - PCB Design - PCB Design & IC …

深入解析Transformer原理

在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;Transformer架构的出现无疑是一个里程碑式的进展。从Google的BERT到OpenAI的GPT系列&#xff0c;Transformer已经成为许多前沿AI模型的核心。今天&#xff0c;我们就来深入探讨Transformer的原理&#xff0c;帮助你更…

优惠充值话费api对接如何选择对接平台?

优惠充值话费接口通常由电信运营商、第三方支付平台或专业的充值服务提供商提供。这些平台通过API接口允许开发者将话费充值功能集成到应用程序或网站中。 选择哪个平台比较好&#xff0c;取决于以下几个因素&#xff1a; 覆盖范围&#xff1a;选择能够覆盖你需要服务的地区和…

深度学习-生成式检索-论文速读-2024-09-14

深度学习-生成式检索-论文速读-2024-09-14 前言: 生成式检索&#xff08;Generative Retrieval&#xff0c; GR&#xff09;是一种结合了生成模型和检索系统的人工智能技术方法。这种方法在处理信息检索任务时&#xff0c;不仅依赖于已有数据的检索&#xff0c;还能生成新的、…

c++基类和派生类对象的赋值转换——赋值兼容规则

1.引出 如下场景&#xff1a; 由于b是double类型&#xff0c;所以赋值给int类型的引用前&#xff0c;要先进行隐式类型转换&#xff0c;这中间会生成临时对象&#xff0c;类是对象具有常性&#xff0c;所以int&之前应该加上const。 但是下面的场景&#xff1a; 没有出现报…

Python3网络爬虫开发实战(16)分布式爬虫(第一版)

文章目录 一、分布式爬虫原理1.1 分布式爬虫架构1.2 维护爬取队列1.3 怎样来去重1.4 防止中断1.5 架构实现 二、Scrapy-Redis 源码解析2.1 获取源码2.2 爬取队列2.3 去重过滤2.4 调度器 三、Scrapy 分布式实现3.1 准备工作3.2 搭建 Redis 服务器3.3 部署代理池和 Cookies 池3.4…

python画图|中秋到了,尝试画个月亮(球体画法)

学习了一段时间的画图&#xff0c;已经掌握了一些3D图的画法&#xff0c;部分链接如下&#xff1a; python画图|极坐标下的3D surface-CSDN博客 python画图|3D参数化图形输出-CSDN博客 我们今天尝试一下月亮的画法。 【1】官网教程 首先还是到达官网教程学习&#xff1a; …

# 深度学习笔记(6)Hugginface -Transformer

深度学习笔记&#xff08;6&#xff09;Hugginface -Transformer 文章目录 深度学习笔记&#xff08;6&#xff09;Hugginface -Transformer一、工具包二、 Tokenizer三、 模型加载四、 输出五&#xff0c;padding的作用5.1 attention_mask5.2 不同padding方法 六&#xff0c;数…

基于yolov8+lprnet的中文车牌识别系统python源码+pytorch模型+精美GUI界面

【算法介绍】 基于YOLOv8和LPRNet的中文车牌识别系统是一种高效且准确的解决方案&#xff0c;结合了目标检测与字符识别的先进技术。YOLOv8作为最新的实时目标检测算法&#xff0c;以其高速度和精确度著称&#xff0c;能够迅速在图像或视频中定位车牌位置。LPRNet则是一种专为…

反向传播(Back Propagation,简称BP)

反向传播算法是用于训练神经网络的核心算法之一&#xff0c;它通过计算损失函数&#xff08;如均方误差或交叉熵&#xff09;相对于每个权重参数的梯度&#xff0c;来优化神经网络的权重。 1.前向传播&#xff08;Forward Propagation&#xff09; 步骤 输入层&#xff1a;接…

孙怡带你深度学习(2)--PyTorch框架认识

文章目录 PyTorch框架认识1. Tensor张量定义与特性创建方式 2. 下载数据集下载测试展现下载内容 3. 创建DataLoader&#xff08;数据加载器&#xff09;4. 选择处理器5. 神经网络模型构建模型 6. 训练数据训练集数据测试集数据 7. 提高模型学习率 总结 PyTorch框架认识 PyTorc…

计算机人工智能前沿进展-大语言模型方向-2024-09-13

计算机人工智能前沿进展-大语言模型方向-2024-09-13 1. OneEdit: A Neural-Symbolic Collaboratively Knowledge Editing System Authors: Ningyu Zhang, Zekun Xi, Yujie Luo, Peng Wang, Bozhong Tian, Yunzhi Yao, Jintian Zhang, Shumin Deng, Mengshu Sun, Lei Liang, Z…

基于51单片机的直流数字电流表proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1adZbhgOBvvg0KsCO6_ZiAw 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

高级I/O知识分享【5种IO模型 || select || poll】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;Linux_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;前文 2&a…

在Unity UI中实现UILineRenderer组件绘制线条

背景介绍 在Unity的UI系统中&#xff0c;绘制线条并不像在3D世界中那样直观(使用Unity自带的LineRender组件在UI中连线并不方便,它在三维中更合适)。没有内置的工具来处理这种需求。如果你希望在UI元素之间绘制连接线&#xff08;例如在UI上连接不同的图标或控件&#xff09;&a…

20240918 每日AI必读资讯

o1突发内幕曝光&#xff1f;谷歌8月论文已揭示原理&#xff0c;大模型光有软件不存在护城河 - 谷歌DeepMind一篇发表在8月的论文&#xff0c;揭示原理和o1的工作方式几乎一致 - 谷歌DeepMind这篇论文的题目是&#xff1a;优化LLM测试时计算比扩大模型参数规模更高效。 - Op…

828华为云征文 | 云服务器Flexus X实例:one-api 部署,支持众多大模型

目录 一、one-api 介绍 二、部署 one-api 2.1 拉取镜像 2.2 部署 one-api 三、运行 one-api 3.1 添加规则 3.2 运行 one-api 四、添加大模型 API 4.1 添加大模型 API 五、总结 本文通过 Flexus云服务器X实例 部署 one-api。Flexus云服务器X实例是新一代面向中小企业…

拥控算法BBR入门1

拥塞控制算法只与本地有关 一个TCP会话使用的拥塞控制算法只与本地有关。 两个TCP系统可以在TCP会话的两端使用不同的拥塞控制算法 Bottleneck Bandwidth and Round-trip time Bottleneck 瓶颈 BBR models the network to send as fast as the available bandwidth and is 2…

Java | Leetcode Java题解之第414题第三大的数

题目&#xff1a; 题解&#xff1a; class Solution {public int thirdMax(int[] nums) {Integer a null, b null, c null;for (int num : nums) {if (a null || num > a) {c b;b a;a num;} else if (a > num && (b null || num > b)) {c b;b num;…