最近真是忙,连研究细看的时间都没有了,原帖地址:https://alastaira.wordpress.com/2013/11/08/smooth-unity-camera-transitions-with-animation-curves/

先贴到这里

I’m creating a game in which I want to transition between two camera views – a top-down, overhead camera that gives a zoomed-out world view, and an over-the-shoulder style forward-facing camera to give a close-up view. Let’s say for the sake of discussion that these positions are defined relative to the player, as follows:

  • Overview: Position x/y/z: (0, 100, 0). Rotation x/y/z: (-90, 0, 0)  (60 units above, rotated straight down)
  • Close-up: Position x/y/z: (0, 0, –0.5). Rotation x/y/z: (0, 0, 0) (0.5 units behind, aligned with player direction)

Rather than simply cut between the two camera views, or present the top-down view in a second minimap camera alongside the main game view,  I want to use a single camera and transition smoothly between the two view locations. Initially, I tried to simply interpolate the position and rotation of the camera between the two locations (using lerp() for linear interpolation of the position vectors and slerp() for the rotation quaternions), based on a single zoom parameter:

transform.position = Vector3.Lerp(zoomstart.position, zoomend.position, zoom);
transform.rotation = Quaternion.Slerp(zoomstart.rotation, zoomend.rotation, zoom);

This gives:

However, this didn’t create the effect I wanted – I wanted to remain largely looking down as the camera zoomed in, and only pull up to match that player’s look vector at relatively close zoom levels, and also to ease the movement at both ends of the zoom.

My next thought was to ease in/out the camera motion using one of the functions described in this earlier post – perhaps a sigmoid curve, so that the rate of rotation was greatest at either extreme of the zoom spectrum. But I had trouble finding a function that exactly described the motion I wanted to create.

And then I discovered Unity’s AnimationCurves. I don’t know why they’re called animation curves, because they’re not specific to animations at all – they allow you to define custom curves based on an arbitrary number of control points (keys), and then evaluate the value of the function at any point along the curve.

To look up the value at any point along the curve use the Evaluate()  method. For example, in the curve above, the y value of the curve at x=0.5 is given by Curve.Evaluate(0.5) , which results in 0.692. Using this you can smoothly adjust any variable based on a single dimensional input.

Curves for Smooth Camera Movement

I have three camera transform parameters that change between my two camera locations – the offset position in y and z axes, and the rotation in the x axis. Since each animation curve can express only one dimension, I thought I might need to create three animation curves – one to describe each parameter that varies as the camera zooms in. However, on more thought I decided a better way: to have one curve to control the rotation around the x axis (i.e. adjusting the pitch of the camera), and then a second curve to set the distance which the camera should be offset back based on the forward direction of the camera at that point. Since the camera rotates about the x axis, translating back along its normal means that the second curve will govern both the height (y) and offset (z) in a single curve.

You can create animation curves in the inspector, but I initialised them in code as follos:

public class CameraScript : MonoBehaviour {
 
    // How camera pitch (i.e. rotation about x axis) should vary with zoom
    public AnimationCurve pitchCurve;
    // How far the camera should be placed back along the chosen pitch based on zoom
    public AnimationCurve distanceCurve;
 
    // Use this for initialization
    void Start () {
 
        // Create 'S' shaped curve to adjust pitch
        // Varies from 0 (looking forward) at 0, to 90 (looking straight down) at 1
        pitchCurve = AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 90.0f);
        
        // Create exponential shaped curve to adjust distance
        // So zoom control will be more accurate at closer distances, and more coarse further away
        Keyframe[] ks = new Keyframe[2];
        // At zoom=0, offset by 0.5 units
        ks[0] = new Keyframe(0, 0.5f);
        ks[0].outTangent = 0;
        // At zoom=1, offset by 60 units
        ks[1] = new Keyframe(1, 60);
        ks[1].inTangent = 90;
        distanceCurve = new AnimationCurve(ks);
    }
}

This generates the following curves:

Pitch

Distance

I then evaluate the appropriate point from each curve based on the camera zoom level, as follows:

// Calculate the appropriate pitch (x rotation) for the camera based on current zoom      
float targetRotX = pitchCurve.Evaluate(zoom);
 
// The desired yaw (y rotation) is to match that of the target object
float targetRotY = target.rotation.eulerAngles.y;
 
// Create target rotation as quaternion
// Set z to 0 as we don't want to roll the camera
Quaternion targetRot = Quaternion.Euler(targetRotX, targetRotY, 0.0f);
        
// Calculate in world-aligned axis, how far back we want the camera to be based on current zoom
Vector3 offset = Vector3.forward * distanceCurve.Evaluate(zoom);
 
// Then subtract this offset based on the current camera rotation
Vector3 targetPos = target.position - targetRot * offset;

Finally, rather than setting the camera position/rotation directly, I lerp/slerp between the current transform.position/rotation towards the target position/rotation to smooth the movement and get the result as follows, which I’m pretty happy with (scene view on the left, resulting camera view on the right):

