How to make a Slender man follow character script

hi guys i was just wondering if anybody new how to make a script so that the ‘slenderman’ teleports to positions near the player, and gets closer and closer, sorry for the big ask but could anyone help me out?

#This Answer is now CLOSED#

Attention Slender Script Shoppers, this question will be closing in 2 minutes.

All future questions about my scripts will only be answered on the new forum page.

#Here is the link you are looking for#

Unity Forum : http://forum.unity3d.com/threads/172415-Slender-Guide-by-alucardj

I shall not be responding to any more posts here or any other question on Unity Answers either. All future traffic to my ‘Slender’ Guide is going to be solely through the forum page. Any questions that appear on Unity Answers will be closed and redirected to the forum page.

#If you post a new question on Unity Answers with my scripts, I shall bring the hammer down !#

While this may seem a little unfair, it is actually a good thing for all of your benefit. Every comment, change and update will appear there, for everyone to read and contribute to. No more searching through different questions just to get different parts of functionality, but everything you could need for starting your own horror survival game will be in one place. Doesn’t that sound convenient ?!

See You there =]


Slender Guide Version 2

While I have finished writing the code, I don’t have time to write a full guide explaining the steps taken and what I have coded in. I am changing the code in the below guide so people can still make their own rather than just using my package, and I really hope people write their own instead of just using my package.

Slender Guide Version 2 (I can only upload 5MB, so the project is very basic, but working!) : http://www.alucardj.net16.net/unityanswers/SlenderGuideV2-scene0.unitypackage

Fixed problems from Version 1 :

picking up papers in the editor - there were some issues with using LockCursor while running in the editor, hopefully these have been compensated for, recommend use the E key to pick up papers while running in the editor (but mouse still works).
some movement issues - I had no problem, but it was brought up so I have tweaked the movement script.

New features :

The more papers picked up, the Man follows closer.
Audio : when picking up paper, when the Man is first sighted, running and walking footsteps with adjustable audio gap between steps.
Custom mesh with fading alpha fullscreen static effect.

And don’t forget the awesome original flickering flashlight!

Here is the video link for the obstacle avoidance raycast : Obstacle Avoidance - Unity 3d on Vimeo

Comments and feedback are welcome, as long as you have something more to say than just it doesn’t work. The package proves it does. And please don’t ask new questions, post comments here. If this keeps going or more people have requests, I might have to start a Unity Forum page.

Enjoy =]


How to make a ‘Slender’ game by Jay Kay (alucardj)

1- Create the terrain, and add a first person controller

there are many tutorials on both these topics, here are some quick links :

video : CG Cookie | Learn Blender, Online Tutorials and Help - CG Cookie | Learn Blender, Online Tutorials and Feedback

written : http://wiki.unity3d.com/index.php?title=Terrain_tutorial

Some assets to help you out :

http://unity3d.com/support/resources/unity-extensions/terrain-toolkit

Also find some buildings (old shed, abandoned shack, etc) and anything you want to help the player use as ‘landmarks’ while searching around the terrain.

When you add a First Person Character Controller, Change the name of First Person Controller to Player.

2- Set the Ambience and Add a Flashlight

Here I am assuming you have created a terrain, added trees grass and buildings, and dropped in a first person character controller. Hopefully you have also pressed play and walked around the world you have created.

To give the scene a more ‘spooky’ feel, set the render settings.

In Unity, navigate to Edit > Render Settings

Enable (tick) the box that says Fog.

Click the Fog Colour box, set the ambient light to 29 on each of the RGB sliders. You can see the change in the scene, pick a colour that is dark but not pitch-black.

Click the Ambient Light Colour box, set the ambient light to 51 on each of the RGB sliders. You can see the change in the scene. Again, pick a colour that is dark but not pitch-black.

For a skybox I used the Moonshine skybox from the Standard Assets. (Assets > Import Package > Skyboxes). Drop Moonshine Skybox into Skybox Material (while in the Render Settings).

Now for the flashlight. Create a SpotLight, make it a child of the camera (so wherever the camera looks, the spotlight points). Set its Transform to X = 0; Y = 0.467; Z = 0; leave Rotations at 0, Scale at 1.

