UE4 ShooterGame Demo的开火的代码
之前一直没搞懂按下鼠标左键开火之后,代码的逻辑是怎么走的,今天看懂了之前没看懂的部分,进了一步
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的开火的代码的更多相关文章
- 微信JS-SDK DEMO页面和示例代码
<?php require_once "jssdk.php"; $jssdk = new JSSDK("yourAppID", "yourApp ...
- 极客验证官方demo构建使用及代码分析
#什么是极客验证? 官方定义:极验验证是一种在计算机领域用于区分自然人和机器人的,通过简单集成的方式,为开发者提供安全.便捷的云端验证服务. #使用命令从github上获取: git clone ht ...
- linux poi生成excel demo调试附调用代码
1.下载poi-3.9-20121203.jar包 2.java code package com.userpackage; import java.io.FileOutputStream; impo ...
- spring-retry简单demo(附完整代码)
重试 最近项目要用到重试.开始想自己写,后来想用RetryTemplate,最后想到既然项目用了springboot,还是直接集成spring-retry把. 代码 Application packa ...
- 微信小程序DEMO——面包旅行的代码
API 集合在一起写了一个页面,并导出, const apiURL = 'http://xxx.xxxx.com'; const trip = { hot(data,callback){ wx.req ...
- ue4 shooterGame 第一步 搭建git linux服务器
1.分别在linux(服务器)上安装git.和openssh服务, 在windows(客户机)上安装cygwin,模拟linux环境以及安装windows git客户端. 2.windows的cygw ...
- h5 网络断网时,返回上一个页面 demo (与检测网络代码相结合,更直观看到结果)
页面一: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8& ...
- 李宏毅 Gradient Descent Demo 代码讲解
何为梯度下降,直白点就是,链式求导法则,不断更新变量值. 这里讲解的代码为李宏毅老师机器学习课程中 class 4 回归展示 中的代码demo Loss函数 python代码如下 import n ...
- 如何创建独立的UE4服务端
原文作者:@玄冬Wong 转载请注明原文出处:http://aigo.iteye.com/blog/2268777 这是论坛上对UE服务端功能的回答,意思是UE4提供了主流MMO网游服务端所具备的特性 ...
随机推荐
- LwIP Application Developers Manual4---传输层之UDP、TCP
1.前言 本文主要讲解传输层协议UDP TCP 2.UDP 2.1 UDP from an application perspective 2.2 UDP support history in lwI ...
- git与eclipse集成之文件回退
1.1. 文件回退 1.1.1. 添加或修改文件回退,选择要回退的文件,右键Overwrite 1.1.2. 删除文件回退 选择要回退的文件,右键Overwrite 文件变 ...
- 使用vue-cli初始化vue项目
在项目中使用vue我使用vue-cli脚手架搭建项目 1.先安装nodejs 2.使用npm install -g vue-cli (建议在使用这步前先安装nrm来切换npm的源利器,使得下载资源更快 ...
- https 对 json空对象解析的影响
2017年11月24日09:56:01 记录一个问题: PHP返回json给APP(安卓, fastjson) 其中一个值是空对象 json_encode( [ 'aaa' => new st ...
- mysql 命令行常用命令
1.显示数据库列表. show databases; 2.显示库中的数据表: use mysql; show tables; 3.显示数据表的结构: describe 表名; 4.建库: cr ...
- oracle:10g下载地址(转载)
转载地址:http://www.veryhuo.com/a/view/177074.html Oracle 10g Database和Client多平台官方下载地址 http://www.veryhu ...
- HDU 5377 (Exgcd + 原根)
转载自:大牛 知道一个定理了 a ^ x = y (mod p) ===>> logd(a) * x = logd(y) (mod O(p) ) d 为 p 的 原根, O ...
- 彻底删除mysql服务(清理注册表)
前言 由于安装某个项目的执行文件,提示要卸载MySQL以便它自身MySQL安装,然后我禁用了MYSQL服务,再把这个文件夹删除后,发现还是提示请卸载MYSQL服务. ----------------- ...
- 加载UI工程的csb,以及纹理缓存情况
以plist+PNG模式加载csb,并播放UI工程做的动画,用法如下 local Layer = cc.CSLoader:createNode("res/yk/interface/loadi ...
- 10)django-ORM(创建,字段类型,字段参数)
一:ORM关系对象映射(Object Relational Mapping,简称ORM) ORM分两种: DB first 先在数据库中创建数据库表等 Code first 先创建类,然后根据类创建数 ...