游戏开发中,主相机应该是最重要的GameObject之一,毕竟游戏呈现给玩家,就是通过它。
相机的使用,在不同的游戏中,有很大的不同。这里总结一下自己学到的一些相关知识。

固定位置-游戏过程中相机的Transform属性不改变。

  • 调整好位置后就不要动了,一般使用正交相机,即Camera-Projection选择Orthographic。Unity Manual-Camera
    适用:2D游戏。比如飞机大战,消消乐。
  • 游戏开始后,相机追踪某一物体,然后固定不动。
    游戏开始后,我们才能确定追踪物体的位置,先看代码:
  1. using UnityEngine;
  2.  
  3. public class CameraController : MonoBehaviour
  4. {
  5. public GameObject player;
  6. private Vector3 offset;
  7. void Start ()
  8. {
  9. offset = transform.position - player.transform.position;
  10. }
  11. void LateUpdate ()
  12. {
  13. transform.position = player.transform.position + offset;
  14. }
  15. }

适用:固定视角的3D游戏。

3D视角-围绕一个中心随意旋转

先看代码:

  1. using UnityEngine;
  2.  
  3. public class CameraContorller : MonoBehaviour
  4. {
  5. /// <summary>
  6. /// 追踪目标
  7. /// </summary>
  8. public Transform target;
  9. /// <summary>
  10. /// 旋转速度
  11. /// </summary>
  12. public float xSpeed = , ySpeed = ;
  13. /// <summary>
  14. /// 缩放速度
  15. /// </summary>
  16. public float mSpeed = ;
  17. /// <summary>
  18. /// 最小/最大限制角度
  19. /// </summary>
  20. public float yMinLimit = -, yMaxLimit = ;
  21. /// <summary>
  22. /// 是否使用插值运算
  23. /// </summary>
  24. public bool needDamping = true;
  25. /// <summary>
  26. /// 速度
  27. /// </summary>
  28. public float damping = 5.0f;
  29.  
  30. /// <summary>
  31. /// 观察距离
  32. /// </summary>
  33. private float distance = ;
  34. /// <summary>
  35. /// 最小/最大观察距离
  36. /// </summary>
  37. private float minDistance = , maxDistance = ;
  38. /// <summary>
  39. /// 旋转角度
  40. /// </summary>
  41. private float x = 0.0f, y = 0.0f;
  42.  
  43. void Start()
  44. {
  45. Vector3 angles = transform.eulerAngles;
  46. x = angles.y;
  47. y = angles.x;
  48. //根据相机的初始位置初始化距离,最大距离,最小距离;
  49. Vector3 offset = transform.position - target.position;
  50. distance = offset.magnitude;
  51. minDistance = distance / ;
  52. maxDistance = distance * ;
  53. }
  54.  
  55. void LateUpdate()
  56. {
  57. if (target)
  58. {
  59. if (Input.GetMouseButton())//0-左键,1-右键,2-中键
  60. {
  61. x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
  62. y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
  63.  
  64. y = ClampAngle(y, yMinLimit, yMaxLimit);
  65. }
  66. distance -= Input.GetAxis("Mouse ScrollWheel") * mSpeed;
  67. distance = Mathf.Clamp(distance, minDistance, maxDistance);
  68.  
  69. Quaternion rotation = Quaternion.Euler(y, x, 0.0f);
  70. Vector3 disVector = new Vector3(0.0f, 0.0f, -distance);
  71. Vector3 position = rotation * disVector + target.position;
  72. if (needDamping)
  73. {
  74. transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * damping);
  75. Vector3 transformTemp = Vector3.Lerp(transform.position, position, Time.deltaTime * damping);
  76. if (transformTemp.y <= )//如果相机位置在“水平面”以下,强制设置到水平面。
  77. {
  78. transform.position = new Vector3(transformTemp.x, , transformTemp.z);
  79. }
  80. else
  81. {
  82. transform.position = transformTemp;
  83. }
  84. }
  85. else
  86. {
  87. transform.rotation = rotation;
  88. if (position.y <= )//如果相机位置在“水平面”以下,强制设置到水平面。
  89. {
  90. transform.position = new Vector3(position.x, , position.z);
  91. }
  92. else
  93. {
  94. transform.position = position;
  95. }
  96. }
  97. }
  98. }
  99.  
  100. static float ClampAngle(float angle, float min, float max)
  101. {
  102. if (angle < -)
  103. angle += ;
  104. if (angle > )
  105. angle -= ;
  106. return Mathf.Clamp(angle, min, max);
  107. }
  108. }

