After Tim made the environment and assets, it was my turn to bring slendy to life. The original version had some tricky stuff in it, such as the spawn logic for slendy. It took some time and a bit of trial-and-error to get it just right. Slendy had to be unpredictable, which is, from a technical point of view, pretty much impossible. The result was quite close to unpredictable though, and even Tim and I got a fair amount of scares during development.

Title

Programming and behavior

I started work on figuring out how exactly the spawning should happen. First of all, the slenderman must not actually move, he can only teleport. Second, the player may never see the slenderman teleport, neither becoming visible in his field of view nor disappearing when looking at him. Slendy must never be spawned in a tree or a rock and he has to be facing the player. He also must be at the correct height, that is the height of the floor under him. Finally, the spawn logic must be configurably throughout the game. As the player progressed by finding notes, slendy should get more aggresive while chasing him.

Spawn area

Once I got an idea of the rules slendy must obey, I began work on the spawn algorithm. I had some help from Michel, who got the idea of splitting it up into two steps.

Step 1 included deciding the direction relative to the player in which slendy would spawn. The full radius around the player consists of 360 degrees. We especially want control over how far to the front of the player the slenderman will spawn, so we split the area up into 2 half circles of 180 degrees. This made things easier, because we could generate a random number from 0 to 180, getting closer to the player’s face the larger the number gets. By inverting the value half of the time, we still covered both sides.

The spawnable area

The spawnable area in debug view, fully configurable per note

Step 2 described the actual distance between slendy and the player. Because the distance to the player should be somewhat random as well, I fitted in a range system, in which we could define between what bounds the spawning can happen. The image above shows the radius lines (the two red ones in front of the player and the green ones overlapping on the rear), along with the range lines, the white dashed circles. Because this system is pretty fast, I can simply teleport slendy, check if he collides with something like a tree and teleport again if he does.

Timing

Now I had an area where slendy could spawn. Next step was a timed execution of the actual teleporting. So every now and then, slendy may move to a new position. What we were looking for, is that typical, classic horror feel: you would look at him, look away, then look at him again to find that he’s gone. It somehow induces a sense of panic, because you just lost control over a scary and dangerous guy. I went for a pretty simple system, with a timer that counted to a set amount of time. The amount of time was configurable per collected note. Each time the timer reached the limit, there is a certain chance that slendy would teleport. The actual chance is also configurable per collected note.

For every note the player collected, the teleport interval decreased and the teleport probability increased. This made slendy more active with each collected note.

Before actually considering to teleport slendy, the game decides whether the player can see him or not. If so, we should not move him. This decision making was one of the harder parts to accomplish. For this I again went for a two-step approach. First, I check if the slenderman is in a rough line of sight of the player, whether his position is within a certain angle relative to the player. When the first check passes, I then start doing a check on obstacles that may prevent slendy from being visible to the player.

Initially, I did a raycast from the player’s camera to the slenderman’s center. This kind of worked, but was quite imperfect because of the large amounts of trees that block this ray but not the entire view. So the ray was interrupted and slendy could be teleported while the player was still actually able to see him. To get around this, I added multiple points around the player and multiple points around slendy.

Slendy in full view

Slendy in full view, all lines are directly connected, without interruptions

Now I sent rays from the player’s camera, somewhat left of the camera and somewhat right of the camera. From these 3 positions, rays are shot to different points at slendy’s position. The amount of target points and their positions relative to slendy, are configurable. So now I had around 15 rays going from the player to slendy. When at least one of these rays is not interrupted by a tree, a rock or a wall, the player could probably see slendy and we should not do a teleport.

Slendy in partial view

Partial view of slendy, some lines are interrupted

Slendy in partial view from player

Same view from the player’s perspective, slendy is partially visible

public bool IsInLineOfSight()  
{
    Vector3 cameraPosition = playerCamera.transform.position;
    Vector3 to = slenderMan.slenderTransform.position;
    Quaternion playerRotation = playerTransform.rotation;
    Quaternion slendyRotation = slenderMan.slenderTransform.rotation;

    Vector3 originOffset;
    Vector3 castOffset;
    RaycastHit hit;
    for (int j = 0; j < rayCastOriginOffsets.Length; j++)
    {
        originOffset = playerRotation * rayCastOriginOffsets[j];
        for (int i = 0; i < rayCastOffsets.Length; i++)
        {
            castOffset = slendyRotation * rayCastOffsets[i];
            if (Physics.Raycast(cameraPosition + originOffset, ((to + castOffset + raycastOffset) - cameraPosition).normalized, out hit))
            {
                if (hit.transform.GetComponent())
                {
                    return true;
                }
            }
        }
    }

    return false;
}

Chasing

At this point, the slenderman was doing some nice teleporting and scaring us now and then. We encountered a new problem however. When the player would stand still for a longer amount of time, slendy didn´t actually come closer. That would only happen when the player found a note. So I added a mechanic called ‘chase mode’, which made him come closer even when you´re not finding new notes. As long as the player didn´t see slendy, the spawn area would not change and slendy would keep his distance for the first set of notes. When the player got a glimpse of him however, chase mode would activate.

Chase mode activated

Chase mode activated, the red line illustrates the distance to slendy that the player must have before chasing will stop.

While chase mode is active, the spawn area shrinks every set amount of time. To deactivate chase mode, the player should out-run him by clearing a set distance between himself and slendy before he teleports again. Both the shrink time and distance it took to shake him, are configurable per found note. Of course, with every found note the shrink time becomes less and the shake distance greater.

Especially after finding a few notes, this can become really eerie. The slenderman is really chasing you and the game gets more creepy.

The last bit of logic that needed to be implemented, was slendy’s positioning. He needed to spawn at the correct height, which varied throughout the level. It could be the reason that the original slender game had a flat ground, because it also makes detection of visibility by the player a whole lot harder. I fixed this by placing all walkable geometry in a seperate layer and sending a ray down to the terrain. Then I could read the z-value of the point where the ray hit and use that for slendy’s new location. To complete the teleport, slendy’s rotation is adjusted any frame the player is not looking at him. This way, he will always look directly at the player, even after walking around him.

// Look at player
Quaternion delta = Quaternion.LookRotation(slenderMan.slenderTransform.position - playerTransform.position);  
delta.x = 0f;  
delta.z = 0f;  

One last thing that is worth mentioning, is the bats effect. I placed a spherical collider around a couple of trees and put a bit of code on them which detects the player walking through them. When he does, there is a certain chance that the bats - which is a particle effect - triggers. There is a certain minimum amount of time before a second batch of bats can be triggered, so you won’t get them every 10 seconds.

The sperical trigger on one of the trees

The spherical trigger on one of the trees

I really don’t want to bother you with the post-processing effects, they are way too boring to explain in detail. The only thing you might want to know, is that it’s a combination of vignetting (darkened edges), noise with scratches, vortex deforming (skews the view to add a bit of disorientation), depth of field to get the distant level features blurred, motion blur to add a dramatic effect when the player suddenly turns around, extra contrast and a grayscale to get the old movie-feel.

And that’s how we made SlenderMod. The rest of the time, we were tweaking and playing to see how it all feels. There are some situations where people would not see slendy for the entire game, but we knew that could happen. It basically is the risk of making the AI so unpredictable. We made the game in a week or 3, using the Unity 3D engine. You can take a look at, or download the source code at GitHub, even use it to make your own version of the game.

And oh, there’s someone behind you.

There's someone behind you