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

TP_WeaponComponent.h

看看头文件

暴露了attach weapon和fire给蓝图

这两个函数意义一看名字吧,就是捡起来枪的时候执行,一个就是发射子弹的时候执行

cpp 复制代码
#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掉

cpp 复制代码
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函数

cpp 复制代码
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飞出去

相关推荐
日月云棠3 天前
UE5源码分析之Editor——Blutility模块全面分析
ue5
日月云棠3 天前
UE5源码分析之Editor——BehaviorTreeEditor模块全面分析
ue5
日月云棠3 天前
UE5源码分析之Editor——AssetTagsEditor模块全面分析
ue5
远离UE44 天前
UE5 显存 虚拟内存 深入学习笔记
笔记·学习·ue5
日月云棠4 天前
UE5源码分析之Editor——AnimationSettings模块全面分析
ue5
fangzhanpeng1685 天前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
远离UE45 天前
UE5 SF_VertexShader 如何使用
ue5
电子云与长程纠缠5 天前
UE5 Lyra PocketWorld进行3D内容UI预览 - 上
开发语言·学习·3d·ue5·游戏引擎
电子云与长程纠缠5 天前
UE5 Lyra PocketWorld进行3D内容UI预览 - 下
开发语言·学习·游戏·ui·ue5
远离UE46 天前
UE5 GPU内部异步
ue5