Need help with third person camera script!
Hello :) I am trying to create a third person shooter and I want a camera system as seen in Metal Gear Solid 5. What I have now is the camera orbiting and following the player. I want to have it so when I hold right click, the camera zooms over the character shoulder and the camera follows the mouse.
Here is my current Camera Script (attached to the main camera)
ShooterGameScript.cs:
using UnityEngine;
using System.Collections;
// 3rd person game-like camera controller
// keeps camera behind the player and aimed at aiming point
public class ShooterGameCamera : MonoBehaviour {
public Transform player;
public Texture crosshair;
protected Transform aimTarget; // that was public and a gameobject had to be dragged on it. - ben0bi
public float smoothingTime = 10.0f; // it should follow it faster by jumping (y-axis) (previous: 0.1 or so) ben0bi
public Vector3 pivotOffset = new Vector3(0.2f, 0.7f, 0.0f); // offset of point from player transform (?) ben0bi
public Vector3 camOffset = new Vector3(0.0f, 0.7f, -3.4f); // offset of camera from pivotOffset (?) ben0bi
public Vector3 closeOffset = new Vector3(0.35f, 1.7f, 0.0f); // close offset of camera from pivotOffset (?) ben0bi
public float horizontalAimingSpeed = 800f;
public float verticalAimingSpeed = 800f;
public float maxVerticalAngle = 80f;
public float minVerticalAngle = -80f;
//From the other MouseLookScript
private float rotY = 0.0f; // rotation around the up/y axis
private float rotX = 0.0f; // rotation around the right/x axis
public float mouseSensitivity = 0.3f;
public float clampAngle = 80.0f;
private float angleH = 0;
private float angleV = 0;
private Transform cam;
private float maxCamDist = 1;
private LayerMask mask;
private Vector3 smoothPlayerPos;
// Use this for initialization
void Start ()
{
//3 lines from mouseLook
Vector3 rot = transform.localRotation.eulerAngles;
rotY = rot.y;
rotX = rot.x;
// [edit] no aimtarget gameobject needs to be placed anymore - ben0bi
GameObject g=new GameObject();
aimTarget=g.transform;
// Add player's own layer to mask
mask = 1 << player.gameObject.layer;
// Add Igbore Raycast layer to mask
mask |= 1 << LayerMask.NameToLayer("Ignore Raycast");
// Invert mask
mask = ~mask;
cam = transform;
smoothPlayerPos = player.position;
maxCamDist = 3;
}
// Update is called once per frame
void LateUpdate () {
if (Time.deltaTime == 0 || Time.timeScale == 0 || player == null)
return;
angleH += Mathf.Clamp(Input.GetAxis("Mouse X") /* + Input.GetAxis("Horizontal2") */ , -1, 1) * horizontalAimingSpeed * Time.deltaTime;
angleV += Mathf.Clamp(Input.GetAxis("Mouse Y") /* + Input.GetAxis("Vertical2") */ , -1, 1) * verticalAimingSpeed * Time.deltaTime;
// limit vertical angle
angleV = Mathf.Clamp(angleV, minVerticalAngle, maxVerticalAngle);
// Before changing camera, store the prev aiming distance.
// If we're aiming at nothing (the sky), we'll keep this distance.
float prevDist = (aimTarget.position - cam.position).magnitude;
// Set aim rotation
Quaternion aimRotation = Quaternion.Euler(-angleV, angleH, 0);
Quaternion camYRotation = Quaternion.Euler(0, angleH, 0);
cam.rotation = aimRotation;
// Find far and close position for the camera
smoothPlayerPos = Vector3.Lerp(smoothPlayerPos, player.position, smoothingTime * Time.deltaTime);
smoothPlayerPos.x = player.position.x;
smoothPlayerPos.z = player.position.z;
Vector3 farCamPoint = smoothPlayerPos + camYRotation * pivotOffset + aimRotation * camOffset;
Vector3 closeCamPoint = player.position + camYRotation * closeOffset;
float farDist = Vector3.Distance(farCamPoint, closeCamPoint);
// Smoothly increase maxCamDist up to the distance of farDist
maxCamDist = Mathf.Lerp(maxCamDist, farDist, 5 * Time.deltaTime);
// Make sure camera doesn't intersect geometry
// Move camera towards closeOffset if ray back towards camera position intersects something
RaycastHit hit;
Vector3 closeToFarDir = (farCamPoint - closeCamPoint) / farDist;
float padding = 0.3f;
if (Physics.Raycast(closeCamPoint, closeToFarDir, out hit, maxCamDist + padding, mask)) {
maxCamDist = hit.distance - padding;
}
cam.position = closeCamPoint + closeToFarDir * maxCamDist;
// Do a raycast from the camera to find the distance to the point we're aiming at.
float aimTargetDist;
if (Physics.Raycast(cam.position, cam.forward, out hit, 100, mask)) {
aimTargetDist = hit.distance + 0.05f;
}
else {
// If we're aiming at nothing, keep prev dist but make it at least 5.
aimTargetDist = Mathf.Max(5, prevDist);
}
// Set the aimTarget position according to the distance we found.
// Make the movement slightly smooth.
aimTarget.position = cam.position + cam.forward * aimTargetDist;
}
void Update()
{
if (Input.GetKey ("mouse 1")) {
camOffset = new Vector3 (0.0f, 0.8f, -1.7f);
float horizontalAimingSpeed = 0f;
float verticalAimingSpeed = 0f;
} else
{
camOffset = new Vector3(0.0f, 0.7f, -3.4f);
float horizontalAimingSpeed = 400f;
float verticalAimingSpeed = 400f;
}
}
// so you can change the camera from a static observer (level loading) or something else
// to your player or something else. I needed that for network init... ben0bi
public void SetTarget(Transform t)
{
player=t;
}
void OnGUI ()
{
if (Time.time != 0 && Time.timeScale != 0)
GUI.DrawTexture(new Rect(Screen.width/2-(crosshair.width*0.5f), Screen.height/2-(crosshair.height*0.5f), crosshair.width, crosshair.height), crosshair);
}
}
I've got the camera to zoom in over his shoulder when I hold right mouse button. I really have no idea on where to start on this?
Any help would be greatly appreciated!
Cheers.
Answer by Dark Noct · Feb 03, 2016 at 05:46 PM
Hi Yolojoe. What I would do is create an empty game object over the shoulder of the player as a child, and have a reference of the position to that empty object from the camera. Once I press a button, have the camera move to that position and change the view. Thus, it will create an illusion of zooming over the character's shoulder.
Thanks for the input, but I've already got the "zoo$$anonymous$$g over the shoulder" part to work :) Do you have any clue how I can aim with the mouse when I hold $$anonymous$$ouse 1? Ins$$anonymous$$d of the camera orbit? :)
Answer by scarletsnake · Mar 11, 2016 at 04:41 PM
Lock the player object's rotation to the rotation of the mouse, as you do with the camera controls. This way both the camera and the player object will turn simultaneously towards the center of the screen.
I have a similar system in my game and use this line of code;
transform.rotation = Quaternion.Euler(gameObject.transform.eulerAngles.x,Camera.main.transform.eulerAngles.y,Time.deltaTime * 0.01);
And use a seperate controller for the organic movement of the upper body, there should be some examples of that in the forums. Hope this helps.
Your answer
Follow this Question
Related Questions
Third person look around camera, jagged results 0 Answers
How to set viewpoint regardless of tilt of device when use gyroscope 0 Answers
Hard coded rotation of child results in weird arc rotation when parent is rotated? 0 Answers
Spyro Like Camera Follow 0 Answers
Simple Recoil and Reset System 0 Answers