大部分3D游戏中,我这样理解:主角看作球心,球半径玩家可以自己改变,相机的位置就在“地面”以上的半球球体上。
上面这段代码基本做到了这个要求,并在相机到“地面”的时候有抬头看的效果。
代码有点问题,开始游戏后相机会跳动两次,暂时放到自己的问题清单中。

其他用法

官方教程Tanks tutorial 中有个不常见的用法。
不管两个Tank如何移动,相机通过前后缩放,大小缩放保证两个Tank肯定在相机视野内。
主要代码:(官方代码写得好啊)

  1. private void Move ()
  2. {
  3. // Find the average position of the targets.
  4. FindAveragePosition ();
  5.  
  6. // Smoothly transition to that position.
  7. transform.position = Vector3.SmoothDamp(transform.position, m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
  8. }
  9.  
  10. private void FindAveragePosition ()
  11. {
  12. Vector3 averagePos = new Vector3 ();
  13. int numTargets = ;
  14.  
  15. // Go through all the targets and add their positions together.
  16. for (int i = ; i < m_Targets.Length; i++)
  17. {
  18. // If the target isn't active, go on to the next one.
  19. if (!m_Targets[i].gameObject.activeSelf)
  20. continue;
  21.  
  22. // Add to the average and increment the number of targets in the average.
  23. averagePos += m_Targets[i].position;
  24. numTargets++;
  25. }
  26.  
  27. // If there are targets divide the sum of the positions by the number of them to find the average.
  28. if (numTargets > )
  29. averagePos /= numTargets;
  30.  
  31. // Keep the same y value.
  32. averagePos.y = transform.position.y;
  33.  
  34. // The desired position is the average position;
  35. m_DesiredPosition = averagePos;
  36. }
  37.  
  38. private void Zoom ()
  39. {
  40. // Find the required size based on the desired position and smoothly transition to that size.
  41. float requiredSize = FindRequiredSize();
  42. m_Camera.orthographicSize = Mathf.SmoothDamp (m_Camera.orthographicSize, requiredSize, ref m_ZoomSpeed, m_DampTime);
  43. }
  44.  
  45. private float FindRequiredSize ()
  46. {
  47. // Find the position the camera rig is moving towards in its local space.
  48. Vector3 desiredLocalPos = transform.InverseTransformPoint(m_DesiredPosition);
  49.  
  50. // Start the camera's size calculation at zero.
  51. float size = 0f;
  52.  
  53. // Go through all the targets...
  54. for (int i = ; i < m_Targets.Length; i++)
  55. {
  56. // ... and if they aren't active continue on to the next target.
  57. if (!m_Targets[i].gameObject.activeSelf)
  58. continue;
  59.  
  60. // Otherwise, find the position of the target in the camera's local space.
  61. Vector3 targetLocalPos = transform.InverseTransformPoint(m_Targets[i].position);
  62.  
  63. // Find the position of the target from the desired position of the camera's local space.
  64. Vector3 desiredPosToTarget = targetLocalPos - desiredLocalPos;
  65.  
  66. // Choose the largest out of the current size and the distance of the tank 'up' or 'down' from the camera.
  67. size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.y));
  68.  
  69. // Choose the largest out of the current size and the calculated size based on the tank being to the left or right of the camera.
  70. size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.x) / m_Camera.aspect);
  71. }
  72.  
  73. // Add the edge buffer to the size.
  74. size += m_ScreenEdgeBuffer;
  75.  
  76. // Make sure the camera's size isn't below the minimum.
  77. size = Mathf.Max (size, m_MinSize);
  78.  
  79. return size;
  80. }

暂时放下的内容

Unity的相机相关:

