当前位置: 首页 > news >正文

UEC++ 虚幻5第三人称射击游戏(一)

UEC++ 虚幻5第三人称射击游戏(一)

  • 创建一个空白的C++工程

人物角色基本移动

  • 创建一个Character类
  • 添加一些虚幻商城中的基础动画
    在这里插入图片描述
  • 给角色类添加Camera与SPringArm组件
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "SpringArm")class USpringArmComponent* SpringArm;UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")class UCameraComponent* Camera;// Sets default values
AMyCharacter::AMyCharacter()
{// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));SpringArm->SetupAttachment(GetRootComponent());SpringArm->TargetArmLength = 400.f;SpringArm->bUsePawnControlRotation = true;Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));Camera->SetupAttachment(SpringArm);Camera->bUsePawnControlRotation = false;
}

角色基本移动增强输入系统MyCharacter.h

  • 角色基本移动增强输入系统
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "MyCharacter.generated.h"UCLASS()
class SHOOTGAME_API AMyCharacter : public ACharacter
{GENERATED_BODY()public:// Sets default values for this character's propertiesAMyCharacter();UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputMappingContext* DefaultMappingContext;UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputAction* MoveAction;UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputAction* LookAction;UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputAction* CrouchAction;UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "SpringArm")class USpringArmComponent* SpringArm;UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")class UCameraComponent* Camera;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;void CharacterMove(const FInputActionValue& Value);void CharacterLook(const FInputActionValue& Value);void BeginCrouch();void EndCtouch();public:	// Called every framevirtual void Tick(float DeltaTime) override;// Called to bind functionality to inputvirtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;};

角色基本移动增强输入系统MyCharacter.cpp

  • GetMovementComponent()->GetNavAgentPropertiesRef().bCanCrouch = true;:允许角色进行蹲伏(crouch)动作,并且能够影响导航代理(Navigation Agent)的行为
    • GetMovementComponent():获取角色的移动组件
    • GetNavAgentPropertiesRef():获取导航代理属性的引用。这些属性用于定义角色如何与导航系统交互,例如高度、半径、最大爬坡角度等。
    • .bCanCrouch = true;:设置导航代理的一个布尔属性,表示该角色可以进行蹲伏,并且在寻路过程中应当考虑其能通过更低矮的空间。这意味着在自动寻路时,引擎会考虑到角色在蹲伏状态下可以通过的高度限制区域。
  • Crouch与OnCrouch:虚幻自带的蹲伏函数
// Fill out your copyright notice in the Description page of Project Settings.#include "MyCharacter.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/PawnMovementComponent.h"
#include "GameFramework/CharacterMovementComponent.h"// Sets default values
AMyCharacter::AMyCharacter()
{// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;//允许角色进行蹲伏(crouch)动作,并且能够影响导航代理(Navigation Agent)的行为GetMovementComponent()->GetNavAgentPropertiesRef().bCanCrouch = true;//自动转向GetCharacterMovement()->bOrientRotationToMovement = true;//对Character的Pawn的朝向进行硬编码bUseControllerRotationPitch = false;bUseControllerRotationYaw = false;bUseControllerRotationRoll = false;SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));SpringArm->SetupAttachment(GetRootComponent());SpringArm->TargetArmLength = 400.f;SpringArm->bUsePawnControlRotation = true;Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));Camera->SetupAttachment(SpringArm);Camera->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(DefaultMappingContext, 0);}}
}void AMyCharacter::CharacterMove(const FInputActionValue& Value)
{FVector2D MovementVector = Value.Get<FVector2D>();if (Controller){FRotator Rotation = Controller->GetControlRotation();FRotator YawRotation = FRotator(0., Rotation.Yaw, 0.);FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);AddMovementInput(ForwardDirection, MovementVector.Y);AddMovementInput(RightDirection, MovementVector.X);}
}void AMyCharacter::CharacterLook(const FInputActionValue& Value)
{FVector2D LookVector = Value.Get<FVector2D>();if (Controller){AddControllerPitchInput(LookVector.Y);AddControllerYawInput(LookVector.X);}
}void AMyCharacter::BeginCrouch()
{Crouch();
}void AMyCharacter::EndCtouch()
{UnCrouch();
}// 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* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);if (EnhancedInputComponent){EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::CharacterMove);EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyCharacter::CharacterLook);EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Triggered, this, &AMyCharacter::BeginCrouch);EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Completed, this, &AMyCharacter::EndCtouch);}}

