一提到曲线,很多新手就头疼了,包括我。查了很多资料,终于有个大概的了解。想深入了解曲线原理的,推荐一个链接http://www.cnblogs.com/jay-dong/archive/2012/09/26/2704188.html

之前写了一篇博文《unity3D:游戏分解之角色移动和相机跟随》,里面用到了曲线插值,这里算是对上篇博文的一个补充

先看一下曲线的效果

在使用NGUI的过程中,发现iTween.cs里面有两个很有用的方法,一个是输入指定路点数组,一个就是曲线的插值算法。今天我们主要就用到这两个方法来实现曲线效果。

 public static Vector3[] PathControlPointGenerator(Vector3[] path)
{
Vector3[] suppliedPath;
Vector3[] vector3s; //create and store path points:
suppliedPath = path; //populate calculate path;
int offset = ;
vector3s = new Vector3[suppliedPath.Length + offset];
Array.Copy(suppliedPath, , vector3s, , suppliedPath.Length); //populate start and end control points:
//vector3s[0] = vector3s[1] - vector3s[2];
vector3s[] = vector3s[] + (vector3s[] - vector3s[]);
vector3s[vector3s.Length - ] = vector3s[vector3s.Length - ] + (vector3s[vector3s.Length - ] - vector3s[vector3s.Length - ]); //is this a closed, continuous loop? yes? well then so let's make a continuous Catmull-Rom spline!
if (vector3s[] == vector3s[vector3s.Length - ])
{
Vector3[] tmpLoopSpline = new Vector3[vector3s.Length];
Array.Copy(vector3s, tmpLoopSpline, vector3s.Length);
tmpLoopSpline[] = tmpLoopSpline[tmpLoopSpline.Length - ];
tmpLoopSpline[tmpLoopSpline.Length - ] = tmpLoopSpline[];
vector3s = new Vector3[tmpLoopSpline.Length];
Array.Copy(tmpLoopSpline, vector3s, tmpLoopSpline.Length);
} return (vector3s);
} //andeeee from the Unity forum's steller Catmull-Rom class ( http://forum.unity3d.com/viewtopic.php?p=218400#218400 ):
public static Vector3 Interp(Vector3[] pts, float t)
{
int numSections = pts.Length - ;
int currPt = Mathf.Min(Mathf.FloorToInt(t * (float)numSections), numSections - );
float u = t * (float)numSections - (float)currPt; if(currPt == )
{
int dsd = ;
} Vector3 a = pts[currPt];
Vector3 b = pts[currPt + ];
Vector3 c = pts[currPt + ];
Vector3 d = pts[currPt + ]; return .5f * (
(-a + 3f * b - 3f * c + d) * (u * u * u)
+ (2f * a - 5f * b + 4f * c - d) * (u * u)
+ (-a + c) * u
+ 2f * b
);
}

直接上完整代码,把这个脚本放到相机上,然后在场景中拖几个物件作为路点,就可以实现上面的效果

 using System;
using System.Collections.Generic;
using UnityEngine; namespace Fish.Study.Curve
{
/// <summary>
/// 曲线测试
/// </summary>
public class CurveTest : MonoBehaviour
{
//路点
public GameObject[] GameObjectList;
//各路点的坐标
public List<Vector3> TransDataList = new List<Vector3>(); void Start()
{
} //Gizmos
void OnDrawGizmos()
{
//1个点是不能画出曲线的,2个点实际上是直线
if (GameObjectList.Length <= ) return; TransDataList.Clear();
for (int i = ; i < GameObjectList.Length; ++i)
{
TransDataList.Add(GameObjectList[i].transform.position);
} if (TransDataList != null && TransDataList.Count > )
{
DrawPathHelper(TransDataList.ToArray(), Color.red);
}
} public Vector3[] GetCurveData()
{
if (TransDataList != null && TransDataList.Count > )
{
var v3 = (TransDataList.ToArray());
Vector3[] vector3s = PathControlPointGenerator(v3);
return vector3s;
} return null;
} //NGUI iTween.cs中的方法,输入路径点
public static Vector3[] PathControlPointGenerator(Vector3[] path)
{
Vector3[] suppliedPath;
Vector3[] vector3s; //create and store path points:
suppliedPath = path; //populate calculate path;
int offset = ;
vector3s = new Vector3[suppliedPath.Length + offset];
Array.Copy(suppliedPath, , vector3s, , suppliedPath.Length); //populate start and end control points:
vector3s[] = vector3s[] + (vector3s[] - vector3s[]);
vector3s[vector3s.Length - ] = vector3s[vector3s.Length - ] + (vector3s[vector3s.Length - ] - vector3s[vector3s.Length - ]); //is this a closed, continuous loop? yes? well then so let's make a continuous Catmull-Rom spline!
if (vector3s[] == vector3s[vector3s.Length - ])
{
Vector3[] tmpLoopSpline = new Vector3[vector3s.Length];
Array.Copy(vector3s, tmpLoopSpline, vector3s.Length);
tmpLoopSpline[] = tmpLoopSpline[tmpLoopSpline.Length - ];
tmpLoopSpline[tmpLoopSpline.Length - ] = tmpLoopSpline[];
vector3s = new Vector3[tmpLoopSpline.Length];
Array.Copy(tmpLoopSpline, vector3s, tmpLoopSpline.Length);
} return (vector3s);
} //曲线插值函数
public static Vector3 Interp(Vector3[] pts, float t)
{
int numSections = pts.Length - ;
int currPt = Mathf.Min(Mathf.FloorToInt(t * (float)numSections), numSections - );
float u = t * (float)numSections - (float)currPt; Vector3 a = pts[currPt];
Vector3 b = pts[currPt + ];
Vector3 c = pts[currPt + ];
Vector3 d = pts[currPt + ]; return .5f * (
(-a + 3f * b - 3f * c + d) * (u * u * u)
+ (2f * a - 5f * b + 4f * c - d) * (u * u)
+ (-a + c) * u
+ 2f * b
);
} //画曲线
private void DrawPathHelper(Vector3[] path, Color color)
{
Vector3[] vector3s = PathControlPointGenerator(path); //Line Draw:
Vector3 prevPt = Interp(vector3s, );
int SmoothAmount = path.Length * ;
for (int i = ; i <= SmoothAmount; i++)
{
float pm = (float)i / SmoothAmount;
Vector3 currPt = Interp(vector3s, pm); Gizmos.color = color;
Gizmos.DrawSphere(currPt, 0.2f);
prevPt = currPt;
}
}
}
}

