Teleporting script

I need help to make a Nightcrawler style teleporting script, but here’s the thing i’m still kinda new to scripting. The script I have now is only one way, one spot. So what I am looking for in the script is to be able to teleport anyware in the 3D enviroment. Also teleport behind enemies, and across gaps in each level.
this is the script I have:

var teleportTo : Transform;
function Update()
{
if(Input.GetButtonDown(“Fire2”))
{
transform.position = teleportTo.position;
}
}

Hi, looks like the code above is correct, you only need to modify the teleportTo var to where you want to transport to, that var will be the trigger for teleport…

how would I modify the teleport var, because I have no idea on what I am doing. I don’t want to put on any one object. Someone was trying to tell use raycasting, and I have no idea on how to do that either. And as for the script above, I got off the internet. so any help would be cool.

Sounds quite complicated. If you want to teleport around a predefined list of areas, in a linear series (Point A to B, then B to C, etc), you can continuously edit the next location variable you want to travel, like an ontriggerenter/exit/stay function, or a check that you had just used the variable to get there and use the next variable.

Another way would, I assume, would be an array of different locations and to check which location is the closest and then spawn to the nearest one.

If you want to be able to teleport anywhere, I’d make either a pre-defined amount of how far forward (or whatever direction) you’d teleport to. If you only want teleport to be in some instances like behind an enemy, then do a check either by raycast or ontriggerenter with a sphere trigger on the enemy, when either X distance from the enemy or in the sphere trigger, then allow teleportation and teleport to the closest enemy in sight’s behind axis (or an invisible cube/gameobject parented to the enemy you can teleport to).

I’m not going to write for you all of these examples, you have to provide a little more detail as to how extensive this system will be. Also, read up on this.

Okay I may have a better idea on how I want to have done. If you have ever played LOK Blood Omen 2. How Kain gets ready to do his long distance jump. From that i’m guessing the script there is instanciate a distance before jumping, and that works in any direction. But I want to do this kinda thing for teleporting. If you don’t know what Bood Omen 2 is Here is the link:

Now I’m confused.

Do you have a direct shareable link at the exact moment this “leap” happens?

From what I see so far, the character is only jumping, not teleporting?

you need to make everything on a key press. let’s say when you press “Fire2”, you make the Time.scale = 0.1f; (very slow motion, since you are in the teleporting mode) and then you move around on the ground a Texture (just like in Blood Omen 2 ) where a Raycast from the camera through your screen mouse coordinates hits the ground collider, you use a SpheerCast or something similar to see if you char will fit there, if it does, on mouse release, you start the teleporting, if not, choose another place till it fits, or if mouse was released, and no such place was found, do not teleport.

You’re going to have to be able to do some fairly complex programming to pull this off effectively. You may want to run through a few tutorials.

Based on this logic, you could also do this without raycasting I believe.

If you parent a cube in front of the player, hacked up a camera collider script onto it (so that if it hits a wall, to still allow the character to walk towards the wall as to not be restricted by the cube).

Then, you just keep teleporting to the location of the cube infront of you, always the same distance unless the cube has hit a collider (and you could make it ignore enemies, only hitting walls), then you teleport the remaining max distance between you and the wall, once the cube is no longer hitting the wall, to go back to the max distance.

I’ve hacked up camera scripts several times for different things =)

You’ll have show me what you’re talking about, is that camera script in the 3Dplatformer tutorial. Now I have a crude way I have made, but it is kinda cheap. And want to make look, and work better than what I previously have.

Here is the link to my video and channel: http://www.youtube.com/user/2112inuyasha?feature=mhee

You,ll have to show me what you’re talking about.

var targetPO : Transform; //Target Player or object
var self : Transform; //Target Self
var speed = 5.0; //Variable for speed
var maxDistance = 4.3; //Maximum distance from object/player

private var rotationAngle : float = 0.0;
private var cameraY : float = 2.0;

function FixedUpdate () {
p = self.transform.position; //These
self.transform.position = new Vector3(p.x, 4.0, p.z); //Two lines stop movement in Y axis any further than specified

var targetCameraPosition : Vector3 = -(targetPO.position - self.position).normalized * maxDistance * cameraY;
var rotationQuaternion1 : Quaternion = Quaternion.AngleAxis(rotationAngle, Vector3.up);
targetCameraPosition = rotationQuaternion1 * targetCameraPosition;
targetCameraPosition += targetPO.position;
targetCameraPosition = Vector3.Slerp(transform.position,  targetCameraPosition, speed * Time.deltaTime);
transform.LookAt(targetPO.position);
transform.position = targetCameraPosition;	
}