[游戏开发-学习笔记]菜鸟慢慢飞(四)-Camera的更多相关文章

  1. [游戏开发-学习笔记]菜鸟慢慢飞(九)- NGUI- UIPanel(官方说明翻译)

    我自己笔记是做在OneNote上,直接复制粘贴过来变成图片了,效果好像还可以. 机器翻译,我自己看了一下,改了一部分.

  2. [游戏开发-学习笔记]菜鸟慢慢飞(九)- NGUI- UIWidget(官方说明翻译)

  3. 【整理】HTML5游戏开发学习笔记(5)- 猜谜游戏

    距上次学习笔记已有一个多月过去了,期间由于新项目赶进度,以致该学习计划给打断,十分惭愧.书本中的第六章的例子相对比较简单.所以很快就完成. 1.预备知识html5中video标签的熟悉 2.实现思路对 ...

  4. 【整理】HTML5游戏开发学习笔记(1)- 骰子游戏

    <HTML5游戏开发>,该书出版于2011年,似乎有些老,可对于我这样没有开发过游戏的人来说,却比较有吸引力,选择自己感兴趣的方向来学习html5,css3,相信会事半功倍.不过值得注意的 ...

  5. cocos2d-x 3.x游戏开发学习笔记(1)--mac下配置cocos2d-x 3.x开发环境

    打开用户文件夹下.bash_profile文件,配置环境 vim ~/.bash_profile //按键i,进行插入编辑(假设输错d进行删除一行) 环境配置过程例如以下: 1.首先配置下androi ...

  6. Photon + Unity3D 线上游戏开发 学习笔记(四)

    这一节 我们建立 photon Server 端的框架 一个最简单的Photon框架 就包括一个 Applocation 类 和 一个 peer 类,作用例如以下: *  Application 类是 ...

  7. [Android游戏开发学习笔记]View和SurfaceView

    本文为阅读http://blog.csdn.net/xiaominghimi/article/details/6089594的笔记. 在Android游戏中充当主要角色的,除了控制类就是显示类.而在A ...

  8. Photon + Unity3D 线上游戏开发 学习笔记(一)

    大家好. 我也是学习Photon + unity3D 的新手 有什么说错的地方大家见谅哈. 我的开发环境是 unity3D 4.1.3  ,   Visual Studio 是2010 版本号的  p ...

  9. 【Android开发学习笔记】【第四课】基础控件的学习

    通过一个简单的例子来学习下面几种控件: 1.TextView:简单的文本显示控件 2.EditText:可以编辑的文本框 3.Button:按钮 4.Menu:这里指的是系统的Menu 5.Toast ...

随机推荐

  1. 微软Ignite大会我的Session(SQL Server 2014 升级面面谈)PPT分享

       我在首届微软技术大会的Session分享了一个关于SQL Server升级的主题,现在将PPT分享出来.     您可以点击这里下载PPT.     也非常感谢微软中国邀请我进行这次分享.

  2. leetcode--5. Longest Palindromic Substring

    题目来自 https://leetcode.com/problems/longest-palindromic-substring/ 题目:Given a string S, find the long ...

  3. Android线程管理之ThreadPoolExecutor自定义线程池

    前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...

  4. 如何在删除ibdata1和ib_logfile的情况下恢复MySQL数据库

    昨天,有个朋友对公司内部使用的一个MySQL实例开启binlog,但是在启动的过程中失败了(他也没提,为何会失败),在启动失败后,他删除了ibdata1和ib_logfile,后来,能正常启动了,但所 ...

  5. Memcache缓存系统构建一

    在如今这个高效率的社会中,怎样将这个高效率应用到自己的程序中,是一个值得追寻和值得探讨的问题.因为这个memcache能够很好的提高检索速度,提升用户体验,而且重要的是减少数据库的访问.这就大大的提高 ...

  6. ActiveMQ消息队列的使用及应用

    这里就不说怎么安装了,直接解压出来就行了. 谢绝转载,作者保留所有权力 目录:  一:JMQ的两种消息模式 1.1:点对点的消息模式 1.2:订阅模式 二:点对点的实现代码 2.1:点对点的发送端 2 ...

  7. 利用Python进行数据分析(9) pandas基础: 汇总统计和计算

    pandas 对象拥有一些常用的数学和统计方法.   例如,sum() 方法,进行列小计:   sum() 方法传入 axis=1 指定为横向汇总,即行小计:   idxmax() 获取最大值对应的索 ...

  8. 实例讲解react+react-router+redux

    前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...

  9. A chatroom for all! Part 1 - Introduction to Node.js(转发)

    项目组用到了 Node.js,发现下面这篇文章不错.转发一下.原文地址:<原文>. ------------------------------------------- A chatro ...

  10. Ubuntu下的解压缩

    一. 命令: .tar 解包:tar xvf FileName.tar打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)———————————————.gz ...