My settings for the spotlight are :

Range = 25; Spot Angle = 71.5870; Color I made very slightly yellow; Intensity = 1.85;

Now when you press play, you should be walking around your dark scene with a torchlight effect in front of where you look.

Advancing : I helped someone with a flickering flashlight, and have adapted that script to have the following behaviour. 1- light works for 1-2 minutes. 2- Light starts to flicker. 3- press F to reset light (light flashes twice as if being tapped/shaken) then light works again for another 1-2 minutes. I think it works well to add suspense (the flashlight suddenly flickers, and you have to reset it) . The link is : I want to turn my flashlight on and off, while still maintaining the flicker effects. - Questions & Answers - Unity Discussions

3- How to Pick Up Papers

This one gets asked alot, and the usual response is a trigger-collider setup. For this tutorial, I am going to use a raycast method.

First create some papers. This part is easy =] Create a cube, scale it to X = 0.6; Y = 0.9; Z = 0.01;

Name it Paper. Now Duplicate it 7 times, so you have 8 Paper cubes total.

There are some images that can be found on page 5 of this thread : http://forum.unity3d.com/threads/134862-Slender-Man-Design-Outline

Create a material for each Paper, then apply them to the cubes. You can place these where you want around the scene, just make sure they are set at a realistic height, and preferably so they can only seen from one side (nailed to a thick tree, on the side of a shed).

Now to make it so these papers can be collected.

Create a new script, call it CollectPapers. Attach it to the Player. Here is the code :

 function Start()
 {
      Go TO THE FORUM PAGE !
 }

NOTE : in the Start function, there is the line Screen.lockCursor = true; this is to hide the cursor and lock it to the center of the screen. This can have some silly effects when you run in the editor and then click the mouse, but in a build you notice it works as expected. (this script is adapted from my answer here : http://answers.unity3d.com/questions/239927/Collecting-Papers-and-Keeping-Track-of-how-many-collected--need-help.html)

So, when the left mouse button is released, a ray is cast for a certain distance. If the player is close enough to something named Paper, and the ray hits Paper, then the count is increased and the Paper is destroyed.

At this stage you should be walking around your ‘spooky’ scene, collecting papers with the amount collected displayed at the top.

Advancing : I found this link for when the paper is found, first displaying the paper full-screen, then destroying the paper. I think that effect would be cool but havn’t looked into it yet. The link is : Trying to pick up and see paper - pop up GUI window to examine objects when clicked - Questions & Answers - Unity Discussions

4- How to Have an Enemy Follow the Player at a Distance

If you were observant, you would have noticed a model where you got the images for the papers! You can use this, but as the ‘man’ always looks at the player, a 2D image can be used. Search for an image you want to use (), then make a material for that image. (Slenderman In Nba - Topic - d2jsp, http://www.zerochan.net/1271218, etc)

Create a Cube, name it Enemy, scale it to X = 1; Y = 2; Z = 0.1;

Remove or replace the Box Collider with a Capsule Collider ( Component > Physics > Capsule Collider ). My settings for the Capsule Collider are Center = 0 for XYZ, Radius = 0.5, Height = 1, Direction = Y-Axis.

Now also attach a Rigidbody Component ( Component > Physics > Rigidbody ). My settings for the Rigidbody are Mass = 1; Use Gravity = true.

Now for the script, create and call it EnemyScript. I have seen many answers use the Render.isVisible method. For this I am using a Dot.Product method. First there is a check if in a Dot.Product greater than 0.8, then check if within the maximum viewable distance, then check if there is a direct line-of-sight to the player (i.e. not occluded/behind a tree or building). Here is the code :

 function Start()
 {
      Go TO THE FORUM PAGE !
 }

5- Play and Test your Game =]

If all has gone well, you now have your very own Slender game !

This is just the start, try adding many more things :

Add Sounds !! Batteries to pick up for the Flashlight when it runs out of charge. Full screen display of the page when collected. A Game Over screen and a way to restart the game.

Hope you have found this useful and helpful =]