转一篇Unity的相机动画控制的更多相关文章

  1. 关于Unity中Mecanim动画的动画状态代码控制与代码生成动画控制器

    对于多量的.复杂的.有规律的控制器使用代码生成 动画状态代码控制 1:每个动画状态,比如进入状态,离开状态, 等都有可能需要代码来参与和处理,比如,进入这个动画单元后做哪些事情,来开这个动画单元后做哪 ...

  2. unity 对Animator动画系统的研究

    unity的新动画系统叫Mecanim,使用Animator来取代旧系统Animation,按Unity文档的惯例:知识点主要分2部分:unity manual和unity script,读者可以边看 ...

  3. Unity MegaFiers 顶点动画

        使用 MegaFiers 插件,能够使得Unity支持顶点动画的播放. 官方视频教程例如以下: 在这里简单測试使用下,环境例如以下: Blender 2.72 Unity 4.5.4 Mega ...

  4. Unity正交相机智能包围物体(组)方案

    Unity正交相机智能包围物体(组)方案 目录 Unity正交相机智能包围物体(组)方案 一.技术背景 二.相关概念 2.1 正交摄像机 2.2 正交相机的Size 2.3 相机的Aspect 2.4 ...

  5. 深入学习jQuery动画控制

    × 目录 [1]动画状态 [2]停止动画 [3]动画延迟[4]全局控制 前面的话 jQuery动画可以使用fade.hide.slide等方法实现基本动画效果,可以使用animate实现自定义动画,甚 ...

  6. iOS开发Swift篇—(六)流程控制

    iOS开发Swift篇—(六)流程控制 一.swift中的流程控制 Swift支持的流程结构如下: 循环结构:for.for-in.while.do-while 选择结构:if.switch 注意:这 ...

  7. i3D的一篇Unity教程中的笔记

    原地址:http://blog.sina.com.cn/s/blog_72b936d80100wwej.html 以下是i3D的一篇Unity教程中的笔记. i3D的这篇教程是[i3D.Next-Ge ...

  8. Unity Shader序列帧动画学习笔记

    Unity Shader序列帧动画学习笔记 关于无限播放序列帧动画的一点问题 在学shader的序列帧动画时,书上写了这样一段代码: fixed4 frag(v2f i){ // 获得整数时间 flo ...

  9. unity代码添加动画,并传参数

    测试界面 button一个 sprite一个 测试代码 public class BgObject : MonoBehaviour { void Start() { List<string> ...

随机推荐

  1. 常用的js跳转页面方法实现汇总

    1.window.location.href方式 <script language="javascript" type="text/javascript" ...

  2. Ubuntu Kylin15下PHP环境的搭建(LAMP)

    Ubuntu下的PHP开发环境架设   今天重新装了ubuntu那么就吧过程记录下. 打开终端,也就是命令提示符. 我们先来最小化组建安装,按照自己的需求一步一步装其他扩展.命令提示符输入如下命令: ...

  3. C中的数组与指针问题

    反复在数组名与指针上犯错误,特记录下. ,,,,}; int *p, *q; p = (); q = (); *(p+1)?   *(q-1) ? 答案是 3, 5.这里主要涉及的问题就是指针参与运算 ...

  4. chrome内核浏览器input边框

    直接给input加outline:none和设置input {outline:none}都没效 最后逼得没法,*:focus { outline: none; },然后整个世界就安静了,嚯嚯

  5. ARM学习篇一 点亮LED

    要点亮LED,先决条件是什么,当然得有相应的硬件设施.板子的整个电路图比较大,我就直接取相关部分. 给发光二级管加上3.3v电压后,通过1k电阻,直接与S3C2440连接.至于为什么要加电阻,大家应该 ...

  6. .Net程序员之Python基础教程学习----列表和元组 [First Day]

    一. 通用序列操作: 其实对于列表,元组 都属于序列化数据,可以通过下表来访问的.下面就来看看序列的基本操作吧. 1.1 索引: 序列中的所有元素的下标是从0开始递增的. 如果索引的长度的是N,那么所 ...

  7. MMORPG大型游戏设计与开发(客户端架构 part2 of vgui)

    这一节我将讲解vgui的基础系统部分,也是该库提供给外部使用的一些重要接口.作为UI部分比较重要的部分,该节有着至关重要的部分,如果没有看到上一节内容,请留意下面的连接.我们现在可以猜想一下在客户端U ...

  8. MMORPG大型游戏设计与开发(客户端架构 part5 of vegine)

    客户端异常捕获,是一件必然的事情,特别是在开发的时候就更需要这些有利于找出问题原因的捷径.区别于服务器的是,客户端基本上是以界面为主,你很难在正常运行程序的情况下进行一些输出的监视,如一些日志的记录. ...

  9. [AIR] as3 之条件编译多平台妙用

    http://bbs.9ria.com/thread-418864-1-1.html 一直希望as3 可以支持条件编译,即满足A时编译函数1,满足B时则编译函数2. 最佳百度了之后,发现原来是可以实现 ...

  10. StringBuffer和StringBuilder的区别

    StringBuffer和StringBuilder的区别 StringBuffer与StringBuilder就不一样了,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在 ...