Blaster - Multiplayer P77-P89: 武器瞄准机制

P78_ Blaster HUD And Player Controller

P78_1 创建PC和HUD

P78_2 Tick Component => SetHUDCrosshairs()

P79_ Drawing the Crosshairs

  • DrawHUD() Call Every Tick.

#include "HUD/BlasterHUD.h"

void ABlasterHUD::DrawHUD()
{
	Super::DrawHUD();

	FVector2D ViewportSize;
	if (GEngine) {

		GEngine->GameViewport->GetViewportSize(ViewportSize);
		const FVector2D ViewportCenter = FVector2D(ViewportSize.X / 2.0f , ViewportSize.Y / 2.0f);
		
		if (HUDPackage.CrosshairsCenter) {
			DrawCrosshair(HUDPackage.CrosshairsCenter,ViewportCenter);
		}

		if (HUDPackage.CrosshairsLeft) {
			DrawCrosshair(HUDPackage.CrosshairsLeft, ViewportCenter);
		}

		if (HUDPackage.CrosshairsRight) {
			DrawCrosshair(HUDPackage.CrosshairsRight, ViewportCenter);
		}


		if (HUDPackage.CrosshairsTop) {
			DrawCrosshair(HUDPackage.CrosshairsTop, ViewportCenter);
		}


		if (HUDPackage.CrosshairsBottom) {
			DrawCrosshair(HUDPackage.CrosshairsBottom, ViewportCenter);
		}
	}
}

void ABlasterHUD::DrawCrosshair(UTexture2D* Texture, FVector2D ViewportCenter)
{
	const float TextureWidth = Texture->GetSizeX();
	const float TextureHeight = Texture->GetSizeY();
	const FVector2D TextureDrawPoint(
		ViewportCenter.X - (TextureWidth / 2.0f),
		ViewportCenter.Y - (TextureHeight / 2.0f)
	);

	DrawTexture(
		Texture,
		TextureDrawPoint.X,
		TextureDrawPoint.Y,
		TextureWidth,
		TextureHeight,
		0.0f,
		0.0f,
		1.0f,
		1.0f,
		FLinearColor::White);

}

P80_ Crosshair Spread

  • 本节不涉及网络内容.

P81_1 BlasterHUD

P81_1_1 BlasterHUD.h

  • 在结构体中加入了印象准信扩散的因素.
  • 设置一个变量代表准星可以扩散的最大值.

P81_1_2 BlasterHUD.cpp

  • 计算并应用准星扩散.

P81_2 CombatComponent

P81_2_1 CombatComponent.h

  • 创建两个变量存储计算的准星Factor.

P81_2_2 CombatComponent.cpp

  • 通过地速和bIsInAir 计算准星扩散因子.

P81_Correcting the Weapon Rotation

  • 修正武器朝向,让其开火时朝向子弹发射方向.

P81_1 BlasterAnimInstance::Update

  • 这里 IsLocallyControlled 的限制 和 BlasterCharacter 中 HitTarget 变量并不是复制的 , 所以这个调整武器旋转的行为只会在本地进行, 并不会同步也不需要同步到其他客户端上.

P81_2 修改 FABRIK逻辑的位置.

  • 当我们 Transform hand_r bone 后 , 发现 FABRIK 无效了 , 这个因为 FABRIK 逻辑需要再 Transform bone 逻辑之后运行.
  • 这里新建了状态机.

P81_3 只在本地校准武器朝向

  • 详见上面两个截图 , 因为其他端对于是否看见武器有偏移并无影响.

P82_ Zoom While Aiming

P82_1 Zoom While Aiming

  • Call in TickComponent , 涉及 Camera 的内容只在本地执行就行了.

P82_2 解决一下 Zoom过大 时 模糊的问题

P83_ Shrink Crosshair when Aiming And Fire

P83_1 Shrik Crosshair When Aim

P83_2 Spread Crosshair When Fire

  • 开火时设置因子.

  • 每帧都在 Interpto 0.0f.

P84_ Change Crosshair Color

  • We Can Change out Crosshair Red When We Aiming at Another Player For Example.

P84_1 创建了一个接口用于和准星交互.

P84_2 BlasterCharacter 实现了该接口.

P84_3 CombatComponent 射线检测.

P84_4 在 HUD 中动态修改准星的颜色.

P84_5 修改一下 BlasterCharacter SkelMesh 的碰撞.

  • 检查一下.

P84_6 Interp Weapon Rotaion

P85_ Extending the Trace Start

P85_1 目前 LineTrace 存在的一些问题_1

  • 我们这个射线检测到了自己.

  • 射线检测到了视野上的角色,即使这个角色我们没在瞄准.

  • 可以把 Trace Start Point 设置为同一方向上,但是在角色的前面.

P85_2 把 Trace Start Point 设置为同一方向上,但是在角色的前面.

