這是目前在用的Unity玩家攝影機控制Component,掛在攝影機同個GameObject中,設定追蹤對象( target )後就可以使用。
簡單介紹:
滑鼠上下左右移動 = 旋轉
滑鼠滾輪滾動 = 拉近拉遠 ( 需勾選 enableScrollZoomIn )
滑鼠中鍵按住後移動 = 拖曳畫面 ( 需勾選 enableHoldShift )
腳本免費提供,不負修改BUG的責任。
有使用的話請基本的禮貌性回覆。
\( ̄﹁ ̄)/ 腳本內容如下 \( ̄﹁ ̄)/
using UnityEngine;
using System.Collections;
/* Authur : Wei
* This is a third person shooter camera controller.
* Usage:
* Place this component together with Unity Camera component.
* Set a target ( the main character which player controls ) to trace at.
*
* */
public class TPSCameraController : MonoBehaviour
{
public Transform target = null; // the target this camera should trace to.
public float distanceToTarget = 5f; // camera distance to target.
public float minDistToTarget = 1f; // min distance to target. ( should be character radius )
public float maxDistToTarget = 20f; // max distance to target.
public float radius = 1f; // camera radius ( for collison test )
public Vector3 offset = Vector3.up; // camera offset height focus on target.
public float rotateSpeed = 1f; // speed camera orbits target.
public float maxPitchDeg = 60f; // max degree camera can pitch around local x axis. No greater than 90.
public bool enableScrollZoomIn = false; // enable scroll mouse scroll button to zoom in / out.
public float zoomSpeed = 10f;
public bool reverseScrollDir = false;
public bool enableHoldShift = false; // enable hold mouse scroll button to shift position.
public float shiftSpeed = 10f;
public bool reverseShiftUp = false;
public bool reverseShiftRight = false;
private float yawDeg = 0f; // current degree around world y axis.
private float pitchDeg = 0f; // current degree around local x axis.
private bool isShifting = false;
private float defaultYawDeg = 0f;
private float defaultPitchDeg = 0f;
private Vector3 defaultOffset = Vector3.up;
public void ResetToDefault()
{
yawDeg = defaultYawDeg;
pitchDeg = defaultPitchDeg;
offset = defaultOffset;
}
void Start ()
{
if( target == null )
{
Debug.LogWarning( "Camera controller target not set! You must set a target to trace." );
}
if( maxPitchDeg > 90f )
{
maxPitchDeg = 90f;
}
// get camera direction to target
Vector3 startDir = camera.transform.position - target.transform.position;
// get camera to target start degree
float fromDeg = Mathf.Atan2(Vector3.forward.x, Vector3.forward.z) * Mathf.Rad2Deg;
float toDeg = Mathf.Atan2(startDir.x, startDir.z) * Mathf.Rad2Deg;
yawDeg = Mathf.DeltaAngle( fromDeg, toDeg );
// remember default setting
defaultYawDeg = yawDeg;
defaultPitchDeg = pitchDeg;
defaultOffset = offset;
}
void LateUpdate ()
{
if( target == null ){ return; }
_UpdateShiftState();
// shift camera position
if( isShifting )
{
if( reverseShiftRight )
{
offset -= transform.right * Input.GetAxis("Mouse X") * shiftSpeed * Time.deltaTime;
}
else
{
offset += transform.right * Input.GetAxis("Mouse X") * shiftSpeed * Time.deltaTime;
}
if( reverseShiftUp )
{
offset -= transform.up * Input.GetAxis("Mouse Y") * shiftSpeed * Time.deltaTime;
}
else
{
offset += transform.up * Input.GetAxis("Mouse Y") * shiftSpeed * Time.deltaTime;
}
}
// rotate camera
else
{
// update desire yaw degree.
yawDeg += Input.GetAxis("Mouse X") * rotateSpeed * Time.deltaTime;
if( yawDeg > 360f )
{
yawDeg -= 360f;
}
else if( yawDeg < -360f )
{
yawDeg += 360f;
}
// update desire pitch degree.
pitchDeg += Input.GetAxis("Mouse Y") * rotateSpeed * Time.deltaTime;
if( pitchDeg > maxPitchDeg )
{
pitchDeg = maxPitchDeg;
}
else if( pitchDeg < -maxPitchDeg )
{
pitchDeg = -maxPitchDeg;
}
}
// update current distance to target.
if( enableScrollZoomIn )
{
if( reverseScrollDir )
{
distanceToTarget -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed * Time.deltaTime;
}
else
{
distanceToTarget += Input.GetAxis("Mouse ScrollWheel") * zoomSpeed * Time.deltaTime;
}
}
// rotate camera around world y-axis ( i.e. rotate left-ward and right-ward )
Quaternion rotateY = Quaternion.AngleAxis( yawDeg, Vector3.up );
// rotate camera around local x-axis ( i.e. rotate upward and downward )
Quaternion rotateX = Quaternion.AngleAxis( pitchDeg, Vector3.right );
// count camera direction to target.
Vector3 direction = rotateY * rotateX * Vector3.forward;
// count camera look at
Vector3 lookat = target.transform.position;
lookat += offset;
// check if any object between target to camera.
float _distToTarget = _RaycastHitCheck( lookat, direction );
// distance boundary.
if( _distToTarget < minDistToTarget )
{
_distToTarget = minDistToTarget;
}
if( _distToTarget > maxDistToTarget )
{
_distToTarget = maxDistToTarget;
}
// update camera position.
transform.position = lookat + direction * _distToTarget;
// update camera lookat.
transform.LookAt ( lookat );
}
void _UpdateShiftState()
{
if( !enableHoldShift ){ return; }
// NOTE: 2 is mid button.
if( Input.GetMouseButtonDown(2) )
{
isShifting = true;
}
if( Input.GetMouseButtonUp(2) )
{
isShifting = false;
}
}
/* Raycast to check if any object between the distacne from target to camera. If so, fix the distance.
* @param rayStart Raycast start position.
* @param distance Camera distance to target.
* @return Distance from camera to target.
* see http://docs.unity3d.com/Documentation/Components/Layers.html
* */
float _RaycastHitCheck( Vector3 rayStart, Vector3 direction )
{
// NOTE: layer 8 is "Character", don't want "Character" in camera raycast check.
// NOTE2: Trigger detection is switched off-ed in Edit -> Project Settings -> Physics Setting -> raycast hit triggers.
int layerMask = 1 << 8;
layerMask = ~layerMask;
RaycastHit hit;
if( Physics.SphereCast( rayStart, radius, direction, out hit, distanceToTarget, layerMask ) )
{
return hit.distance;
}
// no hit, return default.
return distanceToTarget;
}
}