unity3D:游戏分解之角色移动和相机跟随

游戏中,我们经常会有这样的操作,点击场景中某个位置,角色自动移动到那个位置,同时角色一直是朝向那个位置移动的,而且相机也会一直跟着角色移动。有些游戏,鼠标滑动屏幕,相机就会围绕角色旋转。

看似很简单的操作,那么到底是怎么实现的呢?

我们把上述操作分解为以下几个步骤

角色的移动

1. 移动到下一个路点,线性插值、曲线插值

2. 角色朝向,一直面朝下一个路点

相机跟随角色

1. 相机俯视角度,决定相机的高度

2. 相机跟随距离,前向距离或者直线距离(就是三角形的水平边长或者斜边长)

3. 相机一直看角色的后背(Y轴旋转角度和角色一致)

4. 相机围绕角色旋转

技术点:

1. 向量

2. 旋转

先来看效果,请原谅我未注册屏幕录像orz

角色移动

  包括位移和方向,就是移动角色的同时角色一直要朝向移动的方向。

 

左边的图,角色从A移动到B,朝向却一直是向前方的,明显不符合跑动的显示逻辑。正确的表现是右图所展示那样,角色面朝移动方向。

那么我们要怎么做才能实现这个效果呢?位移很简单,A到B的坐标插值。

其次是旋转角色,Unity提供了一个方法Quaternion.LookRotation。关于这个方法,官方的解释如下:

Quaternion.LookRotation 注视旋转

static function LookRotation (forward : Vector3, upwards : Vector3 = Vector3.up) : Quaternion

Description描述

Creates a rotation that looks along forward with the the head upwards along upwards

创建一个旋转,沿着forward(z轴)并且头部沿着upwards(y轴)的约束注视。也就是建立一个旋转,使z轴朝向view  y轴朝向up。

Logs an error if the forward direction is zero.

如果forward方向是0,记录一个错误。

光看描述,是不是比较难理解。网上对这个方法的解释也挺多的,但是各说纷纭,没个简单明了的说法,更容易误导人。

我们知道向量,包含大小和方向。大小很容易得到,那么方向怎么获得呢?常规来说,可以通过把向量分解为x、y、z三个分量,然后通过三角函数依次求得个分量的夹角。

Unity提供了更简单的方法,就是Quaternion.LookRotation,这个方法就是获得传入向量的方向,即旋转值,是个四元数。

代码实际上很简单,就几行。主要是要理解为什么

1             //计算当前位置到下一个坐标点的向量
2             var vector = (posB - posA).normalized;
3             //取得向量的方向
4             var rotation = Quaternion.LookRotation(vector).eulerAngles;
5             //将物体旋转到指向下一个坐标点的方向
6             transform.rotation = Quaternion.Euler(0, rotation.y, 0);
7             //设置物体的坐标
8             transform.position = posB;

想想为什么Quaternion.Euler(0, rotation.y, 0)这里x和z方向都是填的0?

因为角色的朝向是根据偏转角Yaw,也就是Y轴决定的,x和z轴是没有发生偏转的,倘若改变x轴z轴旋转值,就会发现角色会有俯仰、翻滚的效果。

相机跟随角色

好了,角色的朝向解决了。那么,如果我要让相机一直跟着角色走,同时相机一直看到角色的后背,也就是角色旋转时,相机要跟着转动,同时保持固定距离,该如何实现?

我们先计算相机的位置,然后在旋转相机朝向角色的后背。

1. 计算相机的旋转值,这里需要指定相机的俯仰角Pitch的值,假定是30度,可以根据具体情况调节

//相机的俯仰角和偏航角,Y方向偏航和目标对象一致
Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y, 0);

2. 计算指定长度Distance的向量,这个向量是与世界坐标z方向平行

var vector = Vector3.forward * Distance;

3. 用上面的相机旋转值左乘第二步得到的向量,改变这个向量的方向( 四元数左乘向量,改变向量的方向)

vector  = ro * vector;

4. 用目标位置减去vector,得到指向目标位置的坐标点,也就是相机的最终位置。(为什么这样就得到位置了,回去看看向量的知识吧)

var pos = transform.position - vector; 