here’s my script for making him follow:

var target : Transform; //the enemy's target
var moveSpeed = 3; //move speed
var stopSpeed = 0;
var rotationSpeed = 3; //speed of turning

var myTransform : Transform; //current transform data of this enemy

function Awake()
{
    myTransform = transform; //cache transform data for easy access/preformance
}

function Start()
{
     target = GameObject.FindWithTag("Player").transform; //target the player

}

function Update () {

    var Speed = moveSpeed;
    
    if (renderer.isVisible)
    {
    myTransform.position += myTransform.forward * stopSpeed * Time.deltaTime;
    }
    
    if(!renderer.isVisible)
    {
    myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
    }
    //rotate to look at the player
    myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
    Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);



}

just attach this to slender man and he will follow, hope this helps. :smiley:

//target to follow
var target : Transform;

//Checks his position, used to follow the target
var pos : Transform;

//Ray variables (Length… etc.)
var rayLength : float = 3;

//Movement, speed etc.
var speed : float = 2;

//You can move if he is not being looked at
var move : boolean = false;

//I had problems with my model sinking into the floor, adjust this variable if you need it, or remove it
function FixedUpdate()
{
transform.position.y = 2;
}

function Update()
{
//Setting up Raycast variables for simple object avoidance
var fwd = transform.TransformDirection (Vector3.forward);
var hit : RaycastHit;

    //If you are looking at the object...
    if (renderer.isVisible)
    {
    move = false;
    }
   
    //If you are NOT looking at the object...
    if(!renderer.isVisible)
    {
    move = true;
    }

    //If you are not looking at the object...
    if(move)
    {
    //Make him look at the target
    transform.LookAt(target);
    //Always follow the target
    pos.position += pos.forward * speed * Time.deltaTime;
    }
   
    //If he is 3 units away from something, move right (Works if you are not looking at the object)
    if (Physics.Raycast (transform.position, fwd, rayLength) && move)
    {
    Debug.Log("Something ahead, moving");
    transform.Translate(Vector3.right * 3 * Time.deltaTime);
    }

}

Idk if that’s what you’re looking for?

#pragma strict

// | Credit to Alucard Jay

@script RequireComponent( Rigidbody )

private var myTransform : Transform;
private var myRigidbody : Rigidbody;
private var desiredVelocity : Vector3;

var isGrounded : boolean = false;

var target : Transform;

var moveSpeed : float = 6.0;
var turnSpeed : float = 2.0;

var hitNormal : float = 20.0;

var shoulderMultiplier : float = 0.5;

var rayDistance : float = 5.0;

enum NPC
{
	Idle,
	FreeRoam,
	Chasing,
	RunningAway
}

var myState : NPC;

var minimumRange : float = 4.0;
var maximumRange : float = 45.0;

private var minimumRangeSqr : float;
private var maximumRangeSqr : float;

var terrainMaximumHeight : float = 5000.0;

var isNpcChasing : boolean = true;

var freeRoamTimer : float = 0.0;
var freeRoamTimerMax : float = 5.0;
var freeRoamTimerMaxRange : float = 1.5;
var freeRoamTimerMaxAdjusted : float = 5.0;

var calcDir : Vector3;

var isSlender  : boolean = true;

function Start()
{

	myTransform = transform;
	myRigidbody = rigidbody;
	
	minimumRangeSqr = minimumRange * minimumRange;
	maximumRangeSqr = maximumRange * maximumRange;
	
	rigidbody.freezeRotation = true;
	
	//calcDir = Random.onUnitSphere;
	//calcDir.y = myTransform.position.y;
	
	var freeRoamTimer : float = 1000;
	
	if ( isSlender )
	{
		InvokeRepeating( "TeleportEnemy", 60.0, 20.0 );
	}
	
}