Don’t think it does height calculations hence I had the vector3 fixed height added, if it does do height then I’ve clearly forgotten it does as I haven’t been using it for jumping characters lately. Give it a go. It’s a compilation of a few scripts I found around on wiki answers I think.

Height calculations shouldn’t matter for objects that aren’t cameras, as they should be made a fixed height and parented to the player anyway.

If this script is attached to a collider infront of the player, parented, and the object hits a wall the object shouldn’t go through the wall and will just remain at a set distance that is left to teleport to between the player and the object. After it’s no longer hitting the wall it should re-align with the 4.3 max distance that’s already set for you from my stuff.

The video you provided however shows a pre-defined list of locations to teleport between, and you can have the (X) sign object in the video go straight to a new location rather than moving towards that location, so the player doesn’t have to wait.

Since I am here, and answered another guys question with what would be considered to be a working prototype of a camera and character controller… And I am bored… and its Friday afternoon and I am just waiting to get off of work… I set out to look at this problem.

I took the script I posted here:
http://forum.unity3d.com/threads/107277-Auto-rotating-camera

And set out to add a “teleporting” section to it. I first said, “Well, how do I want to implement this… Press t and you teleport?” Not really. I approached it as the WoW gamer in me looked at it… Click a number, click a spot, teleport to that spot. But there are some catches. I have to stop my character in order to teleport, maybe do show something where I want to teleport to. Then, how do I handle the animation going from point A to point B?

So the “I want a teleporting script” becomes a whole complicated mess of how you want to accomplish it.

Well… I wouldn’t be posting if I didnt solve it all. I used some states to tell me where I was going to teleport to and the state of the selection. Perhaps later I would implement this into a spell casting and action bar setup, but meh, not right now.

OK, here is the script from the other post. I added some lines. (in red) and changed some things around to make it a little less bulky.

using UnityEngine;
using System.Collections;

public class WowCharacter : MonoBehaviour {
	bool isPlayer = true;
	
	private float speed = 5.0f;
	private float jumpSpeed = 8.0f;
	private float gravity = 20.0f;
	private Vector3 moveDirection = Vector3.zero;
	
	Vector3 headPoint = new Vector3(0,1,0);
	private float yMinLimit = -60.0f;
	private float yMaxLimit = 60.0f;
	private float minDistance = 0.0f;
	private float maxDistance = 20.0f;
	
	float xSpeed = 5.0f;
	float ySpeed = 2.4f;
	float zoomSpeed = 10.0f;
	
	private float distance;
	private float currentDistance;
	private float mouseX = 0f;
	private float mouseY = 0f;
	
	[COLOR="red"]private bool teleportSelecting = false;
	private bool teleporting = false;
	private Vector3 teleportFrom = Vector3.zero;
	private Vector3 teleportTo = Vector3.zero;
	private float maxTeleportDistance = 40.0f;
	private Transform teleportingBox;[/COLOR]
	
