unity自带脚本ThirdPersonCamera.cs(收藏)
2015-03-26 18:25
148 查看
“`
using UnityEngine;
using System.Collections;
/**
* @Author : www.xuanyusong.com
*/
public class ThirdPersonCamera : MonoBehaviour {
public Transform cameraTransform;
private Transform _target;
public static float distance = 10.0f;
public float height = 1.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;
}
}
void DebugDrawStuff ()
{
Debug.DrawLine(_target.position, _target.position + headOffset);
}
float AngleDistance (float a , float b )
{
a = Mathf.Repeat(a, 360);
b = Mathf.Repeat(b, 360);
}
void Apply (Transform dummyTarget, Vector3 dummyCenter)
{
// Early out if we don’t have a target
if (!controller)
return;
// DebugDrawStuff();
}
void LateUpdate () {
Apply (transform, Vector3.zero);
}
void Cut (Transform dummyTarget , Vector3 dummyCenter)
{
float oldHeightSmooth = heightSmoothLag;
float oldSnapMaxSpeed = snapMaxSpeed;
float oldSnapSmooth = snapSmoothLag;
}
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;
}
}
using UnityEngine;
using System.Collections;
/**
* @Author : www.xuanyusong.com
*/
public class ThirdPersonCamera : MonoBehaviour {
public Transform cameraTransform;
private Transform _target;
public static float distance = 10.0f;
public float height = 1.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 = (CharacterController)_target.collider; 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);
}
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("Fire2")) snap = true; if (snap) { // We are close to the target, so we can stop snapping now! if (AngleDistance (currentAngle, originalTargetAngle) < 3.0) snap = false; currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angleVelocity, snapSmoothLag, snapMaxSpeed); } // Normal camera motion else { //targetÐýתֹͣºó£¬¾¹ýlockCameraTimeoutÃ룬Ïà»ú¿ªÊ¼×ªÏòtarget 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; // Set the height of the camera cameraTransform.position = new Vector3(cameraTransform.position.x,currentHeight,cameraTransform.position.z); // 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(0.5f, 0.5f, 1f)); Ray topRay = cameraTransform.camera.ViewportPointToRay(new Vector3(0.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); }
}
Vector3 GetCenterOffset () { return centerOffset; }
}
相关文章推荐
- unity自带脚本ThirdPersonController.cs(收藏)
- 我的游戏开发笔记(一):完善并把u3d自带的ThirdPersonController.js改成cs版本
- Unity基础包 FirstPersonController下的MouseLook 脚本研究
- UnityStandardAssets里自带的Joystick脚本修改
- unity脚本自带函数执行顺序
- Unity基础包 刚体FPS RigidbodyFirstPersonController 脚本研究
- Unity脚本自带函数的执行顺序
- Unity基础包 FirstPersonController 脚本研究
- unity脚本自带函数执行顺序
- unity脚本自带函数执行顺序
- BuildReport 插件导入unity脚本报错(BRT_Util.cs:error CS1525: Unexpected symbol `;', expecting `)', or `,')
- Unity基础包 FirstPersonController下的MouseLook 脚本研究
- Unity基础包 FirstPersonController下的FOVKick 脚本研究
- Unity 3D笔记——脚本让camera转动起来
- unity 中用vs 打开cs脚本找不到关联类
- Unity基础包 刚体FPS HeadBob和CameraRefocus 脚本研究
- ThirdPersonCamera
- unity 自带脚本smoothfollow的修改,实现不同方向的跟随
- unity脚本自带函数执行顺序
- Unity基础包 FirstPersonController下的CurveControlledBob和LerpContolledBob 脚本研究