好久没有敲Blog该。感谢您的留言、注意、私人信件和其他支持,但我似乎没有办法继续自己曾经写了一篇博客系列,因为我在网上找到有关unity3D太少的内容,U3D相关的文章!。。
第三人称视角
第三人称视角是什么?非常easy,CS就是一种第一人称视角游戏,玩家没有办法看到自己的角色形象,仅仅能观察除开自己之外的游戏内容。第三人称视角那么就明显是可以看到玩家所控制的角色的一种视角。
并且大部分游戏的镜头不能固定不动,肯定是要尾随猪脚。能看到猪脚,可是保持一定的高度和距离,这种视角才是最好的。
U3D中使用镜头来呈现游戏画面,一般来说是Main Camera。
官方有一个使用JS书写的 第三人称镜头尾随脚本和猪脚控制脚本,可是鉴于U3D的js语法太过于诡异。于是我想自己去搞明确如何来写一个自己用起来爽的第三人称镜头尾随脚本。
==去机场接个人,回来再继续写==
OK。以下分步骤完毕这个脚本。关于加入猪脚的gameObject 以及加入CharacterController Component这里就不做解释了,前提是猪脚可以在场景中前后左右上下移动而且不会穿越障碍物然后我们继续往下写。
也就是我们的摄像机如今是固定视角,猪脚能够任意移动和跳跃,如图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemF5MTA5MzI3NDAy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
1.创建一个脚本文件CameraFollow.cs
2.接下来。分析我们最想要的效果:
a,摄像机保持和猪脚一定的高度差(y轴固定差值)和
b.距离差(x,z轴向量的合量相对固定);
c,面向猪脚的正前方
先完毕目的a:
//摄像机固定在猪脚上方10米高度 public float camera_height=10.0f; //摄像机离猪脚大概10米的水平距离 public float camera_distance=10.0f; //摄像机和猪脚的transform属性 private Transform player; private Transform camera; // Use this for initialization void Start () { //初始化 player=GameObject.FindGameObjectWithTag("Player").transform; camera = Camera.main.transform; } // Update is called once per frame void Update () { //每一帧都改变摄像机的高度 camera.position = new Vector3 (player.position.x, player.position.y+ camera_height, player.position.z ); }
效果:
我们在脚本中将高度距离两个变量暴露为public,能够在Inspector中改动,先改一个大概惬意的高度
眼下我们看不到猪脚,原因是摄像机的位置是取的猪脚的X,Z 。仅仅是Y轴加上固定高度。
所以我们须要计算摄像机的X,Z坐标与猪脚的X,Z坐标是一个什么样的关系?
假设单纯的 取猪脚的X,Z坐标然后分别减去distance,是不行的,这样我们仅仅有在某一个方向才干正好在猪脚后方
改动update中的赋值语句为:
那么我们执行游戏,选择到mainCamera,改动他的Y轴旋转度,直到镜头正好时刻在猪脚后方。发现这个角度一直是45°:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemF5MTA5MzI3NDAy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
所以不难明确,当且仅当摄像机的Y轴偏离45°的时候,x,z各取地平面某一点的值,摄像机的位置在这个x,z坐标基础上减去一个同样的值。摄像机能够正好看到这个点在正中间。
这是为什么?我来画个图示意一下:
忽略掉摄像机的高度差。我们的猪脚在点O(α。0,α)
摄像机在O一撇(0,0,0)
要让摄像机正好看到猪脚在正中间且保持一定距离,那么本来摄像机的正前方是这个坐标系的Z轴正方向,如今改为朝射线O‘ O方向。那么偏离量非常明显因为是个正方形的对角线。(这是透视下的正方形),角度为45°。
问题来了,我们难道要一直保持45°去望着猪脚吗,别忘了我们的摄像机随时要旋转保持正对猪脚的。那么这个位置究竟该是多少呢?
我们 先把C完毕:随时保证面向猪脚的正前方:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemF5MTA5MzI3NDAy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
加入这两行代码之后。我们再看看问题出在哪儿:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemF5MTA5MzI3NDAy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
非常明显,摄像机的朝向是与猪脚的正前方朝向一致的,可是位置呢,当切仅当猪脚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)
所以我们的代码应该改动为:
//看向猪脚 //camera.LookAt (player); //与猪脚的正前方为正前方(仅仅取Y轴的旋转度) camera.eulerAngles =new Vector3(camera.eulerAngles.x, player.eulerAngles.y, camera.eulerAngles.z); //获取当前的镜头的Y轴旋转度 float angle = camera.eulerAngles.y; //计算x轴的距离差: float deltaX = camera_distance * Mathf.Sin(angle * Mathf.PI /180 ); float deltaZ = camera_distance * Mathf.Cos (angle * Mathf.PI / 180); //每一帧都改变摄像机的高度 camera.position = new Vector3 (player.position.x-deltaX, player.position.y+ camera_height, player.position.z-deltaZ);
这个lookAt已经不须要了,由于我们的镜头旋转到猪脚的正前方而且位置在他的正后方。那么我们镜头必定已经在看他了
最后的效果是不管猪脚如何走。我们的镜头都在完美地尾随:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemF5MTA5MzI3NDAy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
完整脚本代码(比官方的样例精简吧):
using UnityEngine; using System.Collections; //加入脚本到component菜单 [AddComponentMenu ("CameraControl/Follow")] public class CameraFollow : MonoBehaviour { //摄像机固定在猪脚上方10米高度 public float camera_height=10.0f; //摄像机离猪脚大概10米的水平距离 public float camera_distance=10.0f; //摄像机和猪脚的transform属性 private Transform player; private Transform camera; // Use this for initialization void Start () { //初始化 player=GameObject.FindGameObjectWithTag("Player").transform; camera = Camera.main.transform; } // Update is called once per frame void Update () { //看向猪脚 //camera.LookAt (player); //与猪脚的正前方为正前方(仅仅取Y轴的旋转度) camera.eulerAngles =new Vector3(camera.eulerAngles.x, player.eulerAngles.y, camera.eulerAngles.z); //获取当前的镜头的Y轴旋转度 float angle = camera.eulerAngles.y; //计算x轴的距离差: float deltaX = camera_distance * Mathf.Sin(angle * Mathf.PI /180 ); float deltaZ = camera_distance * Mathf.Cos (angle * Mathf.PI / 180); //每一帧都改变摄像机的高度 camera.position = new Vector3 (player.position.x-deltaX, player.position.y+ camera_height, player.position.z-deltaZ); Debug.Log("angle:"+angle+",deltax:"+deltaX+",deltaZ:"+deltaZ); } }
版权声明:本文博客原创文章,博客,未经同意,不得转载。