[I have moved this here from the Support forum]
Hi,
I’m trying to modify the standard asset First Person Controller so that navigation and camera movement work a bit differently (for example, turning instead of strafing). Here’s what I’m aiming for:
- W and S keys (and up and down arrows) move the player forward and back
- A and D keys (and left and right arrows) turn the player to the left and right (pivoting around the Y axis)
- the mouse does not affect the camera or the position of the player unless the right mouse button is down
- with the right mouse button down, the camera can look up and down, and the player can turn to the left and right.
I have searched this forum and found some code that I’ve been able to use to achieve most of what I need it to do. I have taken the following script (written by Paintbrush and posted HERE), [edit: pared it down extensively to removed functions I did not need], and attached it to the First Person Controller in place of the standard assets FPSwalker script:
[edit: the following code block contains the script that does not work right. See the later post for a script that does work.]
private var gravity:float = 20.0;
private var walkSpeed:float = 5.0;
private var rotateSpeed:float = 100.0;
private var grounded:boolean = false;
private var moveDirection:Vector3 = Vector3.zero;
function Update ()
{
// Allow movement while grounded
if(grounded)
{
moveDirection = new Vector3((Input.GetMouseButton(1) ? Input.GetAxis("Horizontal") : 0),0,Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection) * walkSpeed;
transform.Rotate(0,Input.GetAxis("Horizontal") * rotateSpeed * Time.deltaTime, 0);
}
//Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
//Move controller
var controller:CharacterController = GetComponent(CharacterController);
var flags = controller.Move(moveDirection * Time.deltaTime);
grounded = (flags CollisionFlags.Below) != 0;
}
@script RequireComponent(CharacterController)
For the mouselook script, I have just added “if(Input.GetMouseButton(1))” to the script that comes with the FPS standard asset, to produce this:
using UnityEngine;
using System.Collections;
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour {
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationX = 0F;
float rotationY = 0F;
Quaternion originalRotation;
void Update ()
{
if (Input.GetMouseButton(1))
{
if (axes == RotationAxes.MouseXAndY)
{
// Read the mouse input axis
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationX = ClampAngle (rotationX, minimumX, maximumX);
rotationY = ClampAngle (rotationY, minimumY, maximumY);
Quaternion xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
else if (axes == RotationAxes.MouseX)
{
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationX = ClampAngle (rotationX, minimumX, maximumX);
Quaternion xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
transform.localRotation = originalRotation * xQuaternion;
}
else
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = ClampAngle (rotationY, minimumY, maximumY);
Quaternion yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
transform.localRotation = originalRotation * yQuaternion;
}
}
}
void Start ()
{
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
originalRotation = transform.localRotation;
}
public static float ClampAngle (float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp (angle, min, max);
}
}
This combination works pretty well. You can try it out here:
http://www.medievalist.net/unityworlds/gsugallery.htm
However, there are some problems.
If I use the mouse (right button) to look around, and then hit the W key to move forward, I go in the direction I’m looking, which is good. However, if I use the arrow keys to turn from side to side, and then hit the right mouse button to look around, the view instantly reverts to the direction the player was facing before I used the left/right arrows. [edit: removed references to problems that have been solved]
I’m afraid I can’t figure out what’s going wrong here. If you can, please let me know.
Thanks.
Edit:
I’ve solved a number of the issues reported in my original post (and edited them out), but the main one persists: if I turn to the left or right using A or D, or the arrow keys, and then click the right mouse button, the camera viewpoint jumps back to the position it was in before I used the left/right keys. Obviously my script is missing something. If you can tell me what it is I’d be grateful. Or perhaps there is a code snippet somewhere that would work better than this one. If you can point me to such a thing, I’d appreciate it.
Thanks.