Skip to content

Preparing to Make the Glimmerstalkers Actually Stalk

Today was about getting a start on implementing the Glimmerstalker's Stalking state. Before I could really start working on that though, I wanted to take some time to refactor pieces of the existing Glimmerstalker script to change how they pick positions to Harass from and when the physical body is shown.

Previously, the Glimmerstalker picked a random target to "hover" around when Harassing and had a physical body.

Screenshot of the Glimmerstalker in the background

While the physical body was only meant as a temporary placeholder, it posed a couple of problems:

  1. When we go to add dialog to the Glimmerstalker, it will always show up right next to one of the crew (or the Player)
  2. Related, but when going into the Stalking state, it will always be right next to them
  3. Because the body has collision, it would push the Crew or the Player around as it tried to get to them
    1. This was exacerbated because the collision on it was massive

While pretty hilarious, overall it wasn't the vibe we want. I needed to refactor in order to address the above issues.

Gif of the Glimmerstalker pushing the body of a Crew member along the ground after they died

Poor, poor Jayden...even in death he is harassed!

Reworking the Harassing State

I wanted to make the following changes to the Harassing state:

  1. Remove the physical body and colliders unless the Glimmerstalker was in the Attack state
    1. This was always the intention, since we only wanted the body actually visible when it is charging the character
    2. This would also take care of the characters being pushed around
  2. Change the Glimmerstalker to teleport to different positions when Harassing instead of using the NavMeshAgent
    1. This would allow us to not need collision/NavMeshAgent active when it is invisible
  3. Adjust the collision on the Glimmerstalker for when it is shown

Removing the physical body and the NavMeshAgent, for now, was easy. I just disabled their respective components/GameObjects in the prefab and went about my day. I also adjusted the collision while I was at it

General Refactoring

While implementing all of this, I also refactored quite a bit of the surrounding code to extract different pieces into more reusable chunks and to move some logic into better spots. One of the bigger pieces was extracting out the "is protected by light" logic into its own component that the Crew and Player scripts utilize, instead of being lumped in with the IGlimmerstalkerTarget interface. It centralized a lot of the logic and provided a much cleaner interface for the lights to work with.

using UnityEngine;

public class LightDetector : MonoBehaviour, IProtectedByLight
{
    private bool _isProtectedByLight = false;
    private float _timeOutsideLight = 0;

    private void Update()
    {
        if (_isProtectedByLight) return;

        _timeOutsideLight += Time.deltaTime;
    }

    public void OnEnterLight()
    {
        _isProtectedByLight = true;
        _timeOutsideLight = 0f;
    }

    public void OnExitLight()
    {
        _isProtectedByLight = false;
    }

    public bool IsProtectedByLight(float timeOutsideLightLimit)
    {
        if (_isProtectedByLight) return true;
        if (_timeOutsideLight < timeOutsideLightLimit) return true;

        return false;
    }
}

Now the "Repelling Lights" only have to know about the IProtectedByLight and IRepellable interfaces. Makes that nice and clean.

Making it Teleport

The next thing to tackle was getting it to teleport when Harassing. I decided to reuse the arc point logic I had made for the Crew flee point selection. This should ensure that the Glimmerstalker is on a valid point on the NavMesh for when we reenable the NavMeshAgent and body. It also makes it harder to "track" the Glimmerstalker, which adds to the mystery and makes it harder to guess where it will charge from until it actually starts charging.

Screenshot of the Glimmerstalker Harassment Point arcs around the Caravan

Reworking the Harassment Actions

Since I was reworking all of the stuff surrounding the Harass state, I figured I might as well redo the Harassment Actions because they were a little barebones. There were some variables that were being set at the Glimmerstalker-level that should have been set at the Action level (like number of targets) and I was trying to figure out what was needed still and what wasn't.

I ended up converting the HarassmentAction class to be a ScriptableObject and added a list of them into the Glimmerstalker script, instead of the single hard-coded one we had before.

In the screenshot below, you can see the new list (as well as the "arc" related variables)

Screenshot of the Inspector showing the new Harassment fields on the Glimmerstalker prefab

Then, in the ScriptableObject itself, I had a similar structure, where it had a list of potential Morale Modifiers that could be applied, and their weights. The Weight field is a little deceptive because it looks like they need to add up to 1 but it actually uses a "weighted" random behinds the scenes, meaning it sums all the weights then uses that as the basis for checking, instead of requiring everything to equal 1.

Screenshot of the Inspector showing the Sibilant Whispers Harassment Action configuration