游戏开发中,主相机应该是最重要的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. web标准之道——笔记

    字体设置 sans和sans-serif为通用字体,具体哪个字体被最终应用由浏览器决定,通用字体只有在其他字体都无效时才会被当作代替方案.通用字体应该放在最后面 sans衬线字体 容易阅读,一般使用在 ...

  2. Encountered an unexpected error when attempting to resolve tag helper directive '@addTagHelper' with value '"*, Microsoft.AspNet.Mvc.TagHelpers"'

    project.json 配置: { "version": "1.0.0-*", "compilationOptions": { " ...

  3. spring mvc DispatcherServlet详解之前传---FrameworkServlet

    做项目时碰到Controller不能使用aop进行拦截,从网上搜索得知:使用spring mvc 启动了两个context:applicationContext 和WebapplicationCont ...

  4. 打造android偷懒神器———ListView的万能适配器

    如果你去做任何一个项目,我相信你都会跟我有一样的经历,最最普遍的就是列表显示ListView,当然,写N个自定义的适配器也是情理之中.虽说程序员本身就是搬砖,做这些枯燥无味的重复的事情也是理所当然,但 ...

  5. 用SignalR 2.0开发客服系统[系列5:使用SignalR的中文简体语言包和其他技术点]

    前言 交流群:195866844 目录: 用SignalR 2.0开发客服系统[系列1:实现群发通讯] 用SignalR 2.0开发客服系统[系列2:实现聊天室] 用SignalR 2.0开发客服系统 ...

  6. winform程序一启动抛出异常--调用目标发生异常

    在本机测试没有问题,可一到别的电脑上就抛出异常,这是最麻烦的事,一时间还找不出什么原因,本机上还无法重现. 现在好了,终于找到一个完美解决的办法,在Program.cs类中加入如下代码 static ...

  7. Sqlserver调用api

    虽然使用sqlserver去调用服务接口的情况比较少,但也可以去了解下对应的使用情况 一.首先要开启组件的配置 sp_configure ; GO RECONFIGURE; GO sp_configu ...

  8. ubuntu Chromium 安装 pepperflashplugin

    sudo apt-get update sudo apt-get install chromium-browser sudo apt-get install pepperflashplugin-non ...

  9. 【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 很长时间没有来更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其实已经完成了一个框架了,并且正在准备在生产环境中 ...

  10. JavaWeb_day07_JSP

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! day07 JSP 全称 :Java Server P ...