原地址:http://blog.csdn.net/mobanchengshuang/article/details/27591271

好久没有敲Blog了,谢谢大家的留言、关注、私信等支持,但是我好像已经没有办法让自己继续写以前的博客系列了,因为我发现网上关于unity3D的内容太少了,所以我无法自拔地想写U3D相关的文章!!!

第三人称视角

第三人称视角是什么?很简单,CS就是一种第一人称视角游戏,玩家没有办法看到自己的角色形象,只能观察除开自己之外的游戏内容。第三人称视角那么就明显是能够看到玩家所控制的角色的一种视角。

而且大部分游戏的镜头不能固定不动,肯定是要跟随猪脚,能看到猪脚,但是保持一定的高度和距离,这样的视角才是最好的。

U3D中使用镜头来呈现游戏画面,一般来说是Main Camera。官方有一个使用JS书写的 第三人称镜头跟随脚本和猪脚控制脚本,但是鉴于U3D的js语法太过于诡异,于是我想自己去搞明白怎样来写一个自己用起来爽的第三人称镜头跟随脚本。

==去机场接个人,回来再继续写==

OK,下面分步骤完成这个脚本。关于添加猪脚的gameObject 以及添加CharacterController Component这里就不做解释了,前提是猪脚能够在场景中前后左右上下移动并且不会穿越障碍物然后我们继续往下写。

也就是我们的摄像机现在是固定视角,猪脚可以随意移动和跳跃,如图:

1.创建一个脚本文件CameraFollow.cs

2.接下来,分析我们最想要的效果:

a,摄像机保持和猪脚一定的高度差(y轴固定差值)和

b.距离差(x,z轴向量的合量相对固定);

c,面向猪脚的正前方

先完成目的a:

  1. //摄像机固定在猪脚上方10米高度
  2. public float camera_height=10.0f;
  3. //摄像机离猪脚大概10米的水平距离
  4. public float camera_distance=10.0f;
  5. //摄像机和猪脚的transform属性
  6. private Transform player;
  7. private Transform camera;
  8. // Use this for initialization
  9. void Start () {
  10. //初始化
  11. player=GameObject.FindGameObjectWithTag("Player").transform;
  12. camera = Camera.main.transform;
  13. }
  14. // Update is called once per frame
  15. void Update () {
  16. //每一帧都改变摄像机的高度
  17. camera.position = new Vector3 (player.position.x, player.position.y+ camera_height, player.position.z );
  18. }

效果:

我们在脚本中将高度距离两个变量暴露为public,可以在Inspector中修改,先改一个大概满意的高度

目前我们看不到猪脚,原因是摄像机的位置是取的猪脚的X,Z ,只是Y轴加上固定高度。

所以我们需要计算摄像机的X,Z坐标与猪脚的X,Z坐标是一个什么样的关系?

如果单纯的 取猪脚的X,Z坐标然后分别减去distance,是不行的,这样我们只有在某一个方向才能正好在猪脚后方

修改update中的赋值语句为:

那么我们运行游戏,选择到mainCamera,修改他的Y轴旋转度,直到镜头正好时刻在猪脚后方,发现这个角度一直是45°:

所以不难明白,当且仅当摄像机的Y轴偏离45°的时候,x,z各取地平面某一点的值,摄像机的位置在这个x,z坐标基础上减去一个相同的值,摄像机可以正好看到这个点在正中间。

这是为什么?我来画个图示意一下:

忽略掉摄像机的高度差,我们的猪脚在点O(α,0,α)

摄像机在O一撇(0,0,0)

要让摄像机正好看到猪脚在正中间且保持一定距离,那么本来摄像机的正前方是这个坐标系的Z轴正方向,现在改为朝射线O' O方向,那么偏离量很明显由于是个正方形的对角线,(这是透视下的正方形),角度为45°。

问题来了,我们难道要一直保持45°去望着猪脚吗,别忘了我们的摄像机随时要旋转保持正对猪脚的,那么这个位置到底该是多少呢?

我们 先把C完成:随时保证面向猪脚的正前方:

添加这两行代码之后,我们再看看问题出在哪儿:

很明显,摄像机的朝向是与猪脚的正前方朝向一致的,但是位置呢,当切仅当猪脚Y轴旋转度偏离Z轴正方向45°的时候,位置在猪脚正后方,小于45°偏左,大于45°偏右,180°+45°直接跑到猪脚正前面去了。

