【UE】实现子弹追踪效果的一种方法

效果:

1.1 创建项目

        这里直接使用的第一人称游戏的模板,创建为蓝图项目。

1.2 添加子弹类

子弹类头文件:

        其中TargetActor为追踪的目标,BaseVelocity为子弹刚发射时的速度,MaxLength为追踪阶段的最远距离,MinLength为追踪阶段的最近距离(后面会解释)。

class LOCKFPS_API ABulletActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ABulletActor();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;
	void SetVelocity();

	FVector BaseVelocity;
	bool bLock=false;

	UPROPERTY(EditDefaultsOnly)
	UProjectileMovementComponent*ProjectileMovementComp;
	UPROPERTY(BlueprintReadWrite)
	AActor*TargetActor;
	UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(DisplayName="追踪阶段最大距离"))
	float MaxLength=1000;
	UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(DisplayName="追踪阶段最小距离"))
	float MinLength=50;	
};
子弹类源文件:

        原理:子弹分为追踪阶段和普通运动阶段(速度方向固定),如果未捕获到目标则以普通运动阶段运行。如果捕获到目标,会进入追踪阶段并根据和目标的直线距离实时计算速度方向,当子弹和目标的距离小于追踪阶段的最近距离,停止追踪并进入普通运动阶段。

ABulletActor::ABulletActor()
{
	PrimaryActorTick.bCanEverTick = true;
	RootComponent=CreateDefaultSubobject<USceneComponent>(TEXT("RootComp"));
	ProjectileMovementComp=CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComp"));
	ProjectileMovementComp->ProjectileGravityScale=0;
	
}

void ABulletActor::BeginPlay()
{
	Super::BeginPlay();
	BaseVelocity=ProjectileMovementComp->Velocity.GetSafeNormal()*ProjectileMovementComp->MaxSpeed;
}

void ABulletActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	SetVelocity();
}

void ABulletActor::SetVelocity()
{
	if (TargetActor)
	{
		float VelocityAlpha;
		float VelocityLength;
		FVector TargetDir;
		//计算当前位置指向目标位置的向量方向和模长
		(TargetActor->GetActorLocation()-GetActorLocation()).ToDirectionAndLength(TargetDir,VelocityLength);
		//判断当前位置和目标位置的距离是否小于追踪阶段最小距离,如果小于,清除目标并停止追踪。子弹将沿着停止追踪时的速度方向继续运动
		if (VelocityLength<=MinLength){TargetActor=nullptr;return;}
	
		if (VelocityLength<MaxLength||bLock)
		{
			//如果进入追踪状态,将bLock设置为true
			bLock=true;
			//计算Alpha值,当前位置距离目标位置为MaxLength时,Alpha≈0。当前位置距离目标位置为MinLength时,Alpha=1。
			VelocityAlpha=(MaxLength-(VelocityLength-MinLength))/MaxLength;
			//使用lerp进行计算,A为子弹刚发射时的速度方向,B为前位置指向目标位置的方向
			ProjectileMovementComp->Velocity=FMath::Lerp<FVector,float>
			(BaseVelocity.GetSafeNormal(),TargetDir,VelocityAlpha)*ProjectileMovementComp->MaxSpeed;
		}
		else
		{
			ProjectileMovementComp->Velocity=ProjectileMovementComp->Velocity.GetSafeNormal()*ProjectileMovementComp->MaxSpeed;
		}
	}
}

1.3 目标捕获和发射子弹(玩家类蓝图)

1.4 子弹属性设置(子弹类蓝图)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值