First-Person Shooter: Raycast weapon
This is Elympics First-Person Shooter tutorial: part 7. In this part we’ll be creating raycast gun. See: Part 6.
Raycast gun
The second weapon type to implement is a raycast-damage gun. Just like RocketLauncher
, it will inherit from the Weapon
class, but due to the use of raycast, it will not require additional scripts such as bullet or explosion area.
Let's go straight to the implementation:
public class RailGun : Weapon
{
[Header("Parameters:")]
[SerializeField] private float loadingTime = 1.0f;
[SerializeField] private float damage = 50.0f;
[Header("References:")]
[SerializeField] private new Camera camera = null;
private ElympicsFloat currentLoadingTime = new ElympicsFloat(0.0f);
private ElympicsBool isLoadingToShot = new ElympicsBool(false);
public event Action<float, float> LoadingTimeChanged;
public event Action<RaycastHit> WeaponFired;
public override void Initialize()
{
base.Initialize();
currentLoadingTime.ValueChanged += HandleCurrentLoadingTimeChanged;
}
protected override void ProcessWeaponAction()
{
if (isLoadingToShot)
return;
currentLoadingTime.Value = 0.0f;
isLoadingToShot.Value = true;
}
public override void ElympicsUpdate()
{
base.ElympicsUpdate();
if (isLoadingToShot)
{
if (currentLoadingTime.Value >= loadingTime)
{
ChangeCurrentLoadingTime(0.0f);
isLoadingToShot.Value = false;
}
else
{
ChangeCurrentLoadingTime(currentLoadingTime.Value + Elympics.TickDuration);
}
}
}
private void HandleCurrentLoadingTimeChanged(float lastValue, float newValue)
{
if (lastValue >= loadingTime && newValue < loadingTime)
ProcessRayShot();
}
private void ProcessRayShot()
{
RaycastHit hit;
if (Physics.Raycast(camera.transform.position, camera.transform.forward, out hit, Mathf.Infinity))
{
if (hit.transform.TryGetComponent<StatsController>(out StatsController statsController))
{
statsController.ChangeHealth(-damage, (int)PredictableFor);
}
}
WeaponFired?.Invoke(hit);
ChangeCurrentLoadingTime(0.0f);
isLoadingToShot.Value = false;
}
public override void SetIsActive(bool isActive)
{
base.SetIsActive(isActive);
if (!isActive)
isLoadingToShot.Value = false;
ChangeCurrentLoadingTime(0.0f);
}
private void ChangeCurrentLoadingTime(float newCurrentLoadingTime)
{
currentLoadingTime.Value = newCurrentLoadingTime;
LoadingTimeChanged?.Invoke(currentLoadingTime, loadingTime);
}
}
The parameters that determine the weapon are the damage it deals after hitting the player with a raycast and the recharge time. Unlike the RocketLauncher, this weapon won’t fire immediately after a click but will start the loading operation and will only fire after a certain amount of time. To be able to use raycasts precisely, this component needs a reference to the player's main camera.
Calling the main method through ProcessWeaponAction
first checks if the weapon is being loaded. If not - the timer responsible for loading the weapon is reset and a flag is set that determines the loading status of the weapon.
ElympicsUpdate
checks if the timer has reached the value needed for the weapon to fire. If so, the ProcessRayShot
method is called.
The ProcessRayShot
method is responsible for using the raycast and checking whether it hit the object with the StatsController
component - if so, the ChangeHealth
method is called on it, whose argument is the previously defined damage value. Finally, all variables are reset and the weapon is ready to be used again.
Having the raycast gun class prepared we can create a raycast gun prefab. For this purpose, as in the case of RocketLauncher
, we create an Empty Game Object and immediately add another Empty Game Object to it, which will be a container and a mesh.
Next, we add the previously created script to the parent object "RailGun" and create a prefab from this object.
Then we add the prepared prefab to the FirstPersonViewContainer
component in the player's prefab, positioning it appropriately and adding a reference to the player's camera.
We also add prefab to the list of available weapons in the LoadoutController
in the parent player object.
Let's try a new weapon!
From now on, players can use both bullet projectile weapons and raycast weapons!
In the next part we'll focus on player's respawn! 💀➞🕺