2014年8月19日火曜日

iTweenパス上をユーザー操作で移動するサンプル

UnityにてObjectをiTweenを使用してユーザー操作でパス上をいったりきたり移動するサンプル。





概要

  • 使用言語: C#。

  • パスの作成: iTween Visual Editor。

  • 作成したパス上でCube ObjectをiTweenで移動させる。

  • 移動指示はユーザー操作で行う

  • 操作:
    PCならキーボードのA、D。
    Androidなら左右の傾き(加速度センサ)。
    Unity上の再生、実機又は、UnityRemote4で動作確認。

準備:

  1. Unityで新規プロジェクト作成。

  2. iTween Visual Editor パッケージをAsset Storeからインポート。
    1. CTRL+9でAsset Storeを開く。
    2. iTween Visual Editor」 で検索&インポート。
      ※iTween本体も同梱。別途入れる必要なし。入れるとエラーがでる。
  3. 一応ライトを追加しておく。
    Hierarchyウィンドウ内のCreateボタンから、
    Create > Direction Light
     


動かすObjectの追加

ここでは簡単にする為、Cubeを使う。

Hierarchyウィンドウ内のCreateボタンから、

Create > Cube

にて、追加。


iTween Visual Editorでパス作成


■iTween Visual Editor スクリプトを追加


動かす Cube オブジェクトに iTween Visual Editor スクリプトを追加する。
  1. Hierarchy上でCubeを選択状態にする。

  2. 上部メニューバーから、
    Component > Scripts > ITween Path

  3. Inspector上で ITween Path (Script) が追加される。
これで、パス作成の操作ができるようになる。


■パス名、ノード数を指定

  1. Cubeを選択状態にする
  2. Inspector で ITween Path (Script) が表示されていることを確認。
    以後この欄内の設定を行う。

    • Path Name:
      パスの名前。ここでは、

      MyPath

      としておく。
      ※1つのオブジェクトに複数のパスを持つこともできる。その際はパス名で区別する。
    • Path Color:
      パスの表示色。とりあえずデフォルトのまま。
      ※複数パスを作成した際に色で区別しやすくできる。
    • Node Count:
      パスの基点の数。ここでは5箇所とする為、

      5

      としておく。
      これで基点、中間点3つ、終点の計5箇所を設定できるようになる。
    • Node 1 ~ 5
      Node Countで 5 を指定したので、ここは Node 1 ~ 5 の5行になる。

■パスを作る

この段階で、シーン上に5つのXYZ矢印を示すパスカーソルが重なって配置されている。
これらはInspector上の Node1~5に対応している。

シーン上でこれらを操作して好みの移動パスを作成する。

CubeやDirection Lightが重なっていると選択しにくいので、これらを少しずらすと選択しやすい。


各パスを動かすと Inspector上の対応する Node n の欄XYZも変動する。
逆に Inspector上のNode nのXYZ値を変更するとパスカーソルもその位置に動く。

パスを増やしたい場合は Node Count を増やすことでNode n が増える。

※大量のNodeを配置する場合はとりあえず Node Countを少なめにして序盤のパスを配置後、Node Countを増やすという方法でもできる。


下図はパスを設定した画面

制御スクリプトの追加

  1. 新規スクリプトの追加
    Projectウィンドウ内にて、

    Create > C# Script

    にて、C#スクリプトを追加。

  2. スクリプト名を変更。
    ここでは cs_PathControl とした。

  3. スクリプト cs_PathControl をダブルクリックして開く。

  4. 後述のC#ソースをコピー&ペーストする。

  5. スクリプト追加
    Cubeオブジェクトを選択状態として上部メニューより、
    Component > Scripts > cs_Path Control

----- cs_PathControl
/*
 * @file cs_PathControl
 * @attention なし 
 * @note  なし 
 */

using UnityEngine;
using System.Collections;

public class cs_PathControl : MonoBehaviour {
 Vector3[] NodeData;
 iTweenPath cp_ITweenPath; //!< Instance pointer for 'ITween Path' Script
 float PositionPercent = 0; //!< 0.00~1.00. パス全体の移動距離に対し%で指定する値 
 
