Unity released very good FPS example for
people and I decided to analysis how they make this. Personally I wanted to show
you how I analysis the games.
Class: Player Input Handler
What Player Input Handler class does is
controlling a player. It reference to GameFlowManager and get the state of
current game to ignore user input when game is finished.
To
Change Weapon
If user press 1, 2, 3 and so on, we can get
positive number and it is used in PlayerWeaponsManager class.
Class: Player Character Controller
PlayerCharacterController class controls
player’s character. Many properties are adjustable to game feel better. It uses
PlayerWeaponsManager to change weapon and Health Class. Health Class is
managing health for player and bots.(Both uses Health Class)
Class: PlayerWeaponsManager
At the beginning of the game player should
have weapon. Variable ‘startingWeapons’ contains initial weapon list.
Weapon
camera
Weapon has its own camera to render the
weapon on top of main camera. Default position of weapon uses
DefaultWeaponPosition. When User Press zoom (which is aiming), it will use
AimingWeaponPosition. Its x value is 0 which means aligned to 0 of x.
Aiming
When user press right button, Aiming is activated.
As soon as aiming is activated then all of camera’s FOV(field of view) is
changed. This effect will make zoom in. FOV Animation is code driven which
means changing FOV value is running by code.
void UpdateWeaponAiming()
{
if (m_WeaponSwitchState == WeaponSwitchState.Up)
{
WeaponController activeWeapon = GetActiveWeapon();
if (isAiming && activeWeapon)
{
m_WeaponMainLocalPosition = Vector3.Lerp(m_WeaponMainLocalPosition, aimingWeaponPosition.localPosition + activeWeapon.aimOffset, aimingAnimationSpeed * Time.deltaTime);
SetFOV(Mathf.Lerp(m_PlayerCharacterController.playerCamera.fieldOfView, activeWeapon.aimZoomRatio * defaultFOV, aimingAnimationSpeed * Time.deltaTime));
}
else
{
m_WeaponMainLocalPosition = Vector3.Lerp(m_WeaponMainLocalPosition, defaultWeaponPosition.localPosition, aimingAnimationSpeed * Time.deltaTime);
SetFOV(Mathf.Lerp(m_PlayerCharacterController.playerCamera.fieldOfView, defaultFOV, aimingAnimationSpeed * Time.deltaTime));
}
}
}
|
In here, we use aimingWeaponPosition and defaultWeaponPosition.
To
display crosshair hud
At the end of update function, raycast and
set the isPointingAtEnemy bool variable. This variable is used by CrosshairManager
which will display crosshair hud based on isPointingAtEnemy.
<Raycast
fail and no enemy>
<Raycast
success then CrosshairManager will show different hud>
Weapon
Change Animation
When user change the weapon, current weapon
position moves down and changed 3d model (actually hide current weapon and show
new weapon) and then move up. In this case, we use DownWeaponPosition.
Class: Jetpack
After user unlock Jetpack, user press
spacebar then player can fly. A relationship between PlayerCharacterController
and Jetpack is like down below.
Player’s movement uses characterVelocity. In
every update frame of Jetpack checks and applying additional velocity into
characterVelocity.
<<Gameplay Idea: Implement a skill ‘Relentless
Pursuit’ of Lucian in LOL or Tracer’s Blink>>
Class: Actor
When Actor is activated, we register itself
to ActorsManager actors container. ActorsManager doesn’t have any other logic.
Actor also has no logic at all but it has aimPoint variable. This variable is
for aiming. For instance bot is targeting a player then bot should have
specific target. The target will use aimPoint of Actor class.
Class: WeaponController
Every weapon objects has WeaponController
component. WeaponController represent weapon itself. Weapon type, decide which
projectile should use, bulletSpreadAngle (for shotgun), aimZoomRatio and so on.
Zoom
for sniper
For instance, we have sniper rifle then we
probably has zooming function more than pistol. In that case, we can use
aimZoomRatio. If we set animZoomRatio to be 0.3 for instance, then zoom is way
bigger than 0.7
<aimZoomRatio
0.7>
<aimZoomRatio
0.3>
Firing
In WeaponController, we instantiate
projectile prefabs. Function flow like down below.
HandleShootInputs
-> TryShoot -> HandleShoot
Bullet
position
Every generated bullets position set by weaponMuzzle.
In addition, muzzle flash effect is generated.
Prevent
firing too quickly
If we call HandleShoot function really quickly,
bullets will be generated. If we call HandleShoot every single time when user
press the button then bullets will be generated really quickly if user has
lighting speed hand! We have to prevent it. There is a variable m_LastTimeShoot
which will prevent calling a function really quickly. This is timing logic.
Class: EnemyController
Class: Damageable
There is a Health class, which represent
health of Player or Bot. To decrease player/bot health, there are two ways.
1.
Call TakeDamage method of health
class.
2.
Through Damageable, call
TakeDamage method of health class.
Number 2 used for projectiles. Number 1
used for player itself. (get damage by falling/environment or other reasons)
That is it for today. Next time I'll look how projectile works (probably collision detection), add more features such as spawner for bot, user's new skills (tracer blink!)
Hi, that's very interesting, thanks! I was wandering if it was possibile to make the input for mobile... I can't get out of this problem, could you help me some how?
ReplyDelete