之前一直没搞懂按下鼠标左键开火之后,代码的逻辑是怎么走的,今天看懂了之前没看懂的部分,进了一步

ShooterCharacter.cpp

void AShooterCharacter::OnStartFire()
{
AShooterPlayerController* MyPC = Cast<AShooterPlayerController>(Controller);
if (MyPC && MyPC->IsGameInputAllowed())
{
if (IsRunning())
{
SetRunning(false, false);
}
StartWeaponFire();
}
}
void AShooterCharacter::StartWeaponFire()
{
if (!bWantsToFire)
{
bWantsToFire = true;
if (CurrentWeapon)
{
CurrentWeapon->StartFire();
}
}
}

ShooterWeapon.cpp,其中Role==ROLE_Authority表示该程序运行在服务器。如果是客户端,则将调用ServerStartFire来调用服务端的StartFire方法。这是多人游戏中的机制

void AShooterWeapon::StartFire()
{
if (Role < ROLE_Authority)
{
ServerStartFire();
} if (!bWantsToFire)
{
bWantsToFire = true;
DetermineWeaponState();
}
}
void AShooterWeapon::DetermineWeaponState()
{
EWeaponState::Type NewState = EWeaponState::Idle; if (bIsEquipped)
{
if( bPendingReload )
{
if( CanReload() == false )
{
NewState = CurrentState;
}
else
{
NewState = EWeaponState::Reloading;
}
}
else if ( (bPendingReload == false ) && ( bWantsToFire == true ) && ( CanFire() == true ))
{
NewState = EWeaponState::Firing;
}
}
else if (bPendingEquip)
{
NewState = EWeaponState::Equipping;
} SetWeaponState(NewState);
}
void AShooterWeapon::SetWeaponState(EWeaponState::Type NewState)
{
const EWeaponState::Type PrevState = CurrentState; if (PrevState == EWeaponState::Firing && NewState != EWeaponState::Firing)
{
OnBurstFinished();
} CurrentState = NewState; if (PrevState != EWeaponState::Firing && NewState == EWeaponState::Firing)
{
OnBurstStarted();
}
}
void AShooterWeapon::OnBurstStarted()
{
// start firing, can be delayed to satisfy TimeBetweenShots
const float GameTime = GetWorld()->GetTimeSeconds();
if (LastFireTime > && WeaponConfig.TimeBetweenShots > 0.0f &&
LastFireTime + WeaponConfig.TimeBetweenShots > GameTime)
{
GetWorldTimerManager().SetTimer(TimerHandle_HandleFiring, this, &AShooterWeapon::HandleFiring, LastFireTime + WeaponConfig.TimeBetweenShots - GameTime, false);
}
else
{
HandleFiring();
}
}

下面标红的FireWeapon这个函数,实际上在AShooterWeapon中是一个虚函数,并且没有实现,实现是放在了子类中。它有两个子类,分别是AShooterWeapon_Instant(弹道类)和AShooterWeapon_Projectile(投掷类)

我觉得肯定真正使用到的类就是这两个子类,所以包括之前的这个流程,实际上都是子类中的,只不过是从父类中继承而已,当然我此时此刻没有去深究那些方法的可见性修饰符,是否会被继承这些细节问题,我先暂时这么认为吧

void AShooterWeapon::HandleFiring()
{
if ((CurrentAmmoInClip > || HasInfiniteClip() || HasInfiniteAmmo()) && CanFire())
{
if (GetNetMode() != NM_DedicatedServer)
{
SimulateWeaponFire();
} if (MyPawn && MyPawn->IsLocallyControlled())
{
FireWeapon(); UseAmmo(); // update firing FX on remote clients if function was called on server
BurstCounter++;
}
}
else if (CanReload())
{
StartReload();
}
else if (MyPawn && MyPawn->IsLocallyControlled())
{
if (GetCurrentAmmo() == && !bRefiring)
{
PlayWeaponSound(OutOfAmmoSound);
AShooterPlayerController* MyPC = Cast<AShooterPlayerController>(MyPawn->Controller);
AShooterHUD* MyHUD = MyPC ? Cast<AShooterHUD>(MyPC->GetHUD()) : NULL;
if (MyHUD)
{
MyHUD->NotifyOutOfAmmo();
}
} // stop weapon fire FX, but stay in Firing state
if (BurstCounter > )
{
OnBurstFinished();
}
} if (MyPawn && MyPawn->IsLocallyControlled())
{
// local client will notify server
if (Role < ROLE_Authority)
{
ServerHandleFiring();
} // reload after firing last round
if (CurrentAmmoInClip <= && CanReload())
{
StartReload();
} // setup refire timer
bRefiring = (CurrentState == EWeaponState::Firing && WeaponConfig.TimeBetweenShots > 0.0f);
if (bRefiring)
{
GetWorldTimerManager().SetTimer(TimerHandle_HandleFiring, this, &AShooterWeapon::HandleFiring, WeaponConfig.TimeBetweenShots, false);
}
} LastFireTime = GetWorld()->GetTimeSeconds();
}
void AShooterWeapon_Instant::FireWeapon()
{
const int32 RandomSeed = FMath::Rand();
FRandomStream WeaponRandomStream(RandomSeed);
const float CurrentSpread = GetCurrentSpread();
const float ConeHalfAngle = FMath::DegreesToRadians(CurrentSpread * 0.5f);

   //获取AShooterPlayerController的rotation的单位向量
const FVector AimDir = GetAdjustedAim();
const FVector StartTrace = GetCameraDamageStartLocation(AimDir);
const FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, ConeHalfAngle, ConeHalfAngle);
const FVector EndTrace = StartTrace + ShootDir * InstantConfig.WeaponRange; const FHitResult Impact = WeaponTrace(StartTrace, EndTrace);
ProcessInstantHit(Impact, StartTrace, ShootDir, RandomSeed, CurrentSpread); CurrentFiringSpread = FMath::Min(InstantConfig.FiringSpreadMax, CurrentFiringSpread + InstantConfig.FiringSpreadIncrement);
}

