TP_WeaponComponent.h
看看头文件
暴露了attach weapon和fire给蓝图
这两个函数意义一看名字吧,就是捡起来枪的时候执行,一个就是发射子弹的时候执行
#pragma once
#include "CoreMinimal.h"
#include "Components/SkeletalMeshComponent.h"
#include "TP_WeaponComponent.generated.h"
class AFirstPersonCharacter;
UCLASS(Blueprintable, BlueprintType, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class FIRSTPERSON_API UTP_WeaponComponent : public USkeletalMeshComponent
{
GENERATED_BODY()
public:
/** Projectile class to spawn */
UPROPERTY(EditDefaultsOnly, Category=Projectile)
TSubclassOf<class AFirstPersonProjectile> ProjectileClass;
/** Sound to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
USoundBase* FireSound;
/** AnimMontage to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
UAnimMontage* FireAnimation;
/** Gun muzzle's offset from the characters location */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
FVector MuzzleOffset;
/** MappingContext */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
class UInputMappingContext* FireMappingContext;
/** Fire Input Action */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
class UInputAction* FireAction;
/** Sets default values for this component's properties */
UTP_WeaponComponent();
/** Attaches the actor to a FirstPersonCharacter */
UFUNCTION(BlueprintCallable, Category="Weapon")
bool AttachWeapon(AFirstPersonCharacter* TargetCharacter);
/** Make the weapon Fire a Projectile */
UFUNCTION(BlueprintCallable, Category="Weapon")
void Fire();
protected:
/** Ends gameplay for this component. */
UFUNCTION()
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
private:
/** The Character holding this weapon*/
AFirstPersonCharacter* Character;
};
看看具体实现
这个是attach
传入character,然后获取到USkeletalMeshComponent,就是mesh1p这个
然后就attach上去,这个rule后面再细了解吧
然后character还要AddInstanceComponent(this)
这里注意attach和add是分开的
完事就可以注册mapping和bindaction了,最后endplay的时候remove掉
bool UTP_WeaponComponent::AttachWeapon(AFirstPersonCharacter* TargetCharacter)
{
Character = TargetCharacter;
// Check that the character is valid, and has no weapon component yet
if (Character == nullptr || Character->GetInstanceComponents().FindItemByClass<UTP_WeaponComponent>())
{
return false;
}
// Attach the weapon to the First Person Character
FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, true);
AttachToComponent(Character->GetMesh1P(), AttachmentRules, FName(TEXT("GripPoint")));
// add the weapon as an instance component to the character
Character->AddInstanceComponent(this);
// Set up action bindings
if (APlayerController* PlayerController = Cast<APlayerController>(Character->GetController()))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
// Set the priority of the mapping to 1, so that it overrides the Jump action with the Fire action when using touch input
Subsystem->AddMappingContext(FireMappingContext, 1);
}
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerController->InputComponent))
{
// Fire
EnhancedInputComponent->BindAction(FireAction, ETriggerEvent::Triggered, this, &UTP_WeaponComponent::Fire);
}
}
return true;
}
再看另外一个fire函数
void UTP_WeaponComponent::Fire()
{
if (Character == nullptr || Character->GetController() == nullptr)
{
return;
}
// Try and fire a projectile
if (ProjectileClass != nullptr)
{
UWorld* const World = GetWorld();
if (World != nullptr)
{
APlayerController* PlayerController = Cast<APlayerController>(Character->GetController());
const FRotator SpawnRotation = PlayerController->PlayerCameraManager->GetCameraRotation();
// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position
const FVector SpawnLocation = GetOwner()->GetActorLocation() + SpawnRotation.RotateVector(MuzzleOffset);
//Set Spawn Collision Handling Override
FActorSpawnParameters ActorSpawnParams;
ActorSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding;
// Spawn the projectile at the muzzle
World->SpawnActor<AFirstPersonProjectile>(ProjectileClass, SpawnLocation, SpawnRotation, ActorSpawnParams);
}
}
// Try and play the sound if specified
if (FireSound != nullptr)
{
UGameplayStatics::PlaySoundAtLocation(this, FireSound, Character->GetActorLocation());
}
// Try and play a firing animation if specified
if (FireAnimation != nullptr)
{
// Get the animation object for the arms mesh
UAnimInstance* AnimInstance = Character->GetMesh1P()->GetAnimInstance();
if (AnimInstance != nullptr)
{
AnimInstance->Montage_Play(FireAnimation, 1.f);
}
}
}
如果有character,也有子弹类projectileclass
拿到world然后spawnActor了一个AFirstPersonProjectile,就是那个子弹,上一章说过这个对象,他创建完毕是具备一个初速度的,所以就实现发射了,然后执行音频播放和动画播放,动画应该是后坐力
这个attach的具体地方如下所示,所以顺道看看pickup
这个是property,且参数用的是这样的,所以逻辑在蓝图里实现,具体就是上面的图
看看cpp文件实现
就是给overlap也就是相交事件绑定一个broadcast(Character)可以触发onPickUp
然后就走蓝图里的流程了
总结
weapon实现attach,然后是pickup component的mesh使用gun,等character碰到gun了就触发onpick 调用attach
attach后,character就有一个枪拿在手里了
鼠标点击就能出发fire函数了就生成sphere飞出去