- Home /
Using gamepad triggers to control 3rd person camera
I'm working on a control scheme that has movement that basically matches up well enough with the default 3rd person controller that I'm trying to roll with it to save a bit of time and have a well-functioning script for the prototype rather than something janky, since this particular game relies entirely on motion feeling natural. The only issue I have is that I want to make the analog triggers control the camera's rotation and set a much longer timer for the camera moving back around to the back of the player. Basically, I just want it to rotate around the player and MAYBE have it so that after a long enough time idle, it will move around back again, although that is far from necessary.
I know it makes me sound like a total noob, but the biggest issue I'm having is I can't read the code well enough to determine where exactly I'd have to change it from an automated action to one that relies on input. I've looked at tons of tutorials, but everything seems to be focused toward full camera control, usually with the mouse, and since the camera has the type of movement that I want already, it seems silly to try to fish the lines out of those tutorials when everything else works as intended so far. The camera script as I have it is here:
using UnityEngine;
using System.Collections;
public class ThirdPersonCamera : MonoBehaviour
{
public Transform cameraTransform;
private Transform _target;
// The distance in the x-z plane to the target
public float distance= 7.0f;
// the height we want the camera to be above the target
public float height= 3.0f;
public float angularSmoothLag= 0.3f;
public float angularMaxSpeed= 15.0f;
public float heightSmoothLag= 0.3f;
public float snapSmoothLag= 0.2f;
public float snapMaxSpeed= 720.0f;
public float clampHeadPositionScreenSpace= 0.75f;
public float lockCameraTimeout= 0.2f;
private Vector3 headOffset= Vector3.zero;
private Vector3 centerOffset= Vector3.zero;
private float heightVelocity= 0.0f;
private float angleVelocity= 0.0f;
private bool snap= false;
private ThirdPersonController controller;
private float targetHeight= 100000.0f;
void Awake (){
if(!cameraTransform && Camera.main)
cameraTransform = Camera.main.transform;
if(!cameraTransform) {
Debug.Log("Please assign a camera to the ThirdPersonCamera script.");
enabled = false;
}
_target = transform;
if (_target)
{
controller = _target.GetComponent<ThirdPersonController>();
}
if (controller)
{
CharacterController characterController = _target.GetComponent<CharacterController>();
centerOffset = characterController.bounds.center - _target.position;
headOffset = centerOffset;
headOffset.y = characterController.bounds.max.y - _target.position.y;
}
else
Debug.Log("Please assign a target to the camera that has a ThirdPersonController script attached.");
Cut(_target, centerOffset);
}
void DebugDrawStuff (){
Debug.DrawLine(_target.position, _target.position + headOffset);
}
public float AngleDistance ( float a , float b ){
a = Mathf.Repeat(a, 360);
b = Mathf.Repeat(b, 360);
return Mathf.Abs(b - a);
}
void Apply ( Transform dummyTarget , Vector3 dummyCenter ){
// Early out if we don't have a target
if (!controller)
return;
Vector3 targetCenter= _target.position + centerOffset;
Vector3 targetHead= _target.position + headOffset;
// DebugDrawStuff();
// Calculate the current & target rotation angles
float originalTargetAngle= _target.eulerAngles.y;
float currentAngle= cameraTransform.eulerAngles.y;
// Adjust real target angle when camera is locked
float targetAngle= originalTargetAngle;
// When pressing Fire2 (alt) the camera will snap to the target direction real quick.
// It will stop snapping when it reaches the target
if (Input.GetButton("LockOn"))
snap = true;
if (snap)
{
// We are close to the target, so we can stop snapping now!
if (AngleDistance (currentAngle, originalTargetAngle) < 3.0f)
snap = false;
currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angleVelocity, snapSmoothLag, snapMaxSpeed);
}
// Normal camera motion
else
{
if (controller.GetLockCameraTimer () < lockCameraTimeout)
{
targetAngle = currentAngle;
}
// Lock the camera when moving backwards!
// * It is really confusing to do 180 degree spins when turning around.
if (AngleDistance (currentAngle, targetAngle) > 160 && controller.IsMovingBackwards ())
targetAngle += 180;
currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angleVelocity, angularSmoothLag, angularMaxSpeed);
}
// When jumping don't move camera upwards but only down!
if (controller.IsJumping ())
{
// We'd be moving the camera upwards, do that only if it's really high
float newTargetHeight= targetCenter.y + height;
if (newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5)
targetHeight = targetCenter.y + height;
}
// When walking always update the target height
else
{
targetHeight = targetCenter.y + height;
}
// Damp the height
float currentHeight= cameraTransform.position.y;
currentHeight = Mathf.SmoothDamp (currentHeight, targetHeight, ref heightVelocity, heightSmoothLag);
// Convert the angle into a rotation, by which we then reposition the camera
Quaternion currentRotation= Quaternion.Euler (0, currentAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
cameraTransform.position = targetCenter;
cameraTransform.position += currentRotation * Vector3.back * distance;
Vector3 tempCameraTransformPos=cameraTransform.position;
tempCameraTransformPos.y=currentHeight;
cameraTransform.position=tempCameraTransformPos;
// Always look at the target
SetUpRotation(targetCenter, targetHead);
}
void LateUpdate (){
Apply (transform, Vector3.zero);
}
void Cut ( Transform dummyTarget , Vector3 dummyCenter ){
float oldHeightSmooth= heightSmoothLag;
float oldSnapMaxSpeed= snapMaxSpeed;
float oldSnapSmooth= snapSmoothLag;
snapMaxSpeed = 10000;
snapSmoothLag = 0.001f;
heightSmoothLag = 0.001f;
snap = true;
Apply (transform, Vector3.zero);
heightSmoothLag = oldHeightSmooth;
snapMaxSpeed = oldSnapMaxSpeed;
snapSmoothLag = oldSnapSmooth;
}
void SetUpRotation ( Vector3 centerPos , Vector3 headPos ){
// Now it's getting hairy. The devil is in the details here, the big issue is jumping of course.
// * When jumping up and down we don't want to center the guy in screen space.
// This is important to give a feel for how high you jump and avoiding large camera movements.
//
// * At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth.
//
// So here is what we will do:
//
// 1. We first find the rotation around the y axis. Thus he is always centered on the y-axis
// 2. When grounded we make him be centered
// 3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold
// 4. When landing we smoothly interpolate towards centering him on screen
Vector3 cameraPos= cameraTransform.position;
Vector3 offsetToCenter= centerPos - cameraPos;
// Generate base rotation only around y-axis
Quaternion yRotation= Quaternion.LookRotation(new Vector3(offsetToCenter.x, 0, offsetToCenter.z));
Vector3 relativeOffset= Vector3.forward * distance + Vector3.down * height;
cameraTransform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);
// Calculate the projected center position and top position in world space
Ray centerRay= cameraTransform.camera.ViewportPointToRay(new Vector3(.5f, 0.5f, 1f));
Ray topRay= cameraTransform.camera.ViewportPointToRay(new Vector3(.5f, clampHeadPositionScreenSpace, 1f));
Vector3 centerRayPos= centerRay.GetPoint(distance);
Vector3 topRayPos= topRay.GetPoint(distance);
float centerToTopAngle= Vector3.Angle(centerRay.direction, topRay.direction);
float heightToAngle= centerToTopAngle / (centerRayPos.y - topRayPos.y);
float extraLookAngle= heightToAngle * (centerRayPos.y - centerPos.y);
if (extraLookAngle < centerToTopAngle)
{
extraLookAngle = 0;
}
else
{
extraLookAngle = extraLookAngle - centerToTopAngle;
cameraTransform.rotation *= Quaternion.Euler(-extraLookAngle, 0, 0);
}
}
public Vector3 GetCenterOffset (){
return centerOffset;
}
}
Any help is appreciated.
Answer by thedalek247 · Nov 26, 2014 at 09:06 PM
Have you tried using input.Getbutton
? you could use that then configure it so that if the bumper is pressed the camera rotates 90 degrees on the y axis,that's basically what the code does,just automatically.
Answer by meat5000 · Nov 26, 2014 at 09:07 PM
You will need to set up the Z-Axis in the Input Manager and then use this
http://docs.unity3d.com/ScriptReference/Input.GetAxis.html to read it.
According to Windows, gamepad triggers not not buttons but the Z-Axis.
Your answer
Follow this Question
Related Questions
How to make the character move and rotate where the camera is facing (3rd person) 0 Answers
How to get JUST the y rotation of an object? 3 Answers
transform.rotation and localRotation automatically reset after rotating. 1 Answer
How to move player in direction where the camera is aiming ? 1 Answer
Set Character's Rotation 1 Answer