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.