P85_3  目前 LineTrace 存在的一些问题_2

  • 靠墙之后什么都看不见.

P85_4 Hide the Character When Camera is Too Close to the Mesh

P86_ Hitting the Character

P86_1 创建 Hit Montage

P86_2 ProjectileOnHit

P86_3 修改并检查Projectile 的 Collision 的碰撞设置

P86_4 安装 Hit React AnimMontage Slot

P86_5 Multicast HitReact Montage

  • NetMulticast In BlasterCharacter.

  • Projectile Call Multicast RPC Of Character.

  • NetMulticast Unreliable.

P86_6 取消胶囊体会对子弹产生影响

P86_6_1 给 角色 Mesh 创建单独的 ObjectType

P86_6_2 设置 Projectile 的 CollisionResponse

P86_6_3 设置角色Mesh

P87_ Smooth Rotation for Proxies

  • 利用 OnRep_ReplicatedMovement , 让 TurnInPlace逻辑更加平滑.
  • Aim Offset 的时候一直在抖动.

  • 发生这种抖动的原因是我们在动画蓝图中进行这个Rotate Root Bone 逻辑 ,动画蓝图的更新频率比正常的Tick频率要小的多.
  • 所以动画蓝图的 Rotate Root Bone 节点对于网络复制的 Movement 来说并不是一个好的解决方案 , 所以我们不会旋转根骨骼 for simulate proxies , 我们需要做的是直接旋转角色 , 当我们的角色旋转控制器.

P87_1 在Tick中区分LocallyRole

  • if we are simulatedProxy we Rotate Character Directely.
  • if we are not simulatedProxy we Rotate Root Bone In AnimBP.
  • In Other Words , we're locallly Controlle either on the server or a client.

P87_1_1 AimOffset()

P87_1_2 SimProxiesTurn()

P87_1_3 AnimBP

  • 利用创建的变量区分一下.

P87_2 解决在 SimulateProxy端 瞄准偏移 Pitch 失效的问题

P87_2_1  CalculateAP_Pitch()

  • 创建方法我们需要复用这段逻辑.

P87_2_2 Call in AimOffset()

P87_2_3 Call in SimProxiesTurn()

P87_3  Turn In Place In SimulateProxy _V1

P87_3_1 测试结果

  • 打印字符串测试.

  • 存在为0的情况 , 说明我们在 SimulateProxy Net Update 更新的频率 , 比 Client Locally Controlled 的 AotomomousProxy 的更新频率要慢.

P87_3_2 想个办法解决吧

  • This is where replicated movement comes in , every time movement is replicated to a character , there is a rep notify that will be called.
  • So we can't calling SimuProxiesTurn() every frame , We Only want to Call this when our simulated proxy gets its movement updated , and that's where OnRep replicated movement comes in.
  • So We overwrite it !!!

  • 重写.

  • So whenever our actos movement changes and is replicated . this rep notify will be called ,So we can use this instead of the tick function when checking the delta for our character's rotation for simulate proxy.

P87_3_3 取消 SimProxiesTurn() 在 Tick 中的调用.

P87_4 Code 不知道起啥标题了

P87_4_1 Tick

void ABlasterCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	//ROLE_None UMETA(DisplayName = "None"),		== 0
	//ROLE_SimulatedProxy UMETA(DisplayName = "Simulated Proxy"),    == 1
	//ROLE_AutonomousProxy UMETA(DisplayName = "Autonomous Proxy"),  == 2
	//ROLE_Authority UMETA(DisplayName = "Authority"),  == 3


	if (GetLocalRole() > ENetRole::ROLE_SimulatedProxy && IsLocallyControlled()) { //Autonomous And Server Locally Control
		AimOffset(DeltaTime);
	}
	else {												//  Simulated
		//the reason we're keeping track of this is because if thistime reaches a certain amount , meaning
		//we haven't had our movement relicated lately , i'd like to call OnRep+Movement directly.
		//不移动时每0.25秒强制调用 OnRep_ReplicatedMovement();
		TimeSinceLastMovemntReplication += DeltaTime;
		if (TimeSinceLastMovemntReplication > 0.25f) {
			OnRep_ReplicatedMovement();
		}
		CalculateAO_Pitch();
	}

	HideCameraIfCharacterClose();
}

P87_4_2 OnRep_ReplicatedMovement

P87_4_3 SimProxiesTurn()

  • 取消对 CalculateAO_Pitch(); 的调用.

P87_5 滑动

  • 快速旋转奔跑时会滑动.
  • That's Because We're Not Setting out turning status back to not turning as soon as we start running.
  • 当速度大于零时,让其快速结束 TurnInPlace 行为.

P87_6 总结一下

P88_ Automatic Fire

  • 本节不涉及网络内容.

P88_1 FireButtonPressed()

P88_2 Fire()

P88_3 StartFireTimer()

P88_4 FireTImerFinished

P89_ Testing the Game

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值