UE4 ShooterGame Demo的开火的代码的更多相关文章

  1. 微信JS-SDK DEMO页面和示例代码

    <?php require_once "jssdk.php"; $jssdk = new JSSDK("yourAppID", "yourApp ...

  2. 极客验证官方demo构建使用及代码分析

    #什么是极客验证? 官方定义:极验验证是一种在计算机领域用于区分自然人和机器人的,通过简单集成的方式,为开发者提供安全.便捷的云端验证服务. #使用命令从github上获取: git clone ht ...

  3. linux poi生成excel demo调试附调用代码

    1.下载poi-3.9-20121203.jar包 2.java code package com.userpackage; import java.io.FileOutputStream; impo ...

  4. spring-retry简单demo(附完整代码)

    重试 最近项目要用到重试.开始想自己写,后来想用RetryTemplate,最后想到既然项目用了springboot,还是直接集成spring-retry把. 代码 Application packa ...

  5. 微信小程序DEMO——面包旅行的代码

    API 集合在一起写了一个页面,并导出, const apiURL = 'http://xxx.xxxx.com'; const trip = { hot(data,callback){ wx.req ...

  6. ue4 shooterGame 第一步 搭建git linux服务器

    1.分别在linux(服务器)上安装git.和openssh服务, 在windows(客户机)上安装cygwin,模拟linux环境以及安装windows git客户端. 2.windows的cygw ...

  7. h5 网络断网时,返回上一个页面 demo (与检测网络代码相结合,更直观看到结果)

    页面一: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8& ...

  8. 李宏毅 Gradient Descent Demo 代码讲解

    何为梯度下降,直白点就是,链式求导法则,不断更新变量值. 这里讲解的代码为李宏毅老师机器学习课程中 class 4 回归展示 中的代码demo   Loss函数 python代码如下 import n ...

  9. 如何创建独立的UE4服务端

    原文作者:@玄冬Wong 转载请注明原文出处:http://aigo.iteye.com/blog/2268777 这是论坛上对UE服务端功能的回答,意思是UE4提供了主流MMO网游服务端所具备的特性 ...

随机推荐

  1. python中“*”、"*args"、"kwargs"三种用法

    参考链接:https://www.cnblogs.com/cwind/p/8996000.html 注意的是: (1)"*"符号的用法很类似C++中的指针,针对列表; (2)&qu ...

  2. css3新属性运用

    1.css3新单位vh.vw,这个单位是相对显示窗口的宽度或高度 vh等于viewport高度的1/100.例如,如果浏览器的高是900px,1vh求得的值为9px.同理,如果显示窗口宽度为750px ...

  3. HTTP协议05-Web服务器

    1)用单台虚拟主机实现多个域名 HTTP/1.1规范允许一台HTTP服务器搭建多个Web站点.比如,提供Web托管服务的供应商,可以用一台服务器为多位客户服务,也可以以每位客户持有的域名运行各自不同的 ...

  4. 浅谈2017noip信息奥赛普及组试题

    [话前叨叨] 一些日常刷题策略(转载): PS:本题的题目信息来自洛谷平台 下面就是进入正题了(其实这也是我第一次在csdn写博客,所以写的不好的地方也请大家多多谅解和提点/微笑/) 一.score ...

  5. Codeforces 914D - Bash and a Tough Math Puzzle 线段树,区间GCD

    题意: 两个操作, 单点修改 询问一段区间是否能在至多一次修改后,使得区间$GCD$等于$X$ 题解: 正确思路; 线段树维护区间$GCD$,查询$GCD$的时候记录一共访问了多少个$GCD$不被X整 ...

  6. HDU - 1160 FatMouse's Speed 动态规划LIS,路径还原与nlogn优化

    HDU - 1160 给一些老鼠的体重和速度 要求对老鼠进行重排列,并找出一个最长的子序列,体重严格递增,速度严格递减 并输出一种方案 原题等于定义一个偏序关系 $(a,b)<(c.d)$ 当且 ...

  7. 转-CSRF——攻击与防御

    0x01 什么是CSRF攻击 CSRF是Cross Site Request Forgery的缩写(也缩写为XSRF),直译过来就是跨站请求伪造的意思,也就是在用户会话下对某个CGI做一些GET/PO ...

  8. Android-创建一个简单的用户接口-(补day2内容)

    如果按照之前的布局设置,那么输入框和按钮组件的大小就会是刚好满足它们的内容的.如图1. 图1.输入框和按钮宽度设置为”wrap_content” 这样的设置是可以满足按钮的,但不能满足输入框的要求,因 ...

  9. python 基础 Two day

    1.格式化输出 %s   字符串 %d   数字 %%  转义 % %f   小数 现在有以下需求,让用户输入name, age, job,hobby 然后输出如下所示: ------------ i ...

  10. Day7--------------IP地址与子网划分

    1.ip地址:32位    172.16.45.10/16 网络位:前十六位是网络位 主机位:后16位是主机位 网络地址:172.16.0.0 主机地址:172.16.45.10 A类: 0NNNNN ...