unity旋转 缩放摄像机
2016-05-31 14:42
381 查看
研究了摄像机旋转、缩放等问题,那么今天为大家分享的是一个在3D展示中比较常用的功能,即通过鼠标右键实现旋转、鼠标滚轮实现缩放、鼠标中键实现平移。本文采用的方法依然是在[Unity3D]Unity3D游戏开发之自由视角下的角色控制这篇文章中所采用的方法,所以如果大家对于这部分内容不太了解的话,最好先去看看这篇文章。好了,下面我们将以一个具体的实例来讲解今天的内容。如图,是博主创建的一个简单地场景。我们希望实现通过鼠标右键实现对角色的旋转、鼠标滚轮实现对角色的缩放、鼠标中键实现对角色的平移。
好了,接下来我们来创建一个名为FreeView的脚本,该脚本依附在主相机上,下面我们来看它的实现过程:
[csharp]
view plain
copy
using UnityEngine;
using System.Collections;
public class FreeView : MonoBehaviour {
//观察目标
public Transform Target;
//观察距离
public float Distance = 5F;
//旋转速度
private float SpeedX=240;
private float SpeedY=120;
//角度限制
private float MinLimitY = -180;
private float MaxLimitY = 180;
//旋转角度
private float mX = 0.0F;
private float mY = 0.0F;
//鼠标缩放距离最值
private float MaxDistance=10;
private float MinDistance=1.5F;
//鼠标缩放速率
private float ZoomSpeed=2F;
//是否启用差值
public bool isNeedDamping=true;
//速度
public float Damping=10F;
//存储角度的四元数
private Quaternion mRotation;
//定义鼠标按键枚举
private enum MouseButton
{
//鼠标左键
MouseButton_Left=0,
//鼠标右键
MouseButton_Right=1,
//鼠标中键
MouseButton_Midle=2
}
//相机移动速度
private float MoveSpeed=5.0F;
//屏幕坐标
private Vector3 mScreenPoint;
//坐标偏移
private Vector3 mOffset;
void Start ()
{
//初始化旋转角度
mX=transform.eulerAngles.x;
mY=transform.eulerAngles.y;
}
void LateUpdate ()
{
//鼠标右键旋转
if(Target!=null && Input.GetMouseButton((int)MouseButton.MouseButton_Right))
{
//获取鼠标输入
mX += Input.GetAxis("Mouse X") * SpeedX * 0.02F;
mY -= Input.GetAxis("Mouse Y") * SpeedY * 0.02F;
//范围限制
mY = ClampAngle(mY,MinLimitY,MaxLimitY);
//计算旋转
mRotation = Quaternion.Euler(mY, mX, 0);
//根据是否插值采取不同的角度计算方式
if(isNeedDamping){
transform.rotation = Quaternion.Lerp(transform.rotation,mRotation, Time.deltaTime*Damping);
}else{
transform.rotation = mRotation;
}
}
//鼠标中键平移
//鼠标滚轮缩放
Distance-=Input.GetAxis("Mouse ScrollWheel") * ZoomSpeed;
Distance=Mathf.Clamp(Distance,MinDistance,MaxDistance);
//重新计算位置
Vector3 mPosition = mRotation * new Vector3(0.0F, 0.0F, -Distance) + Target.position;
//设置相机的位置
if(isNeedDamping){
transform.position = Vector3.Lerp(transform.position,mPosition, Time.deltaTime*Damping);
}else{
transform.position = mPosition;
}
}
//角度限制
private float ClampAngle (float angle,float min,float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp (angle, min, max);
}
}
大家是不是觉得这部分代码很熟悉?不错,这里的原理都是一样的,大家只要掌握核心原理就可以了,即首先根据鼠标输入来计算旋转角、然后通过滚轮输入计算距离、最后通过四元数运算计算相机的角度和距离。好了,我们来看看最终的效果吧!
大家应该注意到博主没有实现按下鼠标中键平移的相关方法,因为这部分博主目前还没有彻底正确地写出来,如果大家知道的话,可以给博主留言,或者等博主什么时候想清楚了再来更新这篇博客吧。博主的博客会经常更新的,希望大家继续关注我的博客吧。好了,最后我们再来做一个迁移,我们将把这个功能移植到Android平台上,本来想把这部分作为Android手势控制单独写一篇文章的,可是感觉这里的代码都是相似的,再写一篇实在没有必要,所以,就直接给出代码吧!
[csharp]
view plain
copy
using UnityEngine;
using System.Collections;
public class MobileInput : MonoBehaviour {
//观察目标
public Transform Target;
//观察距离
public float Distance = 2F;
//距离最值
public float MaxDistance=5F;
public float MinDistance=0.5F;
//缩放速率
private float ZoomSpeed=0.15F;
//旋转速度
private float SpeedX=240;
private float SpeedY=120;
//角度限制
private float MinLimitY = 5;
private float MaxLimitY = 180;
//旋转角度
private float mX=0;
private float mY=0;
//当前手势
private Vector2 mPos;
void Start ()
{
//允许多点触控
Input.multiTouchEnabled=true;
//初始化旋转
mX=Target.eulerAngles.x;
mY=Target.eulerAngles.y;
}
void Update ()
{
if(!Target) return;
//单点触控
if(Input.touchCount==1)
{
//手指处于移动状态
if(Input.touches[0].phase==TouchPhase.Moved)
{
mX+=Input.GetAxis("Mouse X") * SpeedX * 0.02F;
mY-=Input.GetAxis("Mouse X") * SpeedY * 0.02F;
mY=ClampAngle(mY,MinLimitY,MaxLimitY);
}
}
//多点触控
if(Input.touchCount>1)
{
//两只手指都处于移动状态
if(Input.touches[0].phase==TouchPhase.Moved || Input.touches[1].phase==TouchPhase.Moved)
{
//计算移动方向
Vector2 mDir=Input.touches[1].position-Input.touches[0].position;
//根据向量的大小判断当前手势是放大还是缩小
if(mDir.sqrMagnitude>mPos.sqrMagnitude){
Distance-=ZoomSpeed;
}else{
Distance+=ZoomSpeed;
}
//限制距离
Distance=Mathf.Clamp(Distance,MinDistance,MaxDistance);
//更新当前手势
mPos=mDir;
}
}
//计算相机的角度和位置
transform.rotation=Quaternion.Euler(new Vector3(mY,mX,0));
transform.position=transform.rotation * new Vector3(0,0,-Distance)+Target.position;
}
//角度限制
private float ClampAngle (float angle,float min,float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp (angle, min, max);
}
}
下面是程序在手机上运行过程中的截图
研究了摄像机旋转、缩放等问题,那么今天为大家分享的是一个在3D展示中比较常用的功能,即通过鼠标右键实现旋转、鼠标滚轮实现缩放、鼠标中键实现平移。本文采用的方法依然是在[Unity3D]Unity3D游戏开发之自由视角下的角色控制这篇文章中所采用的方法,所以如果大家对于这部分内容不太了解的话,最好先去看看这篇文章。好了,下面我们将以一个具体的实例来讲解今天的内容。如图,是博主创建的一个简单地场景。我们希望实现通过鼠标右键实现对角色的旋转、鼠标滚轮实现对角色的缩放、鼠标中键实现对角色的平移。
好了,接下来我们来创建一个名为FreeView的脚本,该脚本依附在主相机上,下面我们来看它的实现过程:
[csharp]
view plain
copy
using UnityEngine;
using System.Collections;
public class FreeView : MonoBehaviour {
//观察目标
public Transform Target;
//观察距离
public float Distance = 5F;
//旋转速度
private float SpeedX=240;
private float SpeedY=120;
//角度限制
private float MinLimitY = -180;
private float MaxLimitY = 180;
//旋转角度
private float mX = 0.0F;
private float mY = 0.0F;
//鼠标缩放距离最值
private float MaxDistance=10;
private float MinDistance=1.5F;
//鼠标缩放速率
private float ZoomSpeed=2F;
//是否启用差值
public bool isNeedDamping=true;
//速度
public float Damping=10F;
//存储角度的四元数
private Quaternion mRotation;
//定义鼠标按键枚举
private enum MouseButton
{
//鼠标左键
MouseButton_Left=0,
//鼠标右键
MouseButton_Right=1,
//鼠标中键
MouseButton_Midle=2
}
//相机移动速度
private float MoveSpeed=5.0F;
//屏幕坐标
private Vector3 mScreenPoint;
//坐标偏移
private Vector3 mOffset;
void Start ()
{
//初始化旋转角度
mX=transform.eulerAngles.x;
mY=transform.eulerAngles.y;
}
void LateUpdate ()
{
//鼠标右键旋转
if(Target!=null && Input.GetMouseButton((int)MouseButton.MouseButton_Right))
{
//获取鼠标输入
mX += Input.GetAxis("Mouse X") * SpeedX * 0.02F;
mY -= Input.GetAxis("Mouse Y") * SpeedY * 0.02F;
//范围限制
mY = ClampAngle(mY,MinLimitY,MaxLimitY);
//计算旋转
mRotation = Quaternion.Euler(mY, mX, 0);
//根据是否插值采取不同的角度计算方式
if(isNeedDamping){
transform.rotation = Quaternion.Lerp(transform.rotation,mRotation, Time.deltaTime*Damping);
}else{
transform.rotation = mRotation;
}
}
//鼠标中键平移
//鼠标滚轮缩放
Distance-=Input.GetAxis("Mouse ScrollWheel") * ZoomSpeed;
Distance=Mathf.Clamp(Distance,MinDistance,MaxDistance);
//重新计算位置
Vector3 mPosition = mRotation * new Vector3(0.0F, 0.0F, -Distance) + Target.position;
//设置相机的位置
if(isNeedDamping){
transform.position = Vector3.Lerp(transform.position,mPosition, Time.deltaTime*Damping);
}else{
transform.position = mPosition;
}
}
//角度限制
private float ClampAngle (float angle,float min,float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp (angle, min, max);
}
}
大家是不是觉得这部分代码很熟悉?不错,这里的原理都是一样的,大家只要掌握核心原理就可以了,即首先根据鼠标输入来计算旋转角、然后通过滚轮输入计算距离、最后通过四元数运算计算相机的角度和距离。好了,我们来看看最终的效果吧!
大家应该注意到博主没有实现按下鼠标中键平移的相关方法,因为这部分博主目前还没有彻底正确地写出来,如果大家知道的话,可以给博主留言,或者等博主什么时候想清楚了再来更新这篇博客吧。博主的博客会经常更新的,希望大家继续关注我的博客吧。好了,最后我们再来做一个迁移,我们将把这个功能移植到Android平台上,本来想把这部分作为Android手势控制单独写一篇文章的,可是感觉这里的代码都是相似的,再写一篇实在没有必要,所以,就直接给出代码吧!
[csharp]
view plain
copy
using UnityEngine;
using System.Collections;
public class MobileInput : MonoBehaviour {
//观察目标
public Transform Target;
//观察距离
public float Distance = 2F;
//距离最值
public float MaxDistance=5F;
public float MinDistance=0.5F;
//缩放速率
private float ZoomSpeed=0.15F;
//旋转速度
private float SpeedX=240;
private float SpeedY=120;
//角度限制
private float MinLimitY = 5;
private float MaxLimitY = 180;
//旋转角度
private float mX=0;
private float mY=0;
//当前手势
private Vector2 mPos;
void Start ()
{
//允许多点触控
Input.multiTouchEnabled=true;
//初始化旋转
mX=Target.eulerAngles.x;
mY=Target.eulerAngles.y;
}
void Update ()
{
if(!Target) return;
//单点触控
if(Input.touchCount==1)
{
//手指处于移动状态
if(Input.touches[0].phase==TouchPhase.Moved)
{
mX+=Input.GetAxis("Mouse X") * SpeedX * 0.02F;
mY-=Input.GetAxis("Mouse X") * SpeedY * 0.02F;
mY=ClampAngle(mY,MinLimitY,MaxLimitY);
}
}
//多点触控
if(Input.touchCount>1)
{
//两只手指都处于移动状态
if(Input.touches[0].phase==TouchPhase.Moved || Input.touches[1].phase==TouchPhase.Moved)
{
//计算移动方向
Vector2 mDir=Input.touches[1].position-Input.touches[0].position;
//根据向量的大小判断当前手势是放大还是缩小
if(mDir.sqrMagnitude>mPos.sqrMagnitude){
Distance-=ZoomSpeed;
}else{
Distance+=ZoomSpeed;
}
//限制距离
Distance=Mathf.Clamp(Distance,MinDistance,MaxDistance);
//更新当前手势
mPos=mDir;
}
}
//计算相机的角度和位置
transform.rotation=Quaternion.Euler(new Vector3(mY,mX,0));
transform.position=transform.rotation * new Vector3(0,0,-Distance)+Target.position;
}
//角度限制
private float ClampAngle (float angle,float min,float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp (angle, min, max);
}
}
下面是程序在手机上运行过程中的截图
相关文章推荐
- Unity的camera组件
- Unity中的Path对应各平台中的Path
- GVR-SDK-Unity初体验
- C#中delegate和event的区别(根据unity官方指南)
- Unity中文API,视频转换器(将任何格式的视频转换为.OGV格式)
- unity3D-iOS工程整合爬过的坑~
- 【Unity3D实战】RPG黑暗之光Scene3:创建游戏运行场景及角色控制
- Unity3d与Android交互总结
- U3D Distortion
- Unity3d PackingTag 字母大小写问题,导致图集错误
- IOC 依赖注入 Unity
- 重构Pomelo游戏框架的Unity客户端
- 2016年5月面试题(Unity&iOS)
- 近期unity ios接入的事情
- 【Unity3D实战】RPG黑暗之光Scene2:创建角色选择场景
- 从Profile中窥探Unity的内存管理
- 从Profile中窥探Unity的内存管理
- 简单打飞碟游戏
- 飞碟游戏-序列化
- Unity笔记