基于Unity3D的相机功能的实现(八)—— 收藏篇

看到的不错的相机代码,分享一下生气

// Marmoset Skyshop
// Copyright 2013 Marmoset LLC
// http://marmoset.co

using UnityEngine;
using System.Collections;

public class FreeCamera : MonoBehaviour {	
	
	public float thetaSpeed = 250.0f;
	public float phiSpeed = 120.0f;
	public float moveSpeed = 10.0f;
	public float zoomSpeed = 30.0f;
	
	public float phiBoundMin = -89f;
	public float phiBoundMax = 89f;
	public bool useMoveBounds = true;
	public float moveBounds = 100f;
	
	public float rotateSmoothing = 0.5f;
	public float moveSmoothing = 0.7f;
		
	public float distance = 2.0f;
	private Vector2 euler;
	
	private Quaternion targetRot;
	private Vector3 targetLookAt;
	private float targetDist;
	private Vector3 distanceVec = new Vector3(0,0,0);
	
	private Transform target;
	private Rect inputBounds;
	public Rect paramInputBounds = new Rect(0,0,1,1);
	
	public bool usePivotPoint = true;
	public Vector3 pivotPoint = new Vector3(0,2,0);

	public Transform pivotTransform = null;
	#if UNITY_IPHONE || UNITY_ANDROID
	private bool firstTouch = true;
	#endif	
	
	public void Start () {
	    Vector3 angles = transform.eulerAngles;
	    euler.x = angles.y;
	    euler.y = angles.x;
		//unity only returns positive euler angles but we need them in -90 to 90
		euler.y = Mathf.Repeat(euler.y+180f, 360f)-180f;
		
		GameObject go = new GameObject("_FreeCameraTarget");
		go.hideFlags = HideFlags.HideAndDontSave | HideFlags.HideInInspector;
		target = go.transform;
		
		if( usePivotPoint ) {			
			target.position = pivotPoint;
			targetDist = (transform.position-target.position).magnitude;
		} else if(pivotTransform != null) {
			usePivotPoint = true;
			Vector3 localPos = transform.worldToLocalMatrix.MultiplyPoint3x4(pivotTransform.position);
			localPos.x = 0;
			localPos.y = 0;
			targetDist = localPos.z;
			target.position = transform.localToWorldMatrix.MultiplyPoint3x4(localPos);
		} else {
			target.position = transform.position + transform.forward * distance;
			targetDist = distance;
		}
		targetRot = transform.rotation;
		targetLookAt = target.position;
		#if UNITY_IPHONE || UNITY_ANDROID
		firstTouch = true;
		#endif
	}
	
	public void Update () {
		//NOTE: mouse coordinates have a bottom-left origin, camera top-left
		inputBounds.x = GetComponent<Camera>().pixelWidth * paramInputBounds.x;
		inputBounds.y = GetComponent<Camera>().pixelHeight * paramInputBounds.y;
		inputBounds.width = GetComponent<Camera>().pixelWidth * paramInputBounds.width;
		inputBounds.height = GetComponent<Camera>().pixelHeight * paramInputBounds.height;
	
	    if(target && inputBounds.Contains(Input.mousePosition)) {
	    	float dx = Input.GetAxis("Mouse X");
			float dy = Input.GetAxis("Mouse Y");
			#if UNITY_IPHONE || UNITY_ANDROID
			if(Input.multiTouchEnabled) {
				if(Input.touchCount > 0) {
					//touch-down detection. kekeke.
					if(!firstTouch) {
						dx += Input.GetTouch(0).deltaPosition.x * 0.01f;
						dy += Input.GetTouch(0).deltaPosition.y * 0.01f;
					}
					firstTouch = false;
				} else {
					firstTouch = true;
				}
			}
			#endif
			bool click1 = Input.GetMouseButton(0) || Input.touchCount == 1;
    		bool click2 = Input.GetMouseButton(1) || Input.touchCount == 2;
    		bool click3 = Input.GetMouseButton(2) || Input.touchCount == 3;
    		bool click4 = Input.touchCount >= 4;
			bool rotInput = click1;
			bool skyInput = click4 || click1 && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey (KeyCode.RightShift));
			bool panInput = click3 || click1 && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl));
			bool zoomInput = click2;
			
			if( skyInput ) {
				dx = dx * thetaSpeed * 0.02f;
//				mset.SkyManager manager = mset.SkyManager.Get();
//				if(manager && manager.GlobalSky) { 
//					manager.GlobalSky.transform.Rotate(new Vector3(0,dx,0));
//				}
			}
			else if( panInput ) {
				dx = dx * moveSpeed * 0.005f * targetDist;
	        	dy = dy * moveSpeed * 0.005f * targetDist;
	 			targetLookAt -= transform.up*dy + transform.right*dx;
				if( useMoveBounds ) {
			 		targetLookAt.x = Mathf.Clamp(targetLookAt.x,-moveBounds,moveBounds);
					targetLookAt.y = Mathf.Clamp(targetLookAt.y,-moveBounds,moveBounds);
			 		targetLookAt.z = Mathf.Clamp(targetLookAt.z,-moveBounds,moveBounds);
				}
			}
			else if( zoomInput ) {
				dy = dy * zoomSpeed * 0.005f * targetDist;
		 		targetDist += dy;
		 		targetDist = Mathf.Max(0.1f,targetDist);
	 		}
			else if( rotInput ) {
				dx = dx * thetaSpeed * 0.02f;
				dy = dy * phiSpeed * 0.02f;
				euler.x += dx;
		        euler.y -= dy;				
		        euler.y = ClampAngle(euler.y, phiBoundMin, phiBoundMax);
		        targetRot = Quaternion.Euler(euler.y, euler.x, 0);
			}
	 		
			targetDist -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed * 0.5f;
	 		targetDist = Mathf.Max(0.1f,targetDist);
		}
	}
	
	public void FixedUpdate() {
		distance = moveSmoothing*targetDist + (1-moveSmoothing)*distance;
		
		transform.rotation = Quaternion.Slerp( transform.rotation, targetRot, rotateSmoothing );
	    target.position = Vector3.Lerp(target.position, targetLookAt, moveSmoothing);
		distanceVec.z = distance;
	    transform.position = target.position - transform.rotation * distanceVec;
	}
	
	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);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值