5. 最后,将旋转值和坐标赋值给相机,相机就完成了跟随效果, 是不是很简单

CameraGo.transform.position = pos;
CameraGo.transform.rotation = ro;
1 //相机的俯仰角和偏航角,Y方向偏航和目标对象一致
2 Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y, 0);
3 //给向量赋予旋转
4 var distanceVector = ro * Vector3.forward * Distance;
5 var pos = transform.position - distanceVector;
6 CameraGo.transform.position = pos;
7 CameraGo.transform.rotation = ro;

至于相机围绕角色旋转,我们只需要改变一下Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y, 0) 中transform.rotation.eulerAngles.y这个值

本来这个值是指定相机朝向角色的方向,我们改变这个值,就可以实现相机围绕角色的效果。我们可以这样做

//delta就是围绕角色旋转的旋转角度0~360.
Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y + delta, 0)

最终,上诉代码如下,代码不完整,请各位自行补全:

 1      //角色移动
 2         void SmoothMove()
 3         {
 4             Vector3[] vector3s = _transDataList;// CurvePath.PathControlPointGenerator(_transDataList);
 5             int sample = _transDataList.Length * SampleRate;
 6
 7             _movePtg += Time.deltaTime * MoveSpeed;
 8
 9             //曲线插值
10             transform.position = CurvePath.Interp(vector3s, _movePtg / sample);
11
12             //计算当前位置到下一个坐标点的向量
13             var vector = (transform.position - _prevPos).normalized;
14             //取得向量的方向
15             var rotation = Quaternion.LookRotation(vector, Vector3.right).eulerAngles;
16             //去处x和z方向的影响,仅作用y方向偏转
17             rotation.x = 0;
18             rotation.z = 0;
19
20             //将物体旋转到指向下一个坐标点的方向
21             transform.rotation = Quaternion.Euler(rotation);
22
23
24             _prevPos = transform.position;
25             if (_movePtg >= sample)
26             {
27                 ResetLocalData();
28             }
29         }
30
31         //相机跟随
32         void FollowCamera()
33         {
34             if (CameraGo == null) return;
35
36             if(UseFollow != 0)
37             {
38                 //相机的俯仰角和偏航角,Y方向偏航和目标对象一致
39                 Quaternion ro = Quaternion.Euler(Pitch, transform.rotation.eulerAngles.y + Slider, 0);
40
41                 //给向量赋予旋转
42                 var distanceVector = ro * Vector3.forward * Distance;
43                 var pos = transform.position - distanceVector;
44                 CameraGo.transform.position = pos;
45                 CameraGo.transform.rotation = ro;
46                 return;
47             }
48         }
时间: 2024-11-06 03:43:52

unity3D:游戏分解之角色移动和相机跟随的相关文章

unity3D:游戏分解之曲线

一提到曲线,很多新手就头疼了,包括我.查了很多资料,终于有个大概的了解.想深入了解曲线原理的,推荐一个链接http://www.cnblogs.com/jay-dong/archive/2012/09/26/2704188.html 之前写了一篇博文<unity3D:游戏分解之角色移动和相机跟随>,里面用到了曲线插值,这里算是对上篇博文的一个补充 先看一下曲线的效果 在使用NGUI的过程中,发现iTween.cs里面有两个很有用的方法,一个是输入指定路点数组,一个就是曲线的插值算法.今天我们主

Unity3D游戏开发之如何截屏的技能培训

下面我们开始今天的Unity3D技能培训. 我们学习Unity3D培训目标:让U3D初学者可以更快速的掌握U3D技术,自行制作修改素材,可以独立完成2D.3D小规模游戏及网页游戏开发. 今天我们来做点简单的东西,做个什么呢?答案就是截屏.作为一名热爱单机游戏的玩家,每次在玩游戏的同时截取游戏中比较喜欢的画面,特别是学习了Unity3D以后玩游戏的时候更多地是从一个游戏设计者的角度来看待游戏,换句话说,可能关注技术的成分更多一点吧.比如在写<Unity3D游戏开发之自由视角下的角色控制>和<

Unity3D游戏开发之自由视角状态下的角色控制(二)