创建动画蓝图与混合空间

  • 创建一个混合空间1D
    在这里插入图片描述
  • 创建一个动画蓝图,将这个混合空间链接上去
    在这里插入图片描述
    在这里插入图片描述

引入第三人称射击模型

  • 我们新建一个Character蓝图作为第三人称射击测试角色
  • 在虚幻商城里面添加我们需要的射击动画
    在这里插入图片描述
  • 打开这个内容包的动画蓝图
    在这里插入图片描述
  • 我们只需要移动所以跳跃那些都可以删除
    在这里插入图片描述
  • 然后使用这个包自己的动画蓝图与骨骼资产,它的移动全是在动画蓝图中实现的,所以角色蓝图就不用实现移动,用我们创建的角色去使用这个动画蓝图与骨骼资产,然后设置蹲伏的逻辑
    在这里插入图片描述
    在这里插入图片描述

人物动画IK绑定

  • 首先在虚幻商城下载一个自己喜欢的模型添加到项目资产里面
    在这里插入图片描述
  • 添加IK绑定
    在这里插入图片描述
  • 选择我们第三人称射击动作那个骨骼,Pelvis设置为根组件
    在这里插入图片描述
  • 然后添加骨骼链条
    在这里插入图片描述

人物动画重定向

  • 设置自己角色的IK绑定
    在这里插入图片描述
  • 创建重定向器,源是小白人
    在这里插入图片描述
    在这里插入图片描述
  • 导出重定向的动画
    在这里插入图片描述
  • 将动画蓝图给到角色蓝图
    在这里插入图片描述

创建武器类

  • 导入武器模型
  • 创建武器类
    在这里插入图片描述
    在这里插入图片描述
  • 创建武器类的蓝图添加模型上去
    在这里插入图片描述
  • 在角色蓝图中添加一个手持武器的插槽
    在这里插入图片描述
  • 在角色蓝图中,将武器附加到角色手上
    在这里插入图片描述
  • 调整好武器的位置参数
    在这里插入图片描述
  • 运行结果
    在这里插入图片描述

创建武器追踪线

  • Weapon类中创建一个开火的函数,描绘一些射击的追踪线
    在这里插入图片描述
    在这里插入图片描述

  • LineTraceSingleByChannel:使用特定的通道追踪光线并返回第一个阻塞命中TRUE(如果发现了阻塞命中)
    在这里插入图片描述

  • 逻辑源码

