1. 研究の背景と目的 本研究は当初 RealSense3D カメラのジェスチャー認証を用いたアプリ開発を行っていた Intel の推奨する RealSense3D カメラの開発プラットフォームを一通り試してみたいと考え学習を 進めるうちに Unity による開発に興味を持った Unity にはオブジェクトに物理演算を付加するこ とができるので 物理シミュレーションを製作するのに適したプラットフォームであることに気 付いた そして その物理演算の精度は正しいのか という疑問からガリレオの斜面を利用した 物理シミュレーションアプリを開発することとなった ガリレオの斜面を利用した実験は大きな実験道具を使うことから一般的には普及していない そのことから Unity を利用しガリレオの斜面を物理実験の教材として使用できるアプリを開発 できないかと考え今回の研究に取り組んだ 1.1 Unity とは Unity とは 総合開発エンジン ゲームエンジン と呼ばれるものである.ゲームエンジンと いうのは コンピュータゲームのソフトウェアの主要な処理を代行するソフトウェアの総 称.Unity はオブジェクトに物理演算を付加し プレイしながらリアルタイムで編集できる.スクリ プトを書く際のプログラミング言語には C# UnityScript Boo を使用することができる UnityScript は JavaScript を元にモデル化された Unity 独自設計の言語になっている 本研究は C# の学習するために C#を使用しプログラミングした 1.1.2 マルチプラットフォーム Unity は Windows/Mac 用ゲーム Unity Web Player や Android 用アプリ ios 用アプリ PS3 な どのゲーム機など様々なプラットフォームで実行可能な形式で出力できるマルチプラットフォー ムである これにより Android には Java ios には Objective-C などと使い分けることなく C#で 開発すればそれぞれのディスプレイにあわせたレイアウト マウスやキーボード タッチパネル などの操作方法に合わせたプログラムを変更することで基礎となるプログラムはそのまま実行す ることができる 2. ガリレオの斜面 ガリレオは物体の落下する速度は質量によらず すべて同じであることを発見した さらにガ リレオは物体の落下速度が一定時間間隔でどう変化するのかを研究した 当時 正確な時間を計 れるような道具はなく 物体の自由落下は速すぎ測定することが困難だった そこで落下速度を 制御するために斜面を利用した その研究に使われたのが ガリレオの斜面 である 斜面の角度を変えながら球を転がすことで落下速度を制御することができた さらに 斜面に 沿って鈴を配置し球が触れるたびに鳴るようにした 鈴が一定間隔のリズムでなるように調整を 繰り返することで一定の時間間隔ごとに物体の移動する距離がわかるようになった これは耳で 一定間隔のリズムを聞くことが一定時間を計るのに何より正確だったためと言われている この実験の結果 球が静止状態から出発したとき 一定の時間間隔ごとに走った距離が 1 3 5 7 と奇数の比で増大していくことを発見した これは物体の落下速度が一定の割合で増加 している等加速度運動であることを証明した 3. 技術要素 3.1.開発言語 Unity の開発言語は C# UnityScript Boo が使用できる 本研究のスクリプトはすべて C#で記 述した 1
3.2. Unity 3.2.1. Unity の画面構成 Unity を起動すると以下の図 1 のような画面が表示される 図 1 Unity のインターフェース Unity の画面は主に以下のように分けられる ① Scene View Game View Scene View には作成するゲーム内のオブジェクトが映っており 実際にそれを動かしながら位 置や大きさの調整ができる 実際にゲームをプレイしながら オブジェクトの調整することがで きる Game View では カメラを通して見えるゲーム画面が映っている 実際にゲームを作成して出 力した際にゲームがどう見えるのかを このビューから確認することができる View 上部のタ ブで Scene View と Game View の表示を切り替えることができる ② Hierarchy View Hierarchy View には現在選択されている Scene 内に配置されているすべてのオブジェクトが格 納されている 各オブジェクトの階層構造を確認 編集することができる キャラクターモデル や図形などの素材を Hierarchy View 内に追加することで Scene 内にオブジェクトとして配置する こともできる また オブジェクトの追加はスクリプトや Hierarchy View の Create タブから行う こともできる ③ Inspector View Inspector View では選択されているオブジェクトがどのような設定で どのような要素を持っ ているのかを確認 編集することができる Inspector View の要素にはスクリプトやオーディオ 物理挙動などがあり Unity ではそれらの要素をコンポーネント(Component)と呼ぶ オブジェク トにコンポーネントを追加 アタッチ すると Inspector View 上にその情報が表示される オブジェクトがどこに位置しているか どこの角度を向いているか どれくらいの大きさかは それぞれ Transform コンポーネントの Position Rotation Scale に対応しており確認し編集するこ とができる 2
④ Project View Project View には現在作成しているゲームのプロジェクト内で使用できるすべてのオブジェク トやテクスチャー 音楽データ スクリプトなどゲームを形成する要素が格納されている 3.2.2. スクリプト スクリプトは Unity の中で作成することができる 新規のスクリプトを作成するには Project View で任意のフォルダを選択 右クリックから Create>C# Script を開き 名前をつけて保存する 新規作成した C# Script はデフォルトでは次のように表示される 例 C# Script ファイル名 NewScript using UnityEngine; using System.Collections; public class NewScript : MonoBehaviour // Use this for initialization void Start () // Update is called once per frame void Update () 作成したファイル名と一致するようにクラス名が付けられる クラス名とファイル名が一致し ていなければゲームオブジェクトにアタッチされたスクリプトコンポーネントは無効になってし まうで注意しなければならない Unity 内部処理と連携するため MonoBehaviour と呼ばれるクラスを実装する MonoBehaviour を継承することで GameObject にアタッチすることができる 次に Start 関数と Update 関数がある Start 関数はオブジェクトの最初のフレームで 1 度呼び出 され 初期化を行うのに便利な関数になっている Update 関数はオブジェクトのフレームが更新 する度に呼び出される オブジェクトを動作させたり ユーザー入力操作に反応させるためのイ ベントに使われる オブジェクトを原点から x 方向に毎フレーム 1 ずつ移動させるには以下のよ うに記述する using UnityEngine; using System.Collections; public class NewScript : MonoBehaviour // Use this for initialization void Start () transform.position = new Vector3(0, 0, 0); // Update is called once per frame void Update () transform.translate(1, 0, 0); 3
これは Start 関数で transform コンポーネントの position プロパティの3次元のベクトルデータ を(0,0,0)に初期化 さらに Update 関数の transform.translate(1, 0, 0);で 1 フレームごとに x 方向に 1 ずつ移動させることができる 基本的なコード オブジェクトを移動させる void Update () transform.translate(1, 0, 0); これは上記で記述したように 1 フレームごとに x 軸方向に 1 ずつ移動する また 以下のように書いても同じように移動させることができる void Update () transform.localposition += new Vector3(1.0f, 0.0f, 0.0f); transform.localposition は親オブジェクトから見た相対的な位置のこと 親オブジェクトがいな い場合は transform.position と同じ値になる float 型で少数を扱う場合は 1.5f のように数字のあとに f を付ける必要がある オブジェクトを回転させる void Update () transform.rotate(1, 0, 0); オブジェクトを 1 フレームごとに x 軸を中心に 1 ずつ回転させることができる オブジェクトを大きくする void Update () transform.localscale += new Vector3(1,0,0); オブジェクトを 1 フレームごとに x 軸方向に 1 ずつ大きくする ゲーム内の時間の経過を停止させる Time.timeScale = 0; 停止 Time.timeScale = 1; 再生 ゲーム内の時間の経過を調整することができる Time.timeScale = 0.5f;などにすることでスロー モーションにすることもできる scene を変更する Application.LoadLevel("シーン名"); 変更したい scene を宣言することで画面の切り替えができる scene の切り替えをするには一度 ビルドし Scenes In Build に scene を追加する必要がある 4
図 2 scene の追加 キー入力 if (Input.GetKey("escape")) transform.rotate(1,0,0); これはスペースキーを押している間 常にオブジェクトを回転させることができる また 使うメソッドによって入力を返すタイミングが異なる 表.キー入力 メソッド 内容 Input.GetKey キーを押している間は常に Input.GetKeyDown キーを押していない状態から押した時 Input.GetKeyUp キーを押している状態から離した時 別オブジェクトの参照 public GameObject 変数名; このように宣言するとスクリプトをアタッチしたオブジェクトとは別のオブジェクトを参照す ることができる 例えば 以下のように記述すると参照したオブジェクトを回転させることができる public class NewBehaviourScript : MonoBehaviour public GameObject Object; // Update is called once per frame void Update () 5
Object.transform.Rotate(1,0,0); 図 3 別オブジェクトの参照 参照させたいオブジェクトを図の四角で囲った部分にドラック ドロップすると参照すること ができる オブジェクトの表示 非表示 変数名.SetActive(true); 表示 変数名.SetActive(false); 非表示 オブジェクトの表示 非表示ができる 例えば 以下のように記述するとゲーム開始と同時に Object1 を表示 Object2 を非表 示にする さらに A キー B キーを押すことで Object1 と Object2 の表示を切り替えるこ とができる public class NewBehaviourScript : MonoBehaviour public GameObject Object1; public GameObject Object2; void Start() Object1.SetActive(true); Object2.SetActive(false); void Update() if(input.getkey("a")) Object1.SetActive(false); Object2.SetActive(true); 6
if (Input.GetKey("b")) Object1.SetActive(true); Object2.SetActive(false); 3.3. ガリレオの斜面アプリ 3.3.1. ステージの作成 まず ステージを作成する Hierarchy View の Create から 3D Object > Plane を作成する 作成 した Plane の Position を(0,0,0)にする 図 4 Plane の作成 さらに Plane にテクスチャーを設定しステージの色や質感を与える 本研究は教育用アプリな ので心理学的に落ち着くといわれる緑 青を貴重とし ステージには芝(緑) 背景には空(青)の 画像を使用する テクスチャーは設定したいオブジェクトにドラック ドロップすることで追加 することができる 図 5 テクチャーの追加 3.3.2. 斜面と球の作成 7
ガリレオの斜面に使用する斜面となる柱と 斜面を転がる球を作成する 斜面には Hierarchy View の Create から Cube を選択し Scale(48,1,1)の x 軸方向に長い柱を 2 本 作成 これら 2 本の柱(以下 レールを記述)を z 軸に 2 ずらし隙間ができるよう配置した さらに 球には Hierarchy View の Create から Sphere を選択し Scale(1.2,1.2,1.2)の球を作成し これがレールの隙間を転がるように配置する 球は重力に従って転がらなくてはならないので 物理挙動を設定する Unity ではオブジェクトに Rigidbody を追加することで重力を加えるこ とができる Rigidbody の追加は Hierarchy View で球のオブジェクト(Ball)を選択 Unity メニューの Component > Physics > Rigidbody をクリックすることでできる 図 6 Rigidbody の追加 Rigidbody には摩擦を表現することができるが ガリレオの斜面の実験を正確に測定するには 摩擦を無視しなければならないため 摩擦係数を 0 に設定する必要がある これは Physic Material を追加することで設定できる Physic Material は Project View の Create から作成する 作 成した Physic Material を選択するとパラメーターを調整することができるので摩擦の値を 0 に設 定する 図 7 Physic Material の設定 Physic Material の設定項目は以下の通りとなっている 8
表.Physic Material の設定項目 設定項目 Dynamic Friction Static Friction Bounciness Fricition Combine Bounce Combine 動いているオブジェクトの摩擦を調整できる 値は0 1の間 0の場合 摩擦はなくなる 静止した状態にかかる摩擦を調整できる 値は0 1の間 0の場合は 摩擦がない状態 反発係数を調整できる ボールが壁にぶつかった時どれくらい跳ね返るかを設定出来る 0の場合は まったく跳ね返らない 2つのオブジェクトがぶつかった時の摩擦係数の計算方法を設定できる Average : 平均 2つの摩擦係数の平均が適用される Multiply : 2つの摩擦係数の乗算が適用される Minimum : 小さい方の摩擦係数が適用される Maximum : 大きい方の摩擦係数が適用される 2つのオブジェクトがぶつかった時の反発係数の計算方法を設定できる Average : 平均 2つの反発係数の平均が適用される Multiply : 2つの反発係数の乗算が適用される Minimum : 小さい方の反発係数が適用される Maximum : 大きい方の反発係数が適用される 斜面をキーボード操作で角度が変えられるようする 斜面の回転軸となる位置に Cube のオブジェクト(以下 軸オブジェクトと記述)配置する 図 8 軸オブジェクト 軸オブジェクトを親オブジェクトとし 子オブジェクトにレールと球を配置する 軸オブジェクトに up キー down キーを入力すると z 軸を中心に 1 ずつ回転するスクリプトを アタッチする 親オブジェクトと子オブジェクトの動きは相対的になる つまり 親である軸オ ブジェクトが回転すると 子であるレールと球は軸オブジェクトを中心に回転する こうするこ とで レールの角度が大きくなっていくように見せることができる また このままレールの角度を上げてしまうと球は重力に従って落ちてしまうため レールの 9
角度を操作する間はゲーム内の時間を止める必要があると考え ゲーム開始と同時に Time.timeScale = 0 とし球が動いてしまうことを防いだ 球を転がすのは A キーを押すことで Time.timeScale = 1 に変更し時間を再生させた 3.3.3. 支柱を作成 レールはスクリプトによって上下するが レールがひとりでに上下しているように見え違和感 が生じると考えた そのため レールを支えているように見える支柱を作ることにした 図 9 支柱 支柱はレールの軸から 6/7 の部分を常に支えるようスクリプトをアタッチする 支柱の位置 x はレールの長さ L の 6/7 レールの角度 θ から計算する cos θ = x 6/7 L から x=6/7 L cos θ となる この式をスクリプトで書くには軸オブジェクトの角度 transform.localeulerangles.z(オ イラー角)を参照し cosθ を求める Unity で数学的な関数を利用するには Mathf クラスがある し かし Mathf.Cos はラジアン角で返されるため 軸オブジェクトの transform.localeulerangles.z で 参照したオイラー角をラジアン角に変換する必要がある ラジアン角への変換は Mathf.Deg2Rad で行うことができる これらをスクリプトを書くと以下のようになる public class OjWall : MonoBehaviour float x_pos; public GameObject Cube; //軸オブジェクトの参照 void Update () transform.localposition = new Vector3(((-(6/7 * 49)) * Mathf.Cos(Mathf.Deg2Rad * (-(Cube.transform.localEulerAngles.z - 360)))), 0, 0); また 支柱の高さ y もレールの角度によって変えなければならない 支柱の高さ y はレールの 角度 θ の Sin で求めることができる θsin = y 6 /7 L から 10
y=6 /7 L sin θ が支柱の高さ y の式になる 3.3.4. 鈴の配置 ガリレオの斜面は鈴を配置し 球が当たるたびに鳴るようにしなければならない 今回は球か ら 1 3 5 7 の位置に板のオブジェクトを配置した また 板の位置がわかりやすいように一 定の距離ごとに目印をつけた 図 10 1 3 5 7 の位置に配置した板のオブジェクト Unity にはオブジェクト同士の衝突判定の処理を行うかどうかを設定する istrigger という チェックボックスがあり チェックを付けるを衝突判定の処理が行われなくなる 図 11 Is Trigger の設定 今回作成した板のオブジェクトには衝突判定の処理をしたくないため 板のオブジェクト全て istrigger にチェックをつけた さらに 球には Is Trigger のオブジェクトに侵入した時に音が鳴るようなスクリプトをアタッ チする 球が Is Trigger のオブジェクトに侵入した際のイベントは OnTriggerEnter というメソッド を使うことで呼び出すことができる また 音を鳴らすことは audiosource.play()で行う AudioSource audiosource; // AudioSorce を格納する変数の宣言. 11
public AudioClip audioclip; // 効果音を格納する変数の宣言. void Start() audiosource = gameobject.getcomponent<audiosource>(); audiosource.clip = audioclip; // 鳴らす音(変数)を格納. audiosource.loop = false; // 音のループなし void OnTriggerEnter(Collider other) audiosource.play(); この時の使う音源は Unity にインポートし このスクリプトに参照する必要がある 今回作成するガリレオの斜面アプリは鈴の配置を 1 3 5 7 の他に 1 1 1 1 ま た鈴の配置を自由に変更できる Free Scene をそれぞれ作った 1 1 1 1 のガリレオの 斜面は上記で作成した 1 3 5 7 の配置を変えるだけだが Free は鈴の位置をユーザー が変更できるようにスクリプトを書かなければならない スクリプトは以下のようになっている private Vector3 screenpoint; private Vector3 offset; void OnMouseDown() //カメラから見たオブジェクトの現在位置を画面位置座標に変換 screenpoint = Camera.main.WorldToScreenPoint(transform.position); //取得した screenpoint の値を変数に格納 float x = Input.mousePosition.x; //オブジェクトの座標からマウス位置(つまりクリックした位置)を引いている //これでオブジェクトの位置とマウスクリックの位置の差が取得できる //ドラッグで移動したときのずれを補正するための計算だと考えれば分かりやすい offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(x, screenpoint.y, screenpoint.z)); void OnMouseDrag() //ドラッグ時のマウス位置を変数に格納 float x = Input.mousePosition.x; //ドラッグ時のマウス位置をシーン上の 3D 空間の座標に変換する Vector3 currentscreenpoint = new Vector3(x, screenpoint.y, screenpoint.z); //上記にクリックした場所の差を足すことによって オブジェクトを移動する座標位 置を求める 12
Vector3 currentposition = Camera.main.ScreenToWorldPoint(currentScreenPoint) + offset; //オブジェクトの位置を変更する transform.position = currentposition; 3.3.5. メニュー画面の作成 アプリが開始されるとメニュー画面が現れ Scene を選択できる画面を作成する 図 12 メニュー画面 Scene の選択には GUI のボタンで行う GUI(Graphical User Interface) は ユーザが視覚的に操 作できる入出力機能で ボタンやテキストフィールドを作成することができる これらは Hierarchy View の Create > UI の中から作成できる 図 13 GUI の作成 UI のメニューの中にはいくつもの部品があり これらの基本となるのが Canvas という部 品である Canas は無色透明の GameObject でボタンなどの UI を配置するためのベースとなる 13
他のゲーム画面と区別を付けるために Canvas の中に UI の Panel を作成し Canvas に色を付ける Panel は四角い領域の部品で Canvas とは異なり決まった色やイメージなどでパネル全体を描く ことができる Canvas の中に作ることで自動的に Canvas 全体を覆う大きさで組み込まれる 図 14 Panel の作成 さらに Panel の中に UI の Button を作成する ボタンのクリックイベントのスクリプトを以下 のように記述する public void ButtonPush() Application.LoadLevel("シーン名"); これは GUI ボタンがクリックされたとき Scene を呼び出し変更するものである このスクリ プトをボタンにアタッチし 画像のように Button(Script)の On Click()の項目に設定する 図 15 On Click()の設定 最後にビルドしそれぞれの Scene を設定する 今回は Web Player で出力させるため Web Player の項目を選択する 14
図 16 ビルド設定 4. 課題 今回使用したオブジェクトは Cube などの単純な図形を使用した また GUI もデフォルトの ものを多く使っている そのため アプリとして全体的に安っぽさ出てしまっている オブジェ クトをモデリング GUI などのレイアウトを変えることで 高級感や魅力のあるアプリになり 学習教材アプリとして学習意欲を高めることができたのではないかと思う また キーボード入力など PC での操作しか意識してなかったため Unity による開発のメリッ トであるマルチプラットフォームが生かしきれなかった マウス操作とタッチパネル操作はスク リプトの書き方に多くの共通点があり スマートフォンなどのタッチパネルによる操作を意識し ながら開発していれば Web Player スマートフォンアプリ ios 用アプリなどより多くの端末 に出力できていたと考える 5. まとめ 本研究では Unity による開発を行い ガリレオの斜面の物理実験教材のアプリを作った Unity による開発は初めての経験で知識がなく スクリプトの書き方 外部オブジェクトの参照方法な ど試行錯誤を繰り返し C#のプログラミング言語の学習 アプリ開発のプロセスを学ぶことがで きた また 本研究を通して Unity はゲーム開発だけに留まらず 物理シミュレーションとしても有 用でアプリ開発のプラットフォームとして学習する価値があることがわかった 情報メディア コースでは 3D モデルを扱い アニメーションを作成するという講義があったが プログラミン グを同時に学べる Unity の講義があってもいいのではないかと考えるほどだった 15
6. 謝辞 研究を行うにあたって ご指導して下さった徐丙鉄教授 また 多くのアドバイスをしてくれ た研究室のメンバーに心より御礼申し上げます 7. 参考文献 [1] Unity5 入門:最新環境による簡単 3D 2D ゲーム制作 荒川巧也 浅野祐一(2015) [2] Unity 入門:高機能ゲームエンジンによるマルチプラットフォーム開発 高橋啓治郎 [3] 世界でもっとも美しい 10 の科学実験 ロバート P クリース 青木薫 訳 [4] Unity マニュアル http://docs.unity3d.com/ja/current/manual/index.html [5] Unity C#基本コード http://lo25131.hatenablog.com/entry/2014/01/28/120732 8. 付録 ボールにアタッチしたスクリプト using UnityEngine; using System.Collections; public class ball : MonoBehaviour AudioSource audiosource; public AudioClip audioclip; public GameObject Ball; public GameObject Oball; private GUIStyle style; // AudioSorce を格納する変数の宣言. // 効果音を格納する変数の宣言. void Start() audiosource = gameobject.getcomponent<audiosource>(); audiosource.clip = audioclip; // 鳴らす音(変数)を格納. audiosource.loop = false; // 音のループなし style = new GUIStyle(); style.fontsize = 25; void OnTriggerEnter(Collider other) 16
audiosource.play(); // 音を鳴らす. void OnGUI() Vector3 Apos = Ball.transform.position; Vector3 Bpos = Oball.transform.position; style.fontstyle = FontStyle.Italic; GUI.Label(new Rect(0, 130, 310, 35), "ボールの現在の速度:" + transform.getcomponent<rigidbody>().velocity.magnitude.tostring("f1") + "m/s", style); GUI.Label(new Rect(0, 165, 310, 35), "ボールの移動距離:" + ((Apos Bpos).magnitude).ToString("f1") + "m", style); カメラにアタッチしたスクリプト(カメラの切り替え) using UnityEngine; using System.Collections; public class camerasp : MonoBehaviour public Camera MainCamera; public Camera SabCamera; public GameObject Cube; float x_pos; // Use this for initialization void Start() MainCamera.enabled = true; SabCamera.enabled = false; // Update is called once per frame void Update() x_pos = transform.localposition.x; if(input.getkey("up")) transform.localposition = new Vector3(((10) * Mathf.Sin(Mathf.Deg2Rad * ((Cube.transform.localEulerAngles.z - 360)))),0,0); if (Input.GetKey("down")) 17
transform.localposition = new Vector3(((10) * Mathf.Sin(Mathf.Deg2Rad * ((Cube.transform.localEulerAngles.z - 360)))), 0, 0); if (Input.GetKeyDown(KeyCode.Z)) MainCamera.enabled = true; SabCamera.enabled = false; else if (Input.GetKeyDown(KeyCode.X)) MainCamera.enabled = false; SabCamera.enabled = true; レールにアタッチしたスクリプト using UnityEngine; using System.Collections; public class Rail : MonoBehaviour private GUIStyle style; float z_rotation; void Start() style = new GUIStyle(); style.fontsize = 25; void Update() z_rotation = transform.localeulerangles.z; if (0 > z_rotation z_rotation > 270) if (Input.GetKey("up")) transform.rotate(0, 0, -1); if (Input.GetKey("down")) transform.rotate(0, 0, 1); 18
else if(z_rotation >= 0 && z_rotation <= 1) transform.rotate(0, 0, -0.1f); else if (z_rotation <= 270 && z_rotation >= 269) transform.rotate(0, 0, 0.1f); void OnGUI() style.fontstyle = FontStyle.Italic; GUI.Label(new Rect(0, 200, 300, 30), "斜面の角度:" + (((transform.localeulerangles.z - 360)).ToString("f0")) + " ", style); 支柱にアタッチしたスクリプト using UnityEngine; using System.Collections; public class OjWall2 : MonoBehaviour float x_pos; float y_scale; public GameObject Cube; // Use this for initialization void Start () // Update is called once per frame void Update () x_pos = transform.localposition.x; y_scale = transform.localscale.y; if (-42 <= x_pos && x_pos <= -1) if (Input.GetKey("up")) 19
transform.localposition = new Vector3(((-42) * Mathf.Cos(Mathf.Deg2Rad * ((Cube.transform.localEulerAngles.z - 360)))), 0, 0); transform.localscale = new Vector3(1, ((84) * Mathf.Sin(Mathf.Deg2Rad * ((Cube.transform.localEulerAngles.z - 360)))), 3); if (Input.GetKey("down")) transform.localposition = new Vector3(((-42) * Mathf.Cos(Mathf.Deg2Rad * ((Cube.transform.localEulerAngles.z - 360)))), 0, 0); transform.localscale = new Vector3(1, ((84) * Mathf.Sin(Mathf.Deg2Rad * ((Cube.transform.localEulerAngles.z - 360)))), 3); if (x_pos < -42) transform.localposition += new Vector3(0.1f, 0.0f, 0.0f); if (x_pos > -1) transform.localposition += new Vector3(-0.1f, 0.0f, 0.0f); メニューのアニメーションにアタッチしたスクリプト using UnityEngine; using UnityEngine.UI; using System.Collections; public class buttongarireo : MonoBehaviour public AnimationCurve animcurve = AnimationCurve.Linear(0, 0, 1, 1); public Vector3 inposition; // スライドイン後の位置 public Vector3 outposition; // スライドアウト後の位置 public float duration = 1.0f; // スライド時間 秒 // スライドイン Pause ボタンが押されたときに これを呼ぶ public void SlideIn() StartCoroutine( StartSlidePanel(true) ); // スライドアウト public void SlideOut() StartCoroutine( StartSlidePanel(false) ); 20
private IEnumerator StartSlidePanel(bool isslidein) float starttime = Time.time; // 開始時間 Vector3 startpos = transform.localposition; // 開始位置 Vector3 movedistance; // 移動距離および方向 if (isslidein) movedistance = (inposition - startpos); else movedistance = (outposition - startpos); while ((Time.time - starttime) < duration) transform.localposition = startpos + movedistance * animcurve.evaluate((time.time - starttime) / duration); yield return 0; // 1 フレーム後 再開 transform.localposition = startpos + movedistance; Scene Free の板オブジェクトにアタッチしたスクリプト using UnityEngine; using System.Collections; public class BarController : MonoBehaviour private Vector3 screenpoint; private Vector3 offset; void OnMouseDown() //カメラから見たオブジェクトの現在位置を画面位置座標に変換 screenpoint = Camera.main.WorldToScreenPoint(transform.position); //取得した screenpoint の値を変数に格納 float x = Input.mousePosition.x; //オブジェクトの座標からマウス位置(つまりクリックした位置)を引いている //これでオブジェクトの位置とマウスクリックの位置の差が取得できる //ドラッグで移動したときのずれを補正するための計算だと考えれば分かりやすい offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(x, screenpoint.y, screenpoint.z)); 21
void OnMouseDrag() //ドラッグ時のマウス位置を変数に格納 float x = Input.mousePosition.x; //ドラッグ時のマウス位置をシーン上の 3D 空間の座標に変換する Vector3 currentscreenpoint = new Vector3(x, screenpoint.y, screenpoint.z); //上記にクリックした場所の差を足すことによって オブジェクトを移動する座標位置を求める Vector3 currentposition = Camera.main.ScreenToWorldPoint(currentScreenPoint) + offset; //オブジェクトの位置を変更する transform.position = currentposition; カメラにアタッチしたスクリプト(時間調整 リセット) using UnityEngine; using System.Collections; public class Time : MonoBehaviour void Start() Time.timeScale = 0; void Update() if (Input.GetKey("s")) Time.timeScale = 0; if (Input.GetKey("a")) Time.timeScale = 1; if (Input.GetKey("space")) Application.LoadLevel("Scene 名"); 22