unity3D:游戏分解之曲线的更多相关文章

  1. Unity3d游戏中自定义贝塞尔曲线编辑器[转]

    关于贝塞尔曲线曲线我们再前面的文章提到过<Unity 教程之-在Unity3d中使用贝塞尔曲线>,那么本篇文章我们来深入学习下,并自定义实现贝塞尔曲线编辑器,贝塞尔曲线是最基本的曲线,一般 ...

  2. Unity3D游戏开发初探—2.初步了解3D模型基础

    一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被. ...

  3. Unity3D游戏在iOS上因为trampolines闪退的原因与解决办法

    http://7dot9.com/?p=444 http://whydoidoit.com/2012/08/20/unity-serializer-mono-and-trampolines/ 确定具体 ...

  4. unity3d 游戏插件 溶解特效插件 - Dissolve Shader

    unity3d 游戏插件 溶解特效插件 - Dissolve Shader   链接: https://pan.baidu.com/s/1hr7w39U 密码: 3ed2

  5. 将Unity3D游戏移植到Android平台上

    将Unity3D游戏移植到Android平台是一件很容易的事情,只需要在File->Build Settings中选择Android平台,然后点击Switch Platform并Build出ap ...

  6. 从一点儿不会开始——Unity3D游戏开发学习(一)

    一些废话 我是一个windows phone.windows 8的忠实粉丝,也是一个开发者,开发数个windows phone应用和两个windows 8应用.对开发游戏一直抱有强烈兴趣和愿望,但奈何 ...

  7. unity3d游戏无法部署到windows phone8手机上的解决方法

    今天搞了个unity3d游戏,准备部署到自己的lumia 920上,数据线连接正常,操作正常,但是“build”以后,始终无法部署到手机上,也没有在选择的目录下生产任何相关文件.(你的系统必须是win ...

  8. Unity3D游戏UI开发经验谈

    原地址:http://news.9ria.com/2013/0629/27679.html 在Unity专场上,108km创始人梁伟国发表了<Unity3D游戏UI开发经验谈>主题演讲.他 ...

  9. Unity3D游戏开发之连续滚动背景

    Unity3D游戏开发之连续滚动背景 原文  http://blog.csdn.net/qinyuanpei/article/details/22983421 在诸如天天跑酷等2D游戏中,因为游戏须要 ...

随机推荐

  1. Linux - 进程间通信 - 匿名管道

    一.概念:进程间通信( IPC,InterProcess Communication) 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进城之间要交换数据必须通过内 ...

  2. Android sdk配置 常见问题及处理方法

    1. 下载sdk压缩包,解压后显示 2.双击SDK Manager.exe 程序进入如下界面 注:有的童鞋可能遇到如下问题 一般将一和二两种操作都完成就OK了 一. 更新sdk,遇到了更新下载失败问题 ...

  3. 设计模式的征途—3.抽象工厂(Abstract Factory)模式

    上一篇的工厂方法模式引入了工厂等级结构,解决了在原来简单工厂模式中工厂类职责太重的原则,但是由于工厂方法模式的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,从而增加系统开销.那么,我们应该 ...

  4. JQuery简单动画效果的发生顺序和animate方法

    (1)在同一组元素上的效果 当在一个.animate()方法中以多个属性的方式应用时,是同时发生的. 当以方法连缀的形式应用时,是按顺序发生的(排队效果)---除非queue选项值为false. (2 ...

  5. 源于《Unity官方实例教程 “Space Shooter”》思路分析及相应扩展

    教程来源于:Unity官方实例教程 Space Shooter(一)-(五)       http://www.jianshu.com/p/8cc3a2109d3b 一.经验总结 教程中步骤清晰,并且 ...

  6. 微信小程序(组件demo)以及预览方法:(小程序交流群:604788754)

    1. 获取微信小程序的 AppID 登录 https://mp.weixin.qq.com ,就可以在网站的"设置"-"开发者设置"中,查看到微信小程序的 Ap ...

  7. ES6相关新特性介绍

    你可能已经听说过 ECMAScript 6 (简称 ES6)了.ES6 是 Javascript 的下一个版本,它有很多很棒的新特性.这些特性复杂程度各不相同,但对于简单的脚本和复杂的应用都很有用.在 ...

  8. zoj1654 Place the Robots 二分图最大匹配

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=654 将每一行的包含空地的区域编号 再将每一列的包含空地的区域编号 然 ...

  9. ZooKeeper监听机制

    前言:Zookeeper的监听机制很多人都踩过坑,感觉实现了watcher 接口,后面节点的变化都会一一推送过来,然而并非如此. Watch机制官方声明:一个Watch事件是一个一次性的触发器,当被设 ...

  10. 如何优雅地运用 Chrome (Google)

    已经在很多工具类文章前言中,提及使用工具的重要性:以至于在写这篇时候,大为窘迫:穷尽了脑海中那些名句箴言,目测都已然在先前文章中被引用.鉴于杳让人心底意识到工具的重要性,并且能践行之,远比介绍如何使用 ...