在测试Unity3D游戏开发之自由视角状态下的角色控制这个项目的时候意外地发现了一个Bug.Bug出现在如下位置: [csharp] view plaincopyprint? //设置玩家跟随角度 if(Target.GetComponent<NoLockiVew_Player>().State==NoLockiVew_Player.PlayerState.Walk) { Target.rotation=Quaternion.Euler(new Vector3(0,mX,0)); } 该方法主

Unity3D游戏开发之自由视角状态下的角色控制

在上一篇文章Unity3D游戏开发之基于Trigger的触发式动画设计一文中,博主与大家分享自己在这方面方面的一些感悟.今天呢,我们来探讨Unity3D角色控制的内容,如图是博主非常喜欢的<古剑奇谭>游戏截图,在这款游戏中就使用了博主今天要讲解的自由视角,所谓自由视角是指玩家可以按照自身坐标系向着四个不同的方向移动,当玩家按下鼠标右键时,可以绕Y轴按照一定的角度旋转摄像机,在旋转的过程中,角色将旋转相应的角度.在移动的过程中,摄像机会保持与玩家间的一定距离,然后跟随角色进行移动.好了,下面我们

Unity3D 游戏开发构架篇 ——角色类的设计与持久化

在游戏开发中,游戏角色占了很大的篇幅,可以说游戏中所有的内容都是由主角所带动.这里就介绍一下角色类的设计和持久化. 一.角色类应用场景和设计思想 游戏中的角色类型不一而足,有不同的技能,有不同的属性等等.有些一个玩家只有一个角色,有些一个玩家可以有多个角色.这里就目前项目来描述一下角色类的构造,思路都是类似的. 早期我写角色类都是直接一个Class,然后想到什么属性就往里面添加,如果游戏过程中需要对属性的修改,逻辑判断也写在这个类中,这样必然导致类的庞大和臃肿,最后你自己也忘记了自己写在什么地方

Unity3D游戏开发从零单排(五) - 导入CS模型到Unity3D

游戏动画基础 Animation组件 Animation组件是对于老的动画系统来说的. 老的动画形同对应的动画就是clip,每个运动都是一段单独的动画,使用Play()或CrossFade(),直接播放动画 或淡入淡出播放动画. animation.Play("name"); animation.CrossFade("name"); 下面的是它的几个属性 Animation:默认的动画片段: Aniamtions:包含的动画片段: Play Automaticall

Unity3D游戏开发之虚拟现实项目开发流程

Unity3D游戏开发之虚拟现实项目开发流程 欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,[狗刨学习网]unity极致学院,致力于打造业内unity3d培训.学习第一品牌. 一.系统设计与资料的收集与整理 1.              与项目投资单位沟通并进行系统设计: 2.              收集整理规划图.效果图.现场照片: 3.              拍摄比干文化及景区介

[Unity3D]Unity3D游戏开发之跑酷游戏项目解说

大家好,我是秦元培.我參加了CSDN2014博客之星的评选,欢迎大家为我投票,同一时候希望在新的一年里大家能继续支持我的博客. 大家晚上好.我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei.终于到了更新博客的时间.从昨天下午開始,博主開始设计一个跑酷的游戏,到晚上睡觉前这个游戏已经基本完毕. 博主今天早上七点钟就起来了,到早上十点钟终于把整个游戏写完了. 所以,今天的博客的主题就是<Unity3D游戏开发之跑酷游戏项目解说>. 从博主自身来考虑这

Unity3D游戏开发之伤害数值显示

众所周知,在RPG游戏策划中最为重要的一个环节是数值策划.数值策划是一个关于游戏平衡方面的概念,它是一种非常深奥的概念.游戏从某种意义上 是多种选择的组合,因此如果一个游戏失去平衡,那么就会减少选择而影响游戏的乐趣.数值策划人员通常需要按照一定的规则和方法将整个游戏系统的相关数值调整到一个合适的范围,以确保玩家可以有更多地选择以增强游戏的可玩性.数值策划是近年来国内游戏行业从国外游戏业引申过来的一个概念,我们在学习游戏设计的过程中,除了专注于技术上的实现以外,还应该对游戏设计中的相关理论有所了解