 /*!
  * Visual Path Editorで作成済みのパスデータを取得
  *  @param[in] pathname 取得するパス名
  *  @return     取得結果  true:成功  false:失敗
  *  @note     Visual Path Editorで作成済みのパスデータ Node 1~n を NodeData[]へ格納する 
  *  @attention    呼び出しタイミングはStart()以降とすること。 
  *        iTweenPath.GetPath()内部のパス名リスト更新が OnEnable()のタイミングで行われている。 
  *        よってAwakeではまだ確定していない場合がありえる為、Start()以降のタイミングで呼び出すこと。 
  */
 bool SetPathPosition_from_ITweenPath(string pathname){
  if(cp_ITweenPath==null){
   cp_ITweenPath = GetComponent<iTweenPath>(); // このObject内の ITween path スクリプトコンポーネントのインスタンスを取得 
   if(cp_ITweenPath==null){
    Debug.Log("[NO SCRIPT] No there script 'ITween Path' on this object");
    return(false);
   }
  }
  // GetPath()はStatic宣言されているので直呼び出し  
  NodeData = iTweenPath.GetPath(pathname); // Visual Path Editor のパス名を指定してパスデータを取得する。 
  if(NodeData==null){
   Debug.Log ("[NOT FOUND/null] path name '"+pathname+"'");
   return(false);
  }
  return(true);
 }
 const float addSpeed = 0.005f;
 void Drive_Increase(){
  //Debug.Log ("Drive_Increase");
  PositionPercent += addSpeed;
  if(PositionPercent>1.0f) PositionPercent = 1.0f;
 }
 void Drive_Decrease(){
  //Debug.Log ("Drive_Decrease");
  PositionPercent -= addSpeed;
  if(PositionPercent<0.0f) PositionPercent = 0.0f;
 }
 
 void Watch_UI_Input(){
  bool drive_Fwd = false;
  bool drive_Bwd = false;
  
  //Begin: Control by Keyboard
  bool input_Key_A = Input.GetKey(KeyCode.A);
  bool input_Key_D = Input.GetKey(KeyCode.D);
  if( !(input_Key_A & input_Key_D) ){ // Disable multi press
   drive_Fwd |= input_Key_A;
   drive_Bwd |= input_Key_D;
  }
  //End: Control by Keyboard
  #if UNITY_ANDROID
  //#if UNITY_IPHONE
  //Begin: Control by Accel Sensor
  float accel_X = Input.acceleration.x; // 加速度センサ 横傾き 
  //Debug.Log ("accel_X:"+accel_X);
  if(accel_X <-0.2f){
   drive_Fwd |= true;
  }
  else if(accel_X >0.2f){
   drive_Bwd |= true;
  }
  //End: Control by Accel Sensor
  #endif
  
  if (drive_Fwd) Drive_Increase();
  if (drive_Bwd) Drive_Decrease();
  if(drive_Fwd|drive_Bwd) Debug.Log("Position is "+PositionPercent*100.0f+"%"); //移動したなら表示 
 }
 
 void Start () {
  SetPathPosition_from_ITweenPath("MyPath");
 }
 
 void Update () {
  Watch_UI_Input();
  transform.position = iTween.PointOnPath(NodeData, PositionPercent); // Get target position 
 }
}
-----


Unity5用プロジェクトサンプル: https://github.com/maruton/Sample_iTween_PointOnPath




その他メモ


移動速度

このサンプルでは移動速度は一定にしている。

const float addSpeed = 0.005f;

の数値を動的に可変してやれば、加減速の調節できる。

パスの座標指定について

このサンプルの動作の肝は、iTween のPointOnPath()で、

transform.position = iTween.PointOnPath(NodeData, PositionPercent);

にて、パス全体の移動長さに対して 0~1.0の間で移動位置を指定する部分。

この時与える NodeData は単なる Vector3の配列でしかない。
つまり、このデータ列が用意できるなら、特に iTween Visual Editor を使わなくても動作できる。

例えば、通過ポイントのようなオブジェクトがシーンに既に存在しているような場合、それらのXYZを得て、Vector3の配列に収めれておけば引数に利用できる。

iTweenPathスクリプト


iTween Visual Editorパッケージに含まれている。

このスクリプトのメンバ関数

static GetPath(string requestedName)

を使うと、Visual Editor でシーン上に配置したNodeの配列(Vector3)が簡単に得られる。
(関数型がStaticに注意。パスを複数作成すると、iTweenPathスクリプトも複数Component追加する為、それらのパス名を一意に管理する為にこうなっているようだ)

このスクリプトは単純に、シーン上でビジュアルエディットしたNodeの配置を単純なVector3配列で受け取れるものと解釈できるので、他の用途にも利用価値があるかもしれない。



0 件のコメント:

コメントを投稿