zoukankan      html  css  js  c++  java
  • unity3D:游戏分解之曲线

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

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

    先看一下曲线的效果

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

     1 public static Vector3[] PathControlPointGenerator(Vector3[] path)
     2     {
     3         Vector3[] suppliedPath;
     4         Vector3[] vector3s;
     5 
     6         //create and store path points:
     7         suppliedPath = path;
     8 
     9         //populate calculate path;
    10         int offset = 2;
    11         vector3s = new Vector3[suppliedPath.Length + offset];
    12         Array.Copy(suppliedPath, 0, vector3s, 1, suppliedPath.Length);
    13 
    14         //populate start and end control points:
    15         //vector3s[0] = vector3s[1] - vector3s[2];
    16         vector3s[0] = vector3s[1] + (vector3s[1] - vector3s[2]);
    17         vector3s[vector3s.Length - 1] = vector3s[vector3s.Length - 2] + (vector3s[vector3s.Length - 2] - vector3s[vector3s.Length - 3]);
    18 
    19         //is this a closed, continuous loop? yes? well then so let's make a continuous Catmull-Rom spline!
    20         if (vector3s[1] == vector3s[vector3s.Length - 2])
    21         {
    22             Vector3[] tmpLoopSpline = new Vector3[vector3s.Length];
    23             Array.Copy(vector3s, tmpLoopSpline, vector3s.Length);
    24             tmpLoopSpline[0] = tmpLoopSpline[tmpLoopSpline.Length - 3];
    25             tmpLoopSpline[tmpLoopSpline.Length - 1] = tmpLoopSpline[2];
    26             vector3s = new Vector3[tmpLoopSpline.Length];
    27             Array.Copy(tmpLoopSpline, vector3s, tmpLoopSpline.Length);
    28         }
    29 
    30         return (vector3s);
    31     }
    32 
    33     //andeeee from the Unity forum's steller Catmull-Rom class ( http://forum.unity3d.com/viewtopic.php?p=218400#218400 ):
    34     public static Vector3 Interp(Vector3[] pts, float t)
    35     {
    36         int numSections = pts.Length - 3;
    37         int currPt = Mathf.Min(Mathf.FloorToInt(t * (float)numSections), numSections - 1);
    38         float u = t * (float)numSections - (float)currPt;
    39 
    40         if(currPt == 0)
    41         {
    42             int dsd = 0;
    43         }
    44 
    45         Vector3 a = pts[currPt];
    46         Vector3 b = pts[currPt + 1];
    47         Vector3 c = pts[currPt + 2];
    48         Vector3 d = pts[currPt + 3];
    49 
    50         return .5f * (
    51             (-a + 3f * b - 3f * c + d) * (u * u * u)
    52             + (2f * a - 5f * b + 4f * c - d) * (u * u)
    53             + (-a + c) * u
    54             + 2f * b
    55         );
    56     }

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

      1 using System;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 
      5 namespace Fish.Study.Curve
      6 {
      7     /// <summary>
      8     /// 曲线测试
      9     /// </summary>
     10     public class CurveTest : MonoBehaviour
     11     {
     12         //路点
     13         public GameObject[] GameObjectList;
     14         //各路点的坐标
     15         public List<Vector3> TransDataList = new List<Vector3>();
     16 
     17         void Start()
     18         {
     19         }
     20 
     21         //Gizmos
     22         void OnDrawGizmos()
     23         {
     24             //1个点是不能画出曲线的,2个点实际上是直线
     25             if (GameObjectList.Length <= 1) return;
     26 
     27             TransDataList.Clear();
     28             for (int i = 0; i < GameObjectList.Length; ++i)
     29             {
     30                 TransDataList.Add(GameObjectList[i].transform.position);
     31             }
     32 
     33             if (TransDataList != null && TransDataList.Count > 1)
     34             {
     35                 DrawPathHelper(TransDataList.ToArray(), Color.red);
     36             }
     37         }
     38 
     39         public Vector3[] GetCurveData()
     40         {
     41             if (TransDataList != null && TransDataList.Count > 1)
     42             {
     43                 var v3 = (TransDataList.ToArray());
     44                 Vector3[] vector3s = PathControlPointGenerator(v3);
     45                 return vector3s;
     46             }
     47 
     48             return null;
     49         }
     50 
     51         //NGUI iTween.cs中的方法,输入路径点
     52         public static Vector3[] PathControlPointGenerator(Vector3[] path)
     53         {
     54             Vector3[] suppliedPath;
     55             Vector3[] vector3s;
     56 
     57             //create and store path points:
     58             suppliedPath = path;
     59 
     60             //populate calculate path;
     61             int offset = 2;
     62             vector3s = new Vector3[suppliedPath.Length + offset];
     63             Array.Copy(suppliedPath, 0, vector3s, 1, suppliedPath.Length);
     64 
     65             //populate start and end control points:
     66             vector3s[0] = vector3s[1] + (vector3s[1] - vector3s[2]);
     67             vector3s[vector3s.Length - 1] = vector3s[vector3s.Length - 2] + (vector3s[vector3s.Length - 2] - vector3s[vector3s.Length - 3]);
     68 
     69             //is this a closed, continuous loop? yes? well then so let's make a continuous Catmull-Rom spline!
     70             if (vector3s[1] == vector3s[vector3s.Length - 2])
     71             {
     72                 Vector3[] tmpLoopSpline = new Vector3[vector3s.Length];
     73                 Array.Copy(vector3s, tmpLoopSpline, vector3s.Length);
     74                 tmpLoopSpline[0] = tmpLoopSpline[tmpLoopSpline.Length - 3];
     75                 tmpLoopSpline[tmpLoopSpline.Length - 1] = tmpLoopSpline[2];
     76                 vector3s = new Vector3[tmpLoopSpline.Length];
     77                 Array.Copy(tmpLoopSpline, vector3s, tmpLoopSpline.Length);
     78             }
     79 
     80             return (vector3s);
     81         }
     82 
     83         //曲线插值函数
     84         public static Vector3 Interp(Vector3[] pts, float t)
     85         {
     86             int numSections = pts.Length - 3;
     87             int currPt = Mathf.Min(Mathf.FloorToInt(t * (float)numSections), numSections - 1);
     88             float u = t * (float)numSections - (float)currPt;
     89 
     90             Vector3 a = pts[currPt];
     91             Vector3 b = pts[currPt + 1];
     92             Vector3 c = pts[currPt + 2];
     93             Vector3 d = pts[currPt + 3];
     94 
     95             return .5f * (
     96                 (-a + 3f * b - 3f * c + d) * (u * u * u)
     97                 + (2f * a - 5f * b + 4f * c - d) * (u * u)
     98                 + (-a + c) * u
     99                 + 2f * b
    100             );
    101         }
    102 
    103         //画曲线
    104         private void DrawPathHelper(Vector3[] path, Color color)
    105         {
    106             Vector3[] vector3s = PathControlPointGenerator(path);
    107 
    108             //Line Draw:
    109             Vector3 prevPt = Interp(vector3s, 0);
    110             int SmoothAmount = path.Length * 20;
    111             for (int i = 1; i <= SmoothAmount; i++)
    112             {
    113                 float pm = (float)i / SmoothAmount;
    114                 Vector3 currPt = Interp(vector3s, pm);
    115 
    116                 Gizmos.color = color;
    117                 Gizmos.DrawSphere(currPt, 0.2f);
    118                 prevPt = currPt;
    119             }
    120         }
    121     }
    122 }
  • 相关阅读:
    iOS 字体
    接口继承和实现继承的区别
    实验楼实验——LINUX基础入门
    试看看能不能发布
    mysql binlog恢复
    percona
    ssh2 php扩展
    sphinx
    ngios
    socketlog
  • 原文地址:https://www.cnblogs.com/fishyu/p/6817509.html
Copyright © 2011-2022 走看看