- Home /
Scripting Issue With Top Down Mouse Movement
I have written a Script that will set the camera to a top down style view and have the character face the current mouse location and then move around with the WASD keys. When the camera gets rotated, the character will "loose track" of the mouse location and no longer faces it. If anyone knows why it's doing this and a solution I would really appreciate it.
Camera
/*
© copyright 2013 Emerald Ink, All Rights Reserved
*/
#pragma strict
// The Camera this script should affect
var cameraTransform : Transform;
// The distance in the x-z plane to the target
var distance = 4.0;
// The height we want the camera to be above the target
var height = 4.0;
// Min and max values for the camera height
var heightMin = 0.0;
var heightMax = 8.0;
// The speed at which the camera should rotate
var rotateSpeed = 100.0;
// How much we want to smooth the camera
var heightDamping = 2.0;
var sideDamping = 2.0;
// The target we are following
private var target : Transform;
private var x = 0.0;
function CameraZoom () {
// Scroll in or out using the mouse wheel
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
if (height < heightMax)
{
height++;
}
}
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
if (height > heightMin)
{
height--;
}
}
}
function CameraRotate () {
if (Input.GetButton("Fire3")){
x += Input.GetAxis("Mouse X") * rotateSpeed * 0.02;
}
}
function CameraSmooth () {
// Calculations to smooth out the camera
var wantedHeight = target.position.y + height;
var wantedSide = target.position.x + distance;
var currentHeight = cameraTransform.transform.position.y;
//var currentSide = cameraTransform.transform.position.x;
// Dampen the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
var rotation = Quaternion.Euler(0, x, 0);
var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
cameraTransform.transform.rotation = rotation;
cameraTransform.transform.position = position;
// Set the height of the camera
cameraTransform.transform.position.y = currentHeight;
// Always look at the target
cameraTransform.transform.LookAt(target);
}
function SetTarget(newTarget : Transform)
{
target = newTarget;
}
function Start () {
if(!cameraTransform && Camera.main)
cameraTransform = Camera.main.transform;
if(!cameraTransform) {
Debug.Log("Please assign a camera to the ThirdPersonCamera script.");
enabled = false;
}
target = transform;
var angles = cameraTransform.transform.eulerAngles;
x = angles.y;
}
function Update () {
CameraZoom();
CameraSmooth();
CameraRotate();
}
Character Controller / © copyright 2013 Emerald Ink, All Rights Reserved /
#pragma strict
// Can we control the character or not, during for example, a cut-scene.
var isControllable : boolean = true;
// Speed the player will move at.
var speed : float = 6.0;
// Speed the player will go upwards.
var jumpSpeed : float = 8.0;
// Speed at which the player will go downwards. Simulates gravity.
var gravity : float = 20.0;
private var inputRotation : Vector3;
private var mouseLocation : Vector3;
private var moveDirection : Vector3;
private var moveSpeed : float;
private var screenMiddle : Vector3;
function LookAtCursor () {
// The position of the middle of the screen.
screenMiddle = Vector3(Screen.width * 0.5f,0,Screen.height * 0.5f);
// Get the position of the mouse
mouseLocation = Input.mousePosition;
// Keep mouse location along the X,Z plane.
mouseLocation.z = mouseLocation.y;
mouseLocation.y = 0;
// Rotates the player to face the mouse relative to the center of the screen.
inputRotation = mouseLocation - screenMiddle;
transform.rotation = Quaternion.LookRotation(inputRotation);
}
function Movement () {
var controller : CharacterController = GetComponent(CharacterController);
// Direction of Movement relative to the player's rotation.
moveDirection = Input.GetAxis("Vertical")* transform.forward + Input.GetAxis("Horizontal") * transform.right;
// Keeps WASD movement along the X,Z plane.
moveDirection.y = 0f;
// Set the player's direction and move forward.
moveDirection *= speed;
// Move the player up while "Jump" is being held.
if (Input.GetKey(KeyCode.Space)) {
moveDirection.y = jumpSpeed;
}
// Move the player down while "Crouch" is being held.
if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)){
moveDirection.y = -jumpSpeed;
}
else {
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
}
// Move the controller
controller.Move(moveDirection * Time.deltaTime);
}
function Start () {
}
function Update () {
if (!isControllable)
{
// kill all inputs if not controllable.
Input.ResetInputAxes();
}
LookAtCursor();
Movement();
}
If you don't understand what I mean... Video
You could try solving this using a Raycast from the camera to the mouse position using:
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
Then take the position this returns, and use that for what your player/character is looking at
Thank you that seemed to do the trick. Still some issues though...
function LookAtRay () {
var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
ray.direction.y = 0;
Debug.DrawRay(ray.origin, ray.direction* 10, Color.green);
transform.rotation = Quaternion.LookRotation(ray.direction);
}
I had to set y = 0 to keep that part of the movement 2D. Still isn't moving quite right... I'll have to play around with it
Thanks for the help!
Alright I've been friggen around with this for like an hour now and still need some help.
The problem with this is the camera is set to x units behind the player. This causes a problem when the the mouse is positioned behind the player, but in front of the camera. you should be moving backwards, but continue to move forward until the mouse position is behind the invisible camera. I've tried A LOT of ways to fix this but just can't wrap my head around it.
Any solutions?
Answer by robertbu · Dec 27, 2013 at 04:35 PM
Your original solution is trying to use screen coordinates in a world coordinate situation. Your 'ray' solution is not doing a Raycast. If the camera is parallel to the ground plane, then you can do use Camera.ScreenToWorldPoint(), but I'm going to assume it is not parallel. With a camera at an angle, a good solution is to use Unity's mathematical plane class and raycast against the plane.
function LookAtCursor () {
var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var plane : Plane = new Plane(Vector3.up, transform.position);
var dist : float;
plane.Raycast(ray, dist);
transform.LookAt(ray.GetPoint(dist));
}
Excellent!
This is exactly the kind of mechanic I was looking for. Would of taken me a long time to think of doing this. Performance boost to boot. Thank you!
Your answer
Follow this Question
Related Questions
Camera rotation around player while following. 6 Answers
Camera Rotate to mouse position -2 Answers
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
rotate camera on mobile 1 Answer