	// Use this for initialization
	void Start () {
		Transform cam = Camera.main.transform;
		Vector3 angles = cam.eulerAngles;
	    mouseX = angles.y;
	    mouseY = angles.x;
		distance = (maxDistance - minDistance) / 2 + minDistance;
		currentDistance = distance;
		
		CharacterController controller = gameObject.GetComponent<CharacterController>();
		if(controller == null){
			controller = gameObject.AddComponent<CharacterController>();
		}
	}
	// Update is called once per frame
	void Update (){
		CharacterController controller = GetComponent<CharacterController>();
		[COLOR="red"]float dot = 0.0f;
		
		// catch if we want to teleport
		if(Input.GetKeyDown(KeyCode.Alpha1)  !teleporting){
			teleportSelecting = !teleportSelecting;
		}
		
		// if we are selecting wait for a mouse button down
		if(teleportSelecting){
			if(teleportingBox == null){
				teleportingBox = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
				DestroyImmediate(teleportingBox.collider);
			}
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			RaycastHit hit;
			bool hasHit = GetHitOther(ray, Mathf.Infinity, out hit);
			teleportingBox.position = Vector3.up * 50000.0f;
			if(hasHit){
				dot = Vector3.Dot(hit.normal, Vector3.up);
				Color color = Color.white;
				if(hit.distance > maxTeleportDistance || dot < 0.6f) color = Color.red;
				teleportingBox.position = hit.point;
				teleportingBox.renderer.material.color = color;
			}
			if(Input.GetMouseButtonDown(0)){
				teleportSelecting = false;
				if(hasHit){
					transform.LookAt(hit.point);
					SetUpright();
					if(hit.distance < maxTeleportDistance  dot > 0.6f){
						teleportTo = hit.point;
						ray = new Ray(transform.position, -Vector3.up);
						if(GetHitOther(ray, Mathf.Infinity, out hit)){
							teleportTo += Vector3.up * hit.distance;
							//teleportFrom = transform.position;
							//teleporting=true;
							transform.position = teleportTo; // flat teleport
						}
					}
				}
			}
		}
		
		if(teleporting){
			controller.enabled = false;
			Vector3 directionNormal = (teleportTo - teleportFrom).normalized;
			transform.position = transform.position + directionNormal * speed * 8.0f * Time.deltaTime;
			if(transform.InverseTransformPoint(teleportTo).z < 0){
				transform.position = teleportTo;
				teleporting=false;
				controller.enabled = true;
			} else
				return; // prevent any other movement while teleporting
		}
		
		if(!teleportSelecting  teleportingBox)
			Destroy(teleportingBox.gameObject);[/COLOR]
		
		
		if (controller.isGrounded) {
			moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
			moveDirection = transform.TransformDirection(moveDirection);
			moveDirection *= speed;
			if(Input.GetKey(KeyCode.LeftShift)) moveDirection *= 2.0f;
			if (Input.GetButton("Jump"))
				moveDirection.y = jumpSpeed;
			[COLOR="red"]if(moveDirection.magnitude > 0.0f) teleportSelecting = false;[/COLOR]
		}
		moveDirection.y -= gravity * Time.deltaTime;
		controller.Move(moveDirection * Time.deltaTime);
	}
	
	void LateUpdate () {
		if(isPlayer){
			Transform cam = Camera.main.transform;
			Quaternion rotation;
			
			//do scroll wheel
			distance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 100 * zoomSpeed;
			distance = Mathf.Clamp(distance,minDistance,maxDistance);
			currentDistance = Mathf.Lerp(currentDistance, distance, 2.0f * Time.deltaTime);
	
			//do MouseInput if either mouse button is down
			if(Input.GetMouseButton(0) || Input.GetMouseButton(1)){
				mouseX += Input.GetAxis("Mouse X") * xSpeed;
		        mouseY -= Input.GetAxis("Mouse Y") * ySpeed;
			
				mouseY = ClampAngle(mouseY, yMinLimit, yMaxLimit);
				
				if(Input.GetMouseButton(1)){
					rotation = Quaternion.Euler(0,mouseX,0);
					transform.rotation = rotation;
				}
			}
			
			//set the rotation and position of the camera at the person's head
			rotation = Quaternion.Euler(mouseY, mouseX, 0);
			cam.rotation = rotation;
			cam.position = transform.position + headPoint;
			
			// distance testing for zoom
			RaycastHit hit;
			if(GetHitOther(new Ray(cam.position, -cam.forward), currentDistance + 1.0f, out hit))
				currentDistance = hit.distance - 1.0f;
			if(currentDistance < 0.0f) currentDistance = 0.0f;
			
			//alpha coloring if too close
			//problems with zdepth testing... will have to work on it.
			//float a = Mathf.Clamp01((currentDistance - 0.5f) / 1.5f);
			//Renderer[] rends = gameObject.GetComponentsInChildren<Renderer>();
			//for(i = 0; i<rends.Length; i++){
			//	Color c = rends[i].material.color;
			//	c.a = a;
			//	rends[i].material.color = c;
			//}
			
			// move the camera into place according to the current distance
			cam.Translate(-Vector3.forward * currentDistance);
		}
	}
	
	static float ClampAngle (float angle, float min, float max) {
		if (angle < -360)
			angle += 360;
		if (angle > 360)
			angle -= 360;
		return Mathf.Clamp(angle, min, max);
	}
	
	bool GetHitOther(Ray ray, float dist, out RaycastHit hit){
		RaycastHit[] hits = Physics.RaycastAll(ray, dist + 1.0f);
		for(int i = 0; i < hits.Length; i++){
			//we could test the root's tag against a controller tag, and not stop
			//at any collider that is not the current one as well.
			if(hits[i].transform.root != transform){
				hit = hits[i];
				return true;
			}
		}
		hit = new RaycastHit();
		return false;
	}
	
	void SetUpright(){
		Vector3 euler = transform.localEulerAngles;
		euler.x = 0;
		euler.z = 0;
		transform.localEulerAngles = euler;
	}
}