function TeleportEnemy()
{
	CheckIfVisible();
	
	if ( !isVisible )
	{
		var  sqrDist : float = ( target.position - myTransform.position ).sqrMagnitude;
		
		if ( sqrDist > maximumRangeSqr + 25.0 )
		{
			
			var teleportDistance : float = maximumRange + 5.0;
			
			var rndDir : int = Random.Range( 0, 2 );
			
			if ( rndDir == 0 )
			{
				rndDir = -1;
			}
			
			//var terrainPosCheck : Vector3 = target.position + ( myTransform.right * teleportDistance ); 
			var terrainPosCheck : Vector3 = target.position + ( rndDir * target.right * teleportDistance ); 
			
			terrainPosCheck.y = terrainMaximumHeight;
			
			var hit : RaycastHit;
			
			if ( Physics.Raycast( terrainPosCheck, -Vector3.up, hit, Mathf.Infinity ) )
			{
				if ( hit.collider.gameObject.tag == "Ground" || hit.collider.gameObject.name == "Terrain" )
				{
					myTransform.position = hit.point + new Vector3( 0, 0.25, 0 );
				}
			}
		}
	}
}

var isVisible : boolean = false;

var offScreenDot : float = 0.8;

function Slender()
{
	CheckIfVisible();
	
	var  sqrDist : float = ( target.position - myTransform.position ).sqrMagnitude;
	
	if ( isVisible )
	{
		// Check the range
		if ( sqrDist > maximumRangeSqr )
		{
			myState = NPC.Chasing;
		}
		else
		{
		
			var hit : RaycastHit;
		
			if ( Physics.Linecast( myTransform.position, target.position, hit ) )
			{
				
				//Debug.Log( hit.collider.gameObject.name );
				
				Debug.DrawLine( myTransform.position, target.position, Color.blue );
			
				if ( hit.collider.gameObject.name == target.name )
				{
					myState = NPC.Idle;
		    
					//decrease health here		
				}
				else
				{
					myState = NPC.Chasing;
				}
			}
		}
		
	}
	else // is NOT visible
	{
		 if ( sqrDist > minimumRangeSqr )
		 {
		 	myState = NPC.Chasing;
		 }
		 else
		 {
		 	myState = NPC.Idle;
		 }
	}	
	
}

function CheckIfVisible()
{
	var fwd : Vector3 = target.forward;
	var other : Vector3 = ( myTransform.position - target.position ).normalized;
	//var other : Vector3 = ( target.position - myTransform.position ).normalized;
	
	var dotProduct : float = Vector3.Dot( fwd, other );
	
	if ( dotProduct > offScreenDot )
	{
		isVisible = true;
	}
	else
	{
		isVisible = false;
	}
	
}

function MakeSomeDecisions()
{
	var  sqrDist : float = ( target.position - myTransform.position ).sqrMagnitude;
	
	//STATE IF STATMENTS
	if ( sqrDist > maximumRangeSqr )
	{
		if ( isNpcChasing )
		{
			myState = NPC.Chasing;
		}
		else
		{
			myState = NPC.FreeRoam;
		}
	}
	else if ( sqrDist < minimumRangeSqr )
	{
		if ( isNpcChasing )
		{
			myState = NPC.Idle;
		}
		else
		{
			myState = NPC.RunningAway;
		}
	}
	else
	{
		if ( isNpcChasing )
		{
			myState = NPC.Chasing;
		}
		else
		{
			myState = NPC.RunningAway;
		}
	}
}

function Update()
{
	if ( isSlender )
	{
		Slender();
	}
	else
	{
		MakeSomeDecisions();
	}
	
	switch( myState )
	{
		case NPC.Idle :
			myTransform.LookAt( target );
			desiredVelocity = new Vector3( 0, myRigidbody.velocity.y, 0 );
		break;
		
	    case NPC.FreeRoam :
	    	freeRoamTimer += Time.deltaTime;
	    	
	    	if ( freeRoamTimer > freeRoamTimerMaxAdjusted )
	    	{
	    		freeRoamTimer = 0.0;
	    		freeRoamTimerMaxAdjusted = freeRoamTimerMax + Random.Range( -freeRoamTimerMaxRange, freeRoamTimerMaxRange );
	    		
	    		calcDir = Random.onUnitSphere;
	    		calcDir.y = 0.0; //myTransform.position.forward.y;
	    	}
	    	
	    	Moving( calcDir );
	    	
			//desiredVelocity = new Vector3( 0, myRigidbody.velocity.y, 0 );
		break;
		
		case NPC.Chasing :
			Moving( (target.position - myTransform.position).normalized );
		break;
		
		case NPC.RunningAway :
			Moving( (myTransform.position - target.position).normalized );
		break;
	}


	//Moving();
}

