Blaster - Multiplayer P65-PXX : 射击武器
P65_ Projectile Weapon Class
- 这个项目设计两种武器类型,一种为发射射线检测,另一中为发射真实的 Projectile.
- 这一节我们创建了一个武器的子类 ProjectileWeapon 用于为发射Projectile 的武器类型.
- 创建了 Projectile 类 用于发射.
P66_ Fire Montage
- 本节不涉及网络内容.
P67_ Fire Weapon Effects
- 本节不涉及网络内容.
P68_Fire Effects in Multiplayer - Fire Rep
P68_1 试错 RunOnServer RPC
P68_1_1 Character FireButtonPressedInput
- 这个方法仅在本地端控制的角色上调用.
P68_1_2 CombatComponent::FireButtonPressed
- 简洁版代码为这个,因为这个方法仅在本地端控制的角色上调用 , 所以这两个代码等价,但是我为了逻辑的严谨性还是加上了条件判断.
P68_2 现象
P68_2_1 Server HoldWeapon Fire
- 当Server持枪开火的时候 , 只有Server 端可以看见开火,声音和特效.
- 按照我得理解解释一下,当Server Locally 开火的时候调用的是ServerFire(),因为Server 端不会进行RPC , 所以 只有 Server 本地端能够看见开火 , 同步不到其客户端.我们之前捡起枪的逻辑可以同步给客户端是因为 Weapon Class bReplicate = true , 他自己就同步行为了.
P68_2_2 Client HoldWeapon Fire.
- 当 Client 持枪开火的时候 , 只有Server 端可以看见开火,声音和特效.
- 按照我观察上面的代码啊,客户端调用的是RPC,在客户端上调用的,在服务端上执行,额确实是在服务端执行了 , 但由于RPC里面的内容不是复制的,所以我们本地的 Client Locally Control 没有开火的效果.
P68_2_3 分析
- 温故而知新诶 , 按照我们之前装备武器的逻辑 , 如果我们想要 RunOnServer RPC 出来效果 , 那么RPC方法里面的内容需要是复制的 , 所以这里我们需要用 Multicast RPC方法.
P68_2_4 bFireButtonPressed
- 我们之所以不将bFireButtonPressed做成 replicated , 因为我们每次开火不会将 这个bool值改变 , 值不变 就不会发生复制行为 , 所以满足不了我们的需求.
P68_3 Multicast RPC
- Multicast Server RPC 在 Server 上调用 , 在所有客户端执行.
P69_ The Hit Target
- Determine The Shoot Direction.
P69_1 创建了一个基于屏幕中心确定瞄准方向的方法
void UCombatComponent::TraceUnderCrosshairs(FHitResult& TraceHitResult)
{FVector2D ViewportSize;if (GEngine && GEngine->GameViewport) {GEngine->GameViewport->GetViewportSize(ViewportSize);}FVector2D CrosshairLocation = FVector2D(ViewportSize.X/2.0f, ViewportSize.Y/2.0f);FVector CrosshairWorldPosition;FVector CrosshairWorldDirection;bool bScreenToWorld = UGameplayStatics::DeprojectScreenToWorld(UGameplayStatics::GetPlayerController(this,0),CrosshairLocation,CrosshairWorldPosition,CrosshairWorldDirection);if (bScreenToWorld) {FVector Start = CrosshairWorldPosition;FVector End = Start + CrosshairWorldDirection * TRACE_LENGTH;GetWorld()->LineTraceSingleByChannel(TraceHitResult,Start,End,ECollisionChannel::ECC_Visibility);if (!TraceHitResult.bBlockingHit) {TraceHitResult.ImpactPoint = End;}else {DrawDebugSphere(GetWorld(),TraceHitResult.ImpactPoint,12.0f,24,FColor::Red,false, //Persistent0.0f, //duration0, //Depth3.0f);}}}
P69_2 在Tick中调用
void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{Super::TickComponent(DeltaTime, TickType, ThisTickFunction);FHitResult HitResult;TraceUnderCrosshairs(HitResult);
}
P70_Spawn Projectile
- 本节编写了开火时向前生成并发射 Projectile 的逻辑 , 并无网络内容.
P71_ Projectile Movement Component
- 组件自己处理了 Movement Replication 非常 Nice.
P71_1 这里插播一个知识点.
- 做抛物线不一定用样条线,我们可以设置 ProjectileMovementComponent->bRotationFollowsVelocity = true; 沿着速度方向旋转!!!.