原地址: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. webbroswer 后台注入脚本 的方法

    HtmlElement script = webBrowser.Document.CreateElement("script"); script.SetAttribute(&quo ...

  2. CentOS 7.x安装ELK(Elasticsearch+Logstash+Kibana)

    第一次听到ELK,是新浪的@ARGV 介绍内部使用ELK的情况和场景,当时触动很大,原来有那么方便的方式来收集日志和展现,有了这样的工具,你干完坏事,删除日志,就已经没啥作用了. 很多企业都表示出他们 ...

  3. MySQL flush privileges 명령어

    INSERT나 UPDATE, DELETE문을 이용해서 MySQL의 사용자를 추가,삭제하거나, 사용자 권한 등을 변경하였을 때, MySQL에 변경사항을 적용하기 위해서 사용하는 명령 ...

  4. Unity3D之Ugui 制作弹框

    创建一个UI控件. 这里通过按钮的点击取控制弹框的显示或者隐藏.给按钮Button绑定一个脚本. 将Panel初始化设置为隐藏.就可以实现了. using UnityEngine; using Sys ...

  5. C# 反射 设置字段值无效的解决办法

    FieldInfo.SetValue的原型是:void SetValue(object obj, object value)当你传递一个值类型(结构是值类型)的时候,它要转化成object,也就是要装 ...

  6. MySQL支持多种存储引擎

    MySQL的强大之处在于它的插件式存储引擎,我们可以基于表的特点使用不同的存储引擎,从而达到最好的性能. MySQL有多种存储引擎:MyISAM.InnoDB.MERGE.MEMORY(HEAP).B ...

  7. (poj)1064 Cable master 二分+精度

    题目链接:http://poj.org/problem?id=1064 Description Inhabitants of the Wonderland have decided to hold a ...

  8. Hdu 1042 N! (高精度数)

    Problem Description Givenan integer N(0 ≤ N ≤ 10000), your task is to calculate N! Input OneN in one ...

  9. ajaxSubmit() 上传文件和进度条显示

    1.  首先引用js文件 <script type="text/javascript" src="/js/jquery/jquery.form.js"&g ...

  10. 安卓热更新之Nuwa实现步骤

    安卓热更新之Nuwa实现步骤 最近热更新热修复的功能在安卓应用上越发火热,终于我的产品也提出了相应的需求. 经过两天的研究,搞定了这个功能,在这里还要多谢大神们的博客,大神们的原理分析很到位,不过对于 ...