声明一个函数
//设计特效
void PlayFireEffects(FVector TraceEnd);
定义这个函数
void ASWeapen::PlayFireEffects(FVector TraceEnd)
{
//开枪成功,生成枪口特效
if (MuzzleEffect)
{
//粒子特效,组件,组件的socket
UGameplayStatics::SpawnEmitterAttached(MuzzleEffect, MeshComponent, MuzzleSocketName);
}
//然后生成弹道特效
if (TracerEffect)
{
//计算枪口位置
FVector MuzzleLocation = MeshComponent->GetSocketLocation("MuzzleSocket");
//声明一个变量,拿到这个特效实例
UParticleSystemComponent *TracerComp = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), TracerEffect, MuzzleLocation);
if (TracerComp)
{
TracerComp->SetVectorParameter(TrancerTargetName, TraceEnd);
}
}
}
改造一下fire函数
void ASWeapen::Fire()
{
//创建一个撞击句柄,用来获取弹道相关信息
FHitResult Hit;
//弹道的起点,我们设置为角色眼睛的位置
AActor * MyOwner = GetOwner();
if (MyOwner)
{ //位置
FVector EyeLocation;
//方向
FRotator EyeRotator;
//得到眼睛的位置和角度
MyOwner->GetActorEyesViewPoint(EyeLocation, EyeRotator);
//弹道的终点就是起点+方向*10000
FVector TraceEnd = EyeLocation + (EyeRotator.Vector() * 1000);
//弹道特效的结束点
FVector TraceEndPoint = TraceEnd;
//设置碰撞通道为可见性通道
FCollisionQueryParams QueryParams;
//让射线忽略玩家和枪
QueryParams.AddIgnoredActor(MyOwner);
QueryParams.AddIgnoredActor(this);
//符合追踪设为true,可以让射击更加精准
QueryParams.bTraceComplex = true;
//在创建一个单轨迹线来计算弹道
//LineTraceSingleByChannel击中物体返回true
if (GetWorld()->LineTraceSingleByChannel(Hit, EyeLocation, TraceEnd, ECC_Visibility, QueryParams))
{
//命中对象
AActor * HitActor = Hit.GetActor();
//调用伤害函数
//参数分别为伤害对象、基础伤害、设计方向、命中信息(命中句柄)、MyOwner->GetInstigatorController(暂时不了解)
//this(伤害者) 和伤害类型
UGameplayStatics::ApplyPointDamage(HitActor, 20, EyeRotator.Vector(), Hit, MyOwner->GetInstigatorController(), this, DamageType);
//生成特效在命中点
//ImpactEffect:特效 ImpactPoint:打击点 Rotation():打击方向
if (ImpactEffect)
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactEffect, Hit.ImpactPoint, Hit.ImpactNormal.Rotation());
}
//命中的时候,修改弹道特效的终点
TraceEndPoint = Hit.ImpactPoint;
}
//方便debug
DrawDebugLine(GetWorld(), EyeLocation, TraceEnd, FColor::Red, false, 1, 0, 1);
//射击特效
PlayFireEffects(TraceEndPoint);
}
}
=======================================
打开玩家类
声明多个武器相关的成员变量
//目前玩家手中的武器
class ASWeapen * CurrentWeapen;
//初始时武器类型
UPROPERTY(EditDefaultsOnly, Category = "Player")
TSubclassOf<class ASWeapen> StartWeapen;
//武器插槽的名称
UPROPERTY(EditDefaultsOnly, Category = "Player")
FName WeaponAttachSoketName;
声明一个开火函数
//开火函数
void Fire();
导入头文件
#include "Engine/World.h"
#include "SWeapen.h"
#include "Components/SkeletalMeshComponent.h"
在构造函数中对插槽名进行初始化
//这个要按照你右手骨骼中插槽的名字进行初始化
WeaponAttachSoketName = "WeaponSocket";
在游戏开始函数中,对当前武器进行生成和初始化
void ASCharacter::BeginPlay()
{
Super::BeginPlay();
DefaultsFOV = CameraComp->FieldOfView;
//设置生成参数,当生成的actor碰到了其他物体,也要生成
FActorSpawnParameters Parameters;
Parameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
//生成武器actor(类型、位置、方向、参数),并且其地址赋予到指针上
CurrentWeapen = GetWorld()->SpawnActor<ASWeapen>(StartWeapen, FVector::ZeroVector, FRotator::ZeroRotator, Parameters);
//设置武器的位置与骨骼的插槽中,并设置主人
if (CurrentWeapen)
{
CurrentWeapen->SetOwner(this);
CurrentWeapen->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale,WeaponAttachSoketName);
}
}
然后定义fire()函数
void ASCharacter::Fire()
{
if (CurrentWeapen)
{
CurrentWeapen->Fire();
}
}
然后绑定fire函数
//开火
PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &ASCharacter::Fire);
编译,然后修改玩家蓝图