function Moving( lookDirection : Vector3)
{
	//rotation 
	//var lookDirection : Vector3 = (target.position - myTransform.position).normalized;
	
	var hit : RaycastHit;
	
	
	
	var leftRayPos : Vector3 = myTransform.position - ( myTransform.right * shoulderMultiplier );
	var rightRayPos : Vector3 = myTransform.position + (myTransform.right * shoulderMultiplier );
	
	if ( Physics.Raycast( leftRayPos, myTransform.forward,  hit, rayDistance )  )
	{
		if ( hit.collider.gameObject.tag != "Ground" )
		{
			Debug.DrawLine( leftRayPos, hit.point, Color.red );
		
			lookDirection += hit.normal * hitNormal;
		}
	}
	else if ( Physics.Raycast( rightRayPos, myTransform.forward,  hit, rayDistance )  )
	{
		if ( hit.collider.gameObject.tag != "Ground" )
		{
			Debug.DrawLine( rightRayPos, hit.point, Color.red );
		
			lookDirection += hit.normal * hitNormal;
		}
	}
	else
	{
		Debug.DrawRay( leftRayPos, myTransform.forward * rayDistance, Color.green );
		Debug.DrawRay( rightRayPos, myTransform.forward * rayDistance, Color.green );
	}
	
	var lookRot : Quaternion = Quaternion.LookRotation ( lookDirection );
	
	myTransform.rotation = Quaternion.Slerp( myTransform.rotation, lookRot, turnSpeed * Time.deltaTime );
	
	//movement
	//myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
	desiredVelocity = myTransform.forward * moveSpeed;
	desiredVelocity.y = myRigidbody.velocity.y;
}

function FixedUpdate()
{
	if ( isGrounded )
	{
		myRigidbody.velocity = desiredVelocity;
	}
}

function OnCollisionEnter ( collision : Collision )
{
	if ( collision.collider.gameObject.tag == "Ground" || collision.collider.gameObject.name == "Terrain" )
	{
		isGrounded = true;
	}
}

function OnCollisionStay ( collision : Collision )
{
	if ( collision.collider.gameObject.tag == "Ground" || collision.collider.gameObject.name == "Terrain")
	{
		isGrounded = true;
	}
}

function OnCollisionExit ( collision : Collision ) 
{
	if ( collision.collider.gameObject.tag == "Ground" || collision.collider.gameObject.name == "Terrain")
	{
		isGrounded = false;
	}
}

Add a capsule collider to your camera about the same size as your first person controller. Then drag the camera to the “Target” variable. Set the rest of the values to your liking. Terrain maximum height is the max height your terrain reaches so set that too.

I cant pick up the papers. What is wrong? i made all from your tutorial

so use this c# code

using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {
		public float deathDistance = 0.5f;
		public float distanceAway;
		public Transform thisObject;
		public Transform target;
		private NavMeshAgent navComponent;
		
		void Start() 
		{
			target = GameObject.FindGameObjectWithTag("Player").transform;
			navComponent = this.gameObject.GetComponent<NavMeshAgent>();
		}
		
		void Update() 
	{
			
			float dist = Vector3.Distance(target.position, transform.position);
			
			if(target)
			{
				navComponent.SetDestination(target.position);
			}

			else
			{
				if(target = null)
				{
					target = this.gameObject.GetComponent<Transform>();
				}
				else
				{
					target = GameObject.FindGameObjectWithTag("Player").transform;
				}
			}
			if (dist <= deathDistance)
			{
				//KILL PLAYER
			}
		}
	}

then use this javascript code

#pragma strict

function Start () {

}

function OnTriggerEnter() {
    Application.LoadLevel("YOUR DEATH SCENE");
}