void AWeapon::Fire()
{AActor* MyOwner = GetOwner();if (MyOwner){FVector EyeLocation;FRotator EyeRotation;//返回角色视角MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotation);FVector TraceEnd = EyeLocation + (EyeRotation.Vector() * 10000);FCollisionQueryParams QueryParams;QueryParams.AddIgnoredActor(MyOwner);QueryParams.AddIgnoredActor(this);QueryParams.bTraceComplex = true;FHitResult Hit;//使用特定的通道追踪光线并返回第一个阻塞命中TRUE(如果发现了阻塞命中)if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, ECC_Visibility, QueryParams)){//设置受阻,造成伤害结果}DrawDebugLine(GetWorld(), EyeLocation, TraceEnd,FColor::Red,false,1.0f,0,1.0f);}
}

调整追踪线位置

  • 我们需要将追踪线变为我们摄像机眼睛看见的位置,我们需要重写APawn类中的GetPawnViewLocation函数
    在这里插入图片描述
    在这里插入图片描述
  • 在角色蓝图中实例化对象Weapon类,进行鼠标左键点击测试绘画的线是否是从摄像机眼睛处发出
    在这里插入图片描述
  • 运行结果
    请添加图片描述

创建伤害效果

  • 补全Fire函数中的伤害处理逻辑
  • 首先添加一个UDamageType模版变量,来存储造成伤害的类
    在这里插入图片描述
  • 补全逻辑
    在这里插入图片描述
  • Fire函数
void AWeapon::Fire()
{AActor* MyOwner = GetOwner();if (MyOwner){FVector EyeLocation;FRotator EyeRotation;//返回角色视角MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotation);FVector TraceEnd = EyeLocation + (EyeRotation.Vector() * 10000);FCollisionQueryParams QueryParams;QueryParams.AddIgnoredActor(MyOwner);QueryParams.AddIgnoredActor(this);QueryParams.bTraceComplex = true;FHitResult Hit;FVector ShotDirection = EyeRotation.Vector();//使用特定的通道追踪光线并返回第一个阻塞命中TRUE(如果发现了阻塞命中)if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, ECC_Visibility, QueryParams)){//设置受阻,造成伤害结果AActor* HitActor = Hit.GetActor();UGameplayStatics::ApplyPointDamage(HitActor, 10.f, ShotDirection, Hit, MyOwner->GetInstigatorController(),this, DamageType);}DrawDebugLine(GetWorld(), EyeLocation, TraceEnd,FColor::Red,false,1.0f,0,1.0f);}
}
  • 运行结果

创建射击特效

  • 导入粒子资源
  • 添加两个粒子系统,与一个附加到骨骼的变量
    在这里插入图片描述
  • 默认骨骼名
    在这里插入图片描述
  • Fire函数中添加特效与位置逻辑,一个是开火的特效粒子,一个是子弹打击到目标身上的掉血粒子
    在这里插入图片描述
  • 将特效添加到武器蓝图中
    在这里插入图片描述
  • 将武器骨骼插槽的名字改为我们设置的名字
    在这里插入图片描述
  • 微调一下摄像机方便测试
    在这里插入图片描述
  • 运行结果
    请添加图片描述

Weapon.h

// Fill out your copyright notice in the Description page of Project Settings.
#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Weapon.generated.h"UCLASS()
class SHOOTGAME_API AWeapon : public AActor
{GENERATED_BODY()public:	// Sets default values for this actor's propertiesAWeapon();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;//武器骨骼UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "Components")class USkeletalMeshComponent* SkeletalComponent;//开火UFUNCTION(BlueprintCallable,Category = "WeaponFire")void Fire();//描述所造成的伤害的类UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Weapon")TSubclassOf<class UDamageType> DamageType;//炮口粒子系统UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="WeaponParticle")class UParticleSystem* MuzzleEffect;//粒子附加到骨骼的名字UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="WeaponParticle")FName MuzzleSocketName;//撞击到敌人身上的粒子系统UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "WeaponParticle")UParticleSystem* ImpactEffect;
public:	// Called every framevirtual void Tick(float DeltaTime) override;};

Weapon.cpp

// Fill out your copyright notice in the Description page of Project Settings.
#include "Weapon.h"
#include <Kismet/GameplayStatics.h>
#include "Particles/ParticleSystem.h"
// Sets default values
AWeapon::AWeapon()
{// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;SkeletalComponent = CreateAbstractDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalComponent"));SkeletalComponent->SetupAttachment(GetRootComponent());MuzzleSocketName = "MuzzleSocket";
}// Called when the game starts or when spawned
void AWeapon::BeginPlay()
{Super::BeginPlay();}void AWeapon::Fire()
{AActor* MyOwner = GetOwner();if (MyOwner){FVector EyeLocation;FRotator EyeRotation;//返回角色视角MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotation);FVector TraceEnd = EyeLocation + (EyeRotation.Vector() * 10000);FCollisionQueryParams QueryParams;QueryParams.AddIgnoredActor(MyOwner);QueryParams.AddIgnoredActor(this);QueryParams.bTraceComplex = true;FHitResult Hit;FVector ShotDirection = EyeRotation.Vector();//使用特定的通道追踪光线并返回第一个阻塞命中TRUE(如果发现了阻塞命中)if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, ECC_Visibility, QueryParams)){//设置受阻,造成伤害结果AActor* HitActor = Hit.GetActor();UGameplayStatics::ApplyPointDamage(HitActor, 10.f, ShotDirection, Hit, MyOwner->GetInstigatorController(),this, DamageType);//粒子生成的位置UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactEffect, Hit.ImpactPoint,Hit.ImpactNormal.Rotation());}DrawDebugLine(GetWorld(), EyeLocation, TraceEnd,FColor::Red,false,1.0f,0,1.0f);if (MuzzleEffect){//附加粒子效果UGameplayStatics::SpawnEmitterAttached(MuzzleEffect,SkeletalComponent,MuzzleSocketName);}}
}// Called every frame
void AWeapon::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}

创建十字准心

  • 创建一个控件蓝图作为十字准心的窗口
    在这里插入图片描述
  • 在角色蓝图的BeginPlay中添加这个视口到窗口中
    在这里插入图片描述
  • 运行结果
    在这里插入图片描述

MyCharacter.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "MyCharacter.generated.h"UCLASS()
class SHOOTGAME_API AMyCharacter : public ACharacter
{GENERATED_BODY()public:// Sets default values for this character's propertiesAMyCharacter();UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputMappingContext* DefaultMappingContext;UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputAction* MoveAction;UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputAction* LookAction;UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")class UInputAction* CrouchAction;UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "SpringArm")class USpringArmComponent* SpringArm;UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")class UCameraComponent* Camera;//UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation", meta = (AllowPrivateAccess = "true"))//class UAnimInstance* MyAnimInstance; // 或者使用 TSubclassOf<UAnimInstance> 作为类型指向动画蓝图类protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;void CharacterMove(const FInputActionValue& Value);void CharacterLook(const FInputActionValue& Value);void BeginCrouch();void EndCtouch();public:	// Called every framevirtual void Tick(float DeltaTime) override;// Called to bind functionality to inputvirtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;//重写GetPawnViewLocation函数将其返回摄像机的眼睛看见的位置virtual FVector GetPawnViewLocation() const override;
};

MyCharacter.cpp

// Fill out your copyright notice in the Description page of Project Settings.#include "MyCharacter.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/PawnMovementComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Engine/Engine.h"// Sets default values
AMyCharacter::AMyCharacter()
{// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;//允许角色进行蹲伏(crouch)动作,并且能够影响导航代理(Navigation Agent)的行为GetMovementComponent()->GetNavAgentPropertiesRef().bCanCrouch = true;//自动转向GetCharacterMovement()->bOrientRotationToMovement = true;//对Character的Pawn的朝向进行硬编码bUseControllerRotationPitch = false;bUseControllerRotationYaw = false;bUseControllerRotationRoll = false;SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));SpringArm->SetupAttachment(GetRootComponent());SpringArm->TargetArmLength = 400.f;SpringArm->bUsePawnControlRotation = true;Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));Camera->SetupAttachment(SpringArm);Camera->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(DefaultMappingContext, 0);}}
}void AMyCharacter::CharacterMove(const FInputActionValue& Value)
{FVector2D MovementVector = Value.Get<FVector2D>();if (Controller){FRotator Rotation = Controller->GetControlRotation();FRotator YawRotation = FRotator(0., Rotation.Yaw, 0.);FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);AddMovementInput(ForwardDirection, MovementVector.Y);AddMovementInput(RightDirection, MovementVector.X);}
}void AMyCharacter::CharacterLook(const FInputActionValue& Value)
{FVector2D LookVector = Value.Get<FVector2D>();if (Controller){AddControllerPitchInput(LookVector.Y);AddControllerYawInput(LookVector.X);}
}void AMyCharacter::BeginCrouch()
{//bIsCrouched = true;//Crouch();//FString MessageString;//MessageString.AppendInt((TEXT("bIsCrouched is111, %s"), bIsCrouched));//GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Red, MessageString);GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Red, FString::Printf(bIsCrouched));
}void AMyCharacter::EndCtouch()
{//bIsCrouched = false;//UnCrouch();//FString MessageString;//MessageString.AppendInt((TEXT("bIsCrouched is222, %s"), bIsCrouched));//GEngine->AddOnScreenDebugMessage(0, 10.f, FColor::Red, MessageString);
}// 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* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);if (EnhancedInputComponent){EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::CharacterMove);EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyCharacter::CharacterLook);EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Triggered, this, &AMyCharacter::BeginCrouch);EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Completed, this, &AMyCharacter::EndCtouch);}}FVector AMyCharacter::GetPawnViewLocation() const
{if (Camera){//返回摄像机眼睛的位置return Camera->GetComponentLocation();}return Super::GetPawnViewLocation();
}

Weapon.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Weapon.generated.h"UCLASS()
class SHOOTGAME_API AWeapon : public AActor
{GENERATED_BODY()public:	// Sets default values for this actor's propertiesAWeapon();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;//武器骨骼UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "Components")class USkeletalMeshComponent* SkeletalComponent;//开火UFUNCTION(BlueprintCallable,Category = "WeaponFire")void Fire();//描述所造成的伤害的类UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Weapon")TSubclassOf<class UDamageType> DamageType;//炮口粒子系统UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="WeaponParticle")class UParticleSystem* MuzzleEffect;//粒子附加到骨骼的名字UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="WeaponParticle")FName MuzzleSocketName;//撞击到敌人身上的粒子系统UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "WeaponParticle")UParticleSystem* ImpactEffect;
public:	// Called every framevirtual void Tick(float DeltaTime) override;};

Weapon.cpp

// Fill out your copyright notice in the Description page of Project Settings.#include "Weapon.h"
#include <Kismet/GameplayStatics.h>
#include "Particles/ParticleSystem.h"
// Sets default values
AWeapon::AWeapon()
{// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;SkeletalComponent = CreateAbstractDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalComponent"));SkeletalComponent->SetupAttachment(GetRootComponent());MuzzleSocketName = "MuzzleSocket";
}// Called when the game starts or when spawned
void AWeapon::BeginPlay()
{Super::BeginPlay();}void AWeapon::Fire()
{AActor* MyOwner = GetOwner();if (MyOwner){FVector EyeLocation;FRotator EyeRotation;//返回角色视角MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotation);FVector TraceEnd = EyeLocation + (EyeRotation.Vector() * 10000);FCollisionQueryParams QueryParams;QueryParams.AddIgnoredActor(MyOwner);QueryParams.AddIgnoredActor(this);QueryParams.bTraceComplex = true;FHitResult Hit;FVector ShotDirection = EyeRotation.Vector();//使用特定的通道追踪光线并返回第一个阻塞命中TRUE(如果发现了阻塞命中)if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, ECC_Visibility, QueryParams)){//设置受阻,造成伤害结果AActor* HitActor = Hit.GetActor();UGameplayStatics::ApplyPointDamage(HitActor, 10.f, ShotDirection, Hit, MyOwner->GetInstigatorController(),this, DamageType);//粒子生成的位置UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactEffect, Hit.ImpactPoint,Hit.ImpactNormal.Rotation());}DrawDebugLine(GetWorld(), EyeLocation, TraceEnd,FColor::White,false,1.0f,0,1.0f);if (MuzzleEffect){//附加粒子效果UGameplayStatics::SpawnEmitterAttached(MuzzleEffect,SkeletalComponent,MuzzleSocketName);}}
}// Called every frame
void AWeapon::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}

相关文章:

UEC++ 虚幻5第三人称射击游戏(一)

UEC 虚幻5第三人称射击游戏&#xff08;一&#xff09; 创建一个空白的C工程 人物角色基本移动 创建一个Character类添加一些虚幻商城中的基础动画 给角色类添加Camera与SPringArm组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category "SpringArm")clas…...

java小代码(1)

代码 &#xff1a; 今日总结到此结束&#xff0c;拜拜&#xff01;...

SLAM ORB-SLAM2(27)词袋模型

SLAM ORB-SLAM2(27)词袋模型 1. 词袋模型1.1. 词汇树1.2. 逆向索引表1.3. 逆向索引表2. 词袋向量3. 匹配候选帧3.1. 找出和当前帧具有公共单词的所有关键帧3.2. 找出和当前帧最多公共单词的关键帧3.3. 剔除共享单词数较少的关键帧3.4. 计算关键帧的共视关键帧组的总得分3.5. …...

OpenAI 的 GPT-5:CTO米拉-穆拉提说,到 2026 年将实现博士级智能(Ph.D.-Level))

据首席技术官米拉-穆拉提&#xff08;Mira Murati&#xff09;介绍&#xff0c;GPT-5 是 OpenAI 人工智能的下一代进化产品&#xff0c;将于 2025 年底或 2026 年初在特定任务中实现博士级智能。 GPT-5 内部代号为 "Gobi "和 “Arrakis”&#xff0c;将是一个多模态…...

macbook配置adb环境和用adb操作安卓手机

&#xff08;参考&#xff1a;ADB工具包的安装与使用_adb工具箱-CSDN博客&#xff09; 第一步&#xff1a;从Android开发者网站下载Android SDK&#xff08;软件开发工具包&#xff09;。下载地址为&#xff1a; 第二步&#xff1a;解压下载的SDK压缩文件到某个目录中。 进入解…...

微软TTS最新模型,发布9种更真实的AI语音

很高兴与大家分享 Azure AI 语音翻译产品套件的两个重大更新&#xff1a; 视频翻译和增强的实时语音翻译 API。 视频翻译&#xff08;批量&#xff09; 今天&#xff0c;我们宣布推出视频翻译预览版&#xff0c;这是一项突破性的服务&#xff0c;旨在改变企业本地化视频内容…...

python爬虫 -爬取 json 格式数据

在Python中&#xff0c;爬取JSON格式的数据通常涉及到发送 HTTP请求到某个URL&#xff0c;并解析返回的JSON数据。以下是一个简单的示例&#xff0c;说明如何使用Python的requests库来爬取JSON格式的数据&#xff1a; 1. 首先&#xff0c;确保你已经安装了requests库。如果没…...

Pytorch(5)-----梯度计算

一、问题 如何使用Pytorch计算样本张量的基本梯度呢&#xff1f;考虑一个样本数据集&#xff0c;且有两个展示变量&#xff0c;在给定初始权重的基础上&#xff0c;如何在每次迭代中计算梯度呢&#xff1f; 二、如何运行 假设有x_data 和 y_data 列表&#xff0c;计算两个列表需…...

C#的膨胀之路:创新还是灭亡

开篇概述 C#&#xff0c;这门由微软推出的编程语言&#xff0c;自2000年诞生以来&#xff0c;以其简洁的语法、强大的功能和广泛的应用场景&#xff0c;赢得了我等程序员的热爱。它在.NET框架的加持下&#xff0c;展现出无与伦比的开发效率和性能。然而&#xff0c;随着时间的流…...

SpringBoot 过滤器和拦截器的区别

SpringBoot 过滤器和拦截器的区别 Spring拦截器&#xff08;Interceptor&#xff09;和过滤器&#xff08;Filter&#xff09;是Spring框架中用于处理请求的两种机制&#xff0c;虽然它们都可以在请求处理的不同阶段进行拦截和处理&#xff0c;但它们的工作原理和应用场景有所…...

协程执行顺序引发的问题

引言 在Golang中&#xff0c;因为协程执行的顺序是不固定的&#xff0c;如果不在代码里进行控制&#xff0c;可能就会导致预期外的输出。 本文通过分析一段代码的执行来介绍这种情况&#xff0c;以及可行的控制协程执行顺序的方法&#xff1a; sleep()waitGroup 实例分析 代…...

android webview调用js滚动到指定位置

一、activity import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.tencent.smtt.sdk.WebView import com.tencent.smtt.sdk.WebViewClientclass MainActivity : AppCompatActivity() {private lateinit var webView: WebViewoverride fun …...

WPF 深入理解一、基础知识介绍

基础知识 本系列文章是对个人 B站 up 微软系列技术教程 记录 视频地址 https://www.bilibili.com/video/BV1HC4y1b76v/?spm_id_from333.999.0.0&vd_source0748f94a553c71a2b0125078697617e3 winform 与 wpf 异同 1.winform 项目结构 编辑主要是在 Form1.cs(页面)&#…...

腾讯云点播ugc upload | lack signature 问题处理

我犯一个很傻的错误 参考腾讯云官方文档&#xff1a;云点播 Web 端上传 SDK-开发指南-文档中心-腾讯云 进行开发&#xff0c;但是却报错了&#xff0c;始终找不到问题&#xff0c;错误提示&#xff1a;ugc upload | lack signature&#xff0c;意思是缺少签名或者签名失败&…...

计算机视觉实验二:基于支持向量机和随机森林的分类(Part one: 编程实现基于支持向量机的人脸识别分类 )

目录 一、实验内容 二、实验目的 三、实验步骤 四、实验结果截图 五、实验完整代码 六、报错及解决方案 PS:实验的运行速度受电脑性能影响,如遇运行卡顿请耐心等待。 一、实验内容 编程实现基于支持向量机的人脸识别分类,基本功能包括:Labeled Faces in th…...

5.什么是C语言

什么是 C 语言? C语言是一种用于和计算机交流的高级语言, 它既具有高级语言的特点&#xff0c;又具有汇编语言的特点 非常接近自然语言程序的执行效率非常高 C语言是所有编程语言中的经典&#xff0c;很多高级语言都是从C语言中衍生出来的&#xff0c; 例如:C、C#、Object-C、…...

DINO-DETR

DINO-DETR DETR收敛慢的问题1. Contrastive DeNoising Training(对比方法降噪训练)2. Mixed Query Selection(混合查询选择方法对锚点进行初始化)3. Look Forward Twice(两次前向方法)==DINO模型的传播过程,以及部分模块的改进==DETR收敛慢的问题 PnP-DETR(ICCV 2021) 改进了…...

Representation RL:HarmonyDream: Task Harmonization Inside World Models

ICML2024 paper code Intro 基于状态表征的model-based强化学习方法一般需要学习状态转移模型以及奖励模型。现有方法都是将二者联合训练但普遍缺乏对如何平衡二者之间的比重进行研究。本文提出的HarmonyDream便是通过自动调整损失系数来维持任务间的和谐&#xff0c;即在世界…...

Centos7系统下Docker的安装与配置

文章目录 前言下载Docker安装yum库安装Docker启动和校验配置Docker镜像加速卸载Docker 前言 此博客的内容的为自己的学习笔记&#xff0c;如果需要更具体的内容&#xff0c;可查看Docker官网文档内容 注意&#xff1a;以下命令在root管理员用户下运行&#xff0c;如果在普通用…...

无人机校企合作

有没有想过&#xff0c;无人机和校企合作能碰撞出怎样的火花&#xff1f;&#x1f525;今天就来给大家揭秘一下这个神秘组合&#xff01; 无人机&#xff0c;作为现代科技的代表&#xff0c;已经渗透到我们生活的方方面面。而校企合作&#xff0c;更是推动科技创新、培养人才的…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

DiscuzX3.5发帖json api

参考文章&#xff1a;PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下&#xff0c;适配我自己的需求 有一个站点存在多个采集站&#xff0c;我想通过主站拿标题&#xff0c;采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...