• UE5之5.4 第一人称示例代码阅读2 子弹发射逻辑


    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飞出去

  • 相关阅读:
    【Mybatis】使用注解开发
    Android BottomNavigation底部导航栏使用
    存储大实验,游戏A Slower Speed of Light的开发
    【C++ 构造函数和析构函数:对象生命周期的关键】
    MySQL从入门到入土【20W字收藏篇】
    打车出行小程序APP定制开发代驾拼车专车
    【开发小记】vue项目优化
    11988 - Broken Keyboard (a.k.a. Beiju Text) (UVA)
    JVM 一张图带你了解内存分配过程 搞懂逃逸分析|标量替换|指针碰撞|空闲列表|TLAB
    第十四届蓝桥杯模拟赛第一期试题【Java解析】
  • 原文地址:https://blog.csdn.net/qq_35158695/article/details/143220733