所以说,我们想要的情况是:

45°时,x 与z各减去 distance

180°+45°=225°时,x与z各加上distance

0°的时候,x不变,z-distance/sin45°  (为什么,因为实际上45°时候线段O'O的长度其实不是distance而是distance/sin45°,看我画的那个图,勾股定理)

90°的时候,z不变,x-distance/sin45°

所以其实我们这里的定义的distance参数名字和他代表的不一样,实际距离应该是distance/sin45°

所以不难归纳,我们以角度β为变量,得出x与β的函数关系为:

x-=distance*sinβ

z-=distance*cosβ

正好满足我们上面列的4个条件

由于我们代码中需要的三角函数参数是弧度而不是角度,所以这里把角度替换为弧度:

x-=distance*sin(β*π/180)

z-=distance*cos(β*π/180)

所以我们的代码应该修改为:

  1. //看向猪脚
  2. //camera.LookAt (player);
  3. //与猪脚的正前方为正前方(只取Y轴的旋转度)
  4. camera.eulerAngles =new Vector3(camera.eulerAngles.x,
  5. player.eulerAngles.y,
  6. camera.eulerAngles.z);
  7. //获取当前的镜头的Y轴旋转度
  8. float angle = camera.eulerAngles.y;
  9. //计算x轴的距离差:
  10. float deltaX = camera_distance * Mathf.Sin(angle * Mathf.PI /180 );
  11. float deltaZ = camera_distance * Mathf.Cos (angle * Mathf.PI / 180);
  12. //每一帧都改变摄像机的高度
  13. camera.position = new Vector3 (player.position.x-deltaX,
  14. player.position.y+ camera_height,
  15. player.position.z-deltaZ);

这个lookAt已经不需要了,因为我们的镜头旋转到猪脚的正前方并且位置在他的正后方,那么我们镜头必然已经在看他了

最后的效果是无论猪脚怎样走,我们的镜头都在完美地跟随:

完整脚本代码(比官方的例子精简吧):

    1. using UnityEngine;
    2. using System.Collections;
    3. //添加脚本到component菜单
    4. [AddComponentMenu ("CameraControl/Follow")]
    5. public class CameraFollow : MonoBehaviour {
    6. //摄像机固定在猪脚上方10米高度
    7. public float camera_height=10.0f;
    8. //摄像机离猪脚大概10米的水平距离
    9. public float camera_distance=10.0f;
    10. //摄像机和猪脚的transform属性
    11. private Transform player;
    12. private Transform camera;
    13. // Use this for initialization
    14. void Start () {
    15. //初始化
    16. player=GameObject.FindGameObjectWithTag("Player").transform;
    17. camera = Camera.main.transform;
    18. }
    19. // Update is called once per frame
    20. void Update () {
    21. //看向猪脚
    22. //camera.LookAt (player);
    23. //与猪脚的正前方为正前方(只取Y轴的旋转度)
    24. camera.eulerAngles =new Vector3(camera.eulerAngles.x,
    25. player.eulerAngles.y,
    26. camera.eulerAngles.z);
    27. //获取当前的镜头的Y轴旋转度
    28. float angle = camera.eulerAngles.y;
    29. //计算x轴的距离差:
    30. float deltaX = camera_distance * Mathf.Sin(angle * Mathf.PI /180 );
    31. float deltaZ = camera_distance * Mathf.Cos (angle * Mathf.PI / 180);
    32. //每一帧都改变摄像机的高度
    33. camera.position = new Vector3 (player.position.x-deltaX,
    34. player.position.y+ camera_height,
    35. player.position.z-deltaZ);
    36. Debug.Log("angle:"+angle+",deltax:"+deltaX+",deltaZ:"+deltaZ);
    37. }
    38. }

Unity3D中的第三人称镜头的脚本控制的更多相关文章

  1. Unity3D第三人称摄像机控制脚本

    好久没有敲Blog该.感谢您的留言.注意.私人信件和其他支持,但我似乎没有办法继续自己曾经写了一篇博客系列,因为我在网上找到有关unity3D太少的内容,U3D相关的文章!.. 第三人称视角 第三人称 ...

  2. 在Unity3d中解析Lua脚本的方法

    由于近期项目中提出了热更新的需求,因此本周末在Lua的陪伴下度过.对Lua与Unity3d的搭配使用,仅仅达到了一个初窥门径的程度,记录一二于此.水平有限,欢迎批评指正. 网络上关于Lua脚本和Uni ...

  3. (转)unity3d中脚本生命周期(MonoBehaviour lifecycle)

    自:http://blog.csdn.net/qitian67/article/details/18516503 最近在做一个小示例,发现类继承于MonoBehaviour的类,有很多个方法,于是乎必 ...

  4. (转) [教程] Unity3D中角色的动画脚本的编写(一)

    ps: 这两天研究unity3d,对动画处理特别迷糊,不知FBX导入以后,接下来应该怎么操作,看到这篇文章,感觉非常好,讲解的很详细. 已有好些天没写什么了,今天想起来该写点东西了.这次我所介绍的内容 ...

  5. Unity3d中如何混用三种脚本语言?

    首先要明白,这三种说的混用是指文件级别的混用,就是说一个文件是由一种语言写的.而不是说你这一个文件可以混用这三种语言,注意这是不允许的. 第二要明白,在unity3d中为什么可以使用三种语言混合开发? ...

  6. UE4中创建第一、第三人称角色,并进行角色间的切换

    在游戏中经常会出现第一人称和第三人称的视角切换场景,笔者在这里简单介绍如何进行这步操作. 1.创建角色 在内容浏览器中添加2个Character蓝图,分别命名为FirstPersonalCharact ...

  7. 【转】Unity3D中脚本的执行顺序和编译顺序

    支持原文,原文请戳: Unity3D中脚本的执行顺序和编译顺序 在Unity中可以同时创建很多脚本,并且可以分别绑定到不同的游戏对象上,它们各自都在自己的生命周期中运行.与脚本有关的也就是编译和执行啦 ...

  8. Unity小知识---第三人称中设置摄像机的简单跟随

    第三人称中设置摄像机的简单跟随 private Transform player; private Vector3 offect; private float smooothing = 3f; //插 ...

  9. Unity3D中自带事件函数的执行顺序(转)

    原文:http://www.jianshu.com/p/1d93ece664e2 在Unity3D脚本中,有几个Unity3D自带的事件函数按照预定的顺序执行作为脚本执行.其执行顺序如下: 编辑器(E ...

随机推荐

  1. 如何在Xilinx ISE中使用TCL提高工作效率

    http://wenku.baidu.com/link?url=jxtsPLGUlWwYuD8TtfWYYU_NhY5Qty3rx8ZDLCkINLe39JRGb90V5HoJhnkn9r_PQ6vZ ...

  2. C#中调用存储过程

    [csharp] view plain copy print? string strsql = "Data Source=192.168.24.53;Initial Catalog=JF_C ...

  3. UDP 多播 Java

    1.服务端 public class UdpMulticastServer { /** * @param args */ public static void main(String[] args) ...

  4. 谈谈asp.net中的<% %>,<%= %>,<%# %><%$ %>的使用

    学而不思则罔,思而不学则殆,每天坚持一小步,则成功一大步 asp.net中的<% %>,<%= %>,<%#eval("") %><%$ ...

  5. iOS开发——https+证书

    由于公司项目的需要,经过调研后,已成功. 同事已把此问题写成博客<[加密解密]HTTPS>,我就直接转用了 附带链接如下: http://www.jianshu.com/p/8351917 ...

  6. JavaScript中事件绑定的方法总结

    最近收集了一些关于JavaScript绑定事件的方法,汇总了一下,不全面,但是,希望便于以后自己查看. JavaScript中绑定事件的方法主要有三种: 1 在DOM元素中直接绑定 2 JavaScr ...

  7. TreeSet集合

    TreeSet集合 TreeSet集合是一个依靠TreeMap实现的有序集合,内部存储元素是自动按照自然排序进行排列,所以如果想要保留存储时的顺序,那么就不建议使用TreeSet. TreeSet继承 ...

  8. (转)web.config 为某个单独页面设置编码格式

    原文链接:http://www.cnblogs.com/mytechblog/articles/1937407.html 全站应用utf-8格式,在web.config里的<system.web ...

  9. width() innerwidth() outerwidth() css('width')

    不多说,用一图足以说明 首先先解释下普通元素和非普通元素, 非普通元素是指window,document这些 元素对象, 普通元素是指除window,document之外的元素,如:div 对于普通的 ...

  10. java StringBuffer与StringBuilder

    StringBuffer:就是字符串缓冲区.         * 用于存储数据的容器.         * 特点:         * 1,长度的可变的.          * 2,可以存储不同类型数 ...