This whole script is meant to be put on a capsule collider. It makes it into a character controller.

Hah… a rewrite of the update to change the teleport into a “Heroic Leap”

	// Update is called once per frame
	void Update (){
		CharacterController controller = GetComponent<CharacterController>();
		float dot = 0.0f;
		Vector3 direction;
		
		// catch if we want to teleport
		if(Input.GetKeyDown(KeyCode.Alpha1)  !teleporting){
			teleportSelecting = !teleportSelecting;
		}
		
		// if we are selecting wait for a mouse button down
		if(teleportSelecting){
			if(teleportingBox == null){
				teleportingBox = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
				DestroyImmediate(teleportingBox.collider);
			}
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			RaycastHit hit;
			bool hasHit = GetHitOther(ray, Mathf.Infinity, out hit);
			teleportingBox.position = Vector3.up * 50000.0f;
			if(hasHit){
				dot = Vector3.Dot(hit.normal, Vector3.up);
				Color color = Color.white;
				if(hit.distance > maxTeleportDistance || dot < 0.6f) color = Color.red;
				teleportingBox.position = hit.point;
				teleportingBox.renderer.material.color = color;
			}
			if(Input.GetMouseButtonDown(0)){
				teleportSelecting = false;
				if(hasHit){
					transform.LookAt(hit.point);
					SetUpright();
					if(hit.distance < maxTeleportDistance  dot > 0.6f){
						teleportTo = hit.point + Vector3.up;
						teleportTo = GetSpaceForTeleport(hit.point);
						teleportFrom = transform.position;
						teleporting=true;
						direction = teleportTo - teleportFrom;
						currentTeleportDistance = direction.magnitude;
						//transform.position = teleportTo; // flat teleport
					}
				}
			}
		}
		
		if(teleporting){
			controller.enabled = false;
			direction = teleportTo - teleportFrom;
			float totalTeleportDistance = direction.magnitude;
			currentTeleportDistance -= speed * 8.0f * Time.deltaTime;
			if(currentTeleportDistance < 0) currentTeleportDistance = 0;
			float amount = currentTeleportDistance / totalTeleportDistance;
			float y = Mathf.Sin(amount * 180 * Mathf.Deg2Rad) * totalTeleportDistance / 3;
			Vector3 directionNormal = direction.normalized;
			transform.position = Vector3.Lerp(teleportTo, teleportFrom, amount) + Vector3.up * y;
			if(currentTeleportDistance == 0){
				transform.position = teleportTo;
				teleporting=false;
				controller.enabled = true;
			} else
				return; // prevent any other movement while teleporting
		}
		
		if(!teleportSelecting  teleportingBox)
			Destroy(teleportingBox.gameObject);
		
		
		if (controller.isGrounded) {
			moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
			moveDirection = transform.TransformDirection(moveDirection);
			moveDirection *= speed;
			if(Input.GetKey(KeyCode.LeftShift)) moveDirection *= 2.0f;
			if (Input.GetButton("Jump"))
				moveDirection.y = jumpSpeed;
			//if(moveDirection.magnitude > 0.0f) teleportSelecting = false;
		}
		moveDirection.y -= gravity * Time.deltaTime;
		controller.Move(moveDirection * Time.deltaTime);
	}

i’m confused on how it is suppose to work, I guess i’m use to looking at java script. Saying that is because I know how to modify java, not write from scratch. So can that be written in java.

All scripting is reasonable the same… The difference between JS and C# is that you HAVE to name teh script what the class name is.

So that script HAS to be named “WowCharacter.cs”

Once htat is done, just attach it to an object like a javascript and it works reasonable the same. Look at the other thread and read the comments there as well. :wink:

So am I able to just delete everything but the teleporting part of the script and it still work. What I mean is, I already have a script that moves my character around.It is also all jittery in it’s current state. I also want to add partical Fx to the teleport script, so it looks more like Nightcrawler when my character ports.

The actual section about teleporting deals specifically with selecting a locaation. It does not need to be in the same script as the movement. you can easily find a point using a raycast, then put your character there by transforming it’s point. You can even use the normal from the hit to re-orientate your player to appear that he is on a wall. I do not know exactly how you would handle y rotation at extreme rotation change, but I am sure you can manage it.

The second script look so much like WoW’s warrior Heroic Leap it isnt funny… I made a demo scene and tinkered with it.

Totally fav’d, you’re awesome BigMisterB =)

How do I add partical FX to the script to make it look more like Nightcrawler when the character ports. And thanks for the main script that was having trouble with.