11月15日 作业2,黑洞子弹,子弹发射位置朝着准星方向 UE4斯坦福 学习笔记

黑洞子弹

##这里遇到了问题,作业要求两个子弹,但是我跟着教程创建的黑洞子弹射出后不能吸引周围的物体,传送子弹不起作用,需要未来回来修改

创建一个子弹的Base,继承AActor

.h文件

protected: // Called when the game starts or when spawned virtual void BeginPlay() override; UPROPERTY(EditAnywhere) UParticleSystem* VFXcomp; UPROPERTY(VisibleAnywhere,BlueprintReadOnly) USphereComponent* SphereComp; UPROPERTY(VisibleAnywhere,BlueprintReadOnly) UParticleSystemComponent* EffectComp; UPROPERTY(VisibleAnywhere,BlueprintReadOnly) UProjectileMovementComponent* MovementComp; // Called when the game starts or when spawned UFUNCTION() virtual void OnActorHit(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); UFUNCTION(BlueprintCallable,BlueprintNativeEvent) void Explode(); virtual void PostInitializeComponents() override;

在.cpp内添加功能

ASProjectileBase::ASProjectileBase() { // 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; SphereComp = CreateDefaultSubobject<USphereComponent>("SphereComp"); //绑定 SphereComp->SetCollisionProfileName("Projectile"); //设置了碰撞为配置名称Projectile SphereComp->OnComponentBeginOverlap.AddDynamic(this, &ASProjectileBase::OnActorHit); RootComponent = SphereComp; EffectComp = CreateDefaultSubobject<UParticleSystemComponent>("EffectComp"); EffectComp-> SetupAttachment(SphereComp); MovementComp = CreateDefaultSubobject<UProjectileMovementComponent>("MovementComp"); //设置移动组件 MovementComp->InitialSpeed = 8000.0f; //初始速度 MovementComp->ProjectileGravityScale = 0.0f; MovementComp->bRotationFollowsVelocity = true; //初始位置的旋转跟随我们的Pawn视角 MovementComp->bInitialVelocityInLocalSpace = true;//初始速度被生成的时候以当前location为初始位置 } // Called when the game starts or when spawned void ASProjectileBase::BeginPlay() { Super::BeginPlay(); } void ASProjectileBase::OnActorHit(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) { Explode(); } void ASProjectileBase::Explode_Implementation() { //当子弹没有被杀死时 if(ensure(!IsPendingKill())) { //生成一个特效 UGameplayStatics::SpawnEmitterAtLocation(this,VFXcomp,GetActorLocation(),GetActorRotation()); //摧毁 Destroy(); } } void ASProjectileBase::PostInitializeComponents() { Super::PostInitializeComponents(); } // Called every frame void ASProjectileBase::Tick(float DeltaTime) { Super::Tick(DeltaTime); }

创建一个黑洞子弹,继承我们刚刚创建的子弹类

.h文件

protected: // Called when the game starts or when spawned virtual void BeginPlay() override; UPROPERTY(EditAnywhere,Category="Teleport") float TeleportDelay; UPROPERTY(EditAnywhere,Category="Teleport") float DetonateDelay; UPROPERTY(VisibleAnywhere) URadialForceComponent* RadialForceComp; FTimerHandle TimerHandle; void TeleportInstigator(); virtual void Explode_Implementation() override;

在.cpp内添加功能

ASDashProjectile::ASDashProjectile() { // 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; TeleportDelay = 0.2f; DetonateDelay = 0.2f; MovementComp->InitialSpeed = 6000.0f; RadialForceComp = CreateDefaultSubobject<URadialForceComponent>("RadialFroce"); //是否自动激活 RadialForceComp->SetAutoActivate(false); RadialForceComp->Radius = 2000.0f; RadialForceComp->ImpulseStrength = -750.0f; //是否随着目标速度变化而变化 RadialForceComp->bImpulseVelChange = true; } // Called when the game starts or when spawned void ASDashProjectile::BeginPlay() { Super::BeginPlay(); GetWorldTimerManager().SetTimer(TimerHandle,this,&ASDashProjectile::Explode,DetonateDelay); } // void ASDashProjectile::Explode_Implementation() { GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Green, FString::Printf(TEXT("AttributeComp")));//输出调试信息 RadialForceComp->FireImpulse(); GetWorldTimerManager().ClearTimer(TimerHandle); UGameplayStatics::SpawnEmitterAtLocation(this,VFXcomp,GetActorLocation(),GetActorRotation()); //禁用Effect EffectComp->DeactivateSystem(); //停止运动 MovementComp->StopMovementImmediately(); //关闭碰撞 SetActorEnableCollision(false); FTimerHandle Timer; GetWorldTimerManager().SetTimer(Timer,this,&ASDashProjectile::TeleportInstigator,TeleportDelay); Super::Explode_Implementation(); } // Called every frame void ASDashProjectile::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void ASDashProjectile::TeleportInstigator() { AActor* ActorToTeleport = GetInstigator(); if(ensure(ActorToTeleport)) { ActorToTeleport->TeleportTo(GetActorLocation(),ActorToTeleport->GetActorRotation(),false,false); } }

最后在蓝图内创建ASDashProjectile的蓝图并加上特效即可

子弹发射位置朝着准星方向

先回到chara的.h文件,新增一个void函数

void SpawnProjectile(TSubclassOf<AActor> ClassToSpawn);

和一个float

float AttackAnimDelay;

视频内的思路是:每一种子弹创建单独的指针,再调用同一个发射函数,这部分修改的东西过多

首先修改了攻击指针

void ASCharacter::PrimaryAttack_TimeElapsed() { SpawnProjectile(ProjectileClass); }

去除了之前的发射子弹逻辑,将发射子弹逻辑写入新的SpawnProjectile内

新的攻击逻辑是,不同的子弹调用不同的指针,再传入SpawnProjectile内,然后再生成一个球形的碰撞体,检测到我们的需要攻击的对象,距离是5000f

最后添加了一个攻击时子弹总是从手部射到屏幕中间的位置

//新的射击 void ASCharacter::SpawnProjectile(TSubclassOf<AActor> ClassToSpawn) { if(ensure(ProjectileClass)) { //触发函数的时候从手部位置生成一个魔法球的模型 FVector HandLocation = GetMesh()->GetSocketLocation("Muzzle_01"); FActorSpawnParameters SpawnParameters; SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; SpawnParameters.Instigator=this; //球形碰撞体 FCollisionShape Shape; Shape.SetSphere(20.0f); // FCollisionQueryParams Params; Params.AddIgnoredActor(this); //三种类型 FCollisionObjectQueryParams QueryParams; QueryParams.AddObjectTypesToQuery(ECC_WorldDynamic); QueryParams.AddObjectTypesToQuery(ECC_WorldStatic); QueryParams.AddObjectTypesToQuery(ECC_Pawn); // FVector TraceStart = CameraComp->GetComponentLocation(); FVector TraceEnd = CameraComp->GetComponentLocation() + (GetControlRotation().Vector() * 5000); FHitResult Hit; if(GetWorld()->SweepSingleByObjectType(Hit,TraceStart,TraceEnd,FQuat::Identity,QueryParams,Shape,Params)) { TraceEnd = Hit.ImpactPoint; } //让手部总是朝着十字准星的方向射击,准确的说是跟随射线的终点,这一段的逻辑是终点的Location位置减去手部位置在世界中的Location,用MakeFromX计算出旋转的量 FRotator ProRotator = FRotationMatrix::MakeFromX(TraceEnd - HandLocation).Rotator(); // FTransform Transform = FTransform(ProRotator, HandLocation); //发射 GetWorld()->SpawnActor<AActor>(ClassToSpawn,Transform,SpawnParameters); } }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值