353 Views
July 15, 17
スライド概要
2016/11/5に開催されたUnity道場京都スペシャルの資料です。
講師:安原 裕二(ユニティ・テクノロジーズ・ジャパン合同会社)
リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。
unity 道場 集中講座その3 プロが教える脱初心者スクリプト術! ユニティ・テクノロジーズ・ジャパン フィールド・エンジニア 安原 祐二
unity 道場 集中講座その3 プロが教える脱初心者スクリプト術! 物理を使った ユニティ・テクノロジーズ・ジャパン フィールド・エンジニア 安原 祐二
本日のおはなし unity 道場 ・動きを作るテクニック ・プランナー、アーティストさんにも役に 立つもの COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
本日のおはなし unity 道場 ・実演あり ・実演内容も資料に入れてある ・メモを取る必要はなし! COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
本日のおはなし unity 道場 ・紹介するプログラムはとてもシンプル ・処理を列挙するだけ ・if 文すら書かない COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
本日のおはなし unity 道場 ・「あとでやってみよう!」 ・と思ってもらえるようにがんばります! COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 まずはシンプルに キャラクターを 動かしてみよう
実演パート Unity File Edit Assets GameObject Component Window Help Create Empty N Create Empty Child N 3D Object Cube 2D Object Sphere Light Capsule Audio Cylinder UI Plane Particle System Quad Camera Ragdoll Center On Children Terrain Make Parent Tree Clear Parent Wind Zone Apply Changes To Prefab
実演パート Project Create Folder C# Script Javascript Editor Test C# Script Shader Scene Reveal in Finder Open Delete Open Scene Additive Import New Asset... COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート Project Create SimplePlayer COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlayer : MonoBehaviour {
5
6 void Update () {
7 var hori = Input.GetAxis("Horizontal");
8 var vert = Input.GetAxis("Vertical");
9 transform.position += new Vector3(hori, vert, 0f);
10 }
11 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 InputManager で入力をシンプル にしておこう
実演パート Unity File Edit Assets GameObject Component Window Help Undo Z Redo Z Cut X Copy C Paste V Duplicate D Delete Frame Selected F Lock View to Selected F Find F Select All A Play P Pause P Step P Sign in... Selection Project Settings Input Graphics Emulation Tags and Layers Network Emulation Audio Time Snap Settings... Player Physics Physics 2D Quality Graphics Network Editor Script Execution Order Cluster Input Inspector InputManager Axes Size 18 Horizontal Name Horizontal Descriptive Name Descriptive Nega Negative Button left Positive Button right Alt Negative Butt a Alt Positive Butt d Gravity 1000 Dead 0.001 Sensitivity 1000 Snap Invert Type Key or Mouse Button Axis X axis Joy Num Get Motion from all joystick Vertical Fire1 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
unity 道場 Time.deltaTime を使おう
unity 道場 Δt について復習
ゲームが動くってどういうこと? unity 道場 細かい処理を繰り返して動きを作っている 時間 処理(Update) COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
Δt とは unity 道場 ひとつの処理にかける時間がΔt Δt 時間 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
Δt とは unity 道場 ひとつの処理を1フレームと呼ぶ Δt 時間 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
Δt とは unity 道場 秒間20フレームの場合 Δt 20フレーム 1秒 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
Δt とは unity 道場 Δtの平均は1/20秒 Δt 20フレーム 1秒 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
Δt とは unity 道場 つまり、Δtは秒間フレーム数の逆数 Δt 20フレーム 1秒 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 Δt をプログラムに組み込もう
実演パート unity 道場 FixedUpdate を使おう
実演パート
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlayer : MonoBehaviour {
5
6 void FixedUpdate () {
7 var hori = Input.GetAxis("Horizontal") * Time.fixedDeltaTime;
8 var vert = Input.GetAxis("Vertical") * Time.fixedDeltaTime;
9 transform.position += new Vector3(hori, vert, 0f);
10 }
11 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
【覚書】 Update は1秒間に何回呼ばれるかわからない(性能が低い環境だと 少なくなる) →FixedUpdate は1秒間に呼ばれる回数が固定 Time.deltaTime は変動する(同じフレーム内では固定) →Time.fixedDeltaTime は値が固定 FixedUpdate を使うとシンプルに! Δt は Time.fixedDeltaTime COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 Rigidbody を使おう
実演パート Inspector Cube Tag Untagged Layer Default Transform Position X 0 Y 0 Z 0 Rotation X 0 Y 0 Z 0 Scale X 1 Y 1 Z 1 Cube (Mesh Filter) Mesh Cube Box Collider Mesh Renderer Default-Material Shader Standard Add Component rigidbody Search Rigidbody Rigidbody 2D New Script COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート Inspector Cube Tag Untagged Layer Default Transform Position X 0 Y 0 Z 0 Rotation X 0 Y 0 Z 0 Scale X 1 Y 1 Z 1 Cube (Mesh Filter) Mesh Cube Box Collider Mesh Renderer Default-Material Shader Standard Rigidbody Mass 1 Drag 0 Angular Drag 0.05 Use Gravity Is Kinematic Interpolate None Collision Detection Discrete Constraints Add Component COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 AddForce に入力値を そのまま入れる
実演パート
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlayer : MonoBehaviour {
5
6 void FixedUpdate()
7 {
8 var hori = Input.GetAxis("Horizontal");
9 var force = new Vector3(hori, 0, 0) * 100f;
10 GetComponent<Rigidbody>().AddForce(force);
11 }
12 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 Drag を使って物体を止めよう
Rigidbody Mass 1 Drag 10 Angular Drag 0.05 Use Gravity Is Kinematic Interpolate None Collision Detection Discrete Constraints COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
unity 道場 Drag を制するものは Rigidbody を制する
一定の外力を加えると、ある速度に収束する unity 道場 v 0.5 t 0.5 1 1.5
最終的な速度、それが終端速度 unity 道場 v 0.5 t 0.5 1 1.5
終端速度を算出する記事がありました! unity 道場 Qiita キーワードを入力 News Qiita利用規約を一部修正しました [Unity]RigidbodyのDragから終端速度を得る Unity 2301 Rigidbody 3 Physics 12 yuji_yasuharaが2016/09/16に投稿(2016/09/16に編集)・編集履歴(11)・問題がある投稿を報告する
unity 道場 http://qiita.com/yuji_yasuhara/ items/1f438f0f27f5ef854a73
外力、質量、ドラッグが与えられたときの終端速度 v’ unity 道場 v' = F0 / mk * (1 - kΔt) m:質量 k:ドラッグ F0:外力 v':終端速度 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
終端速度 v’ を得るための外力(単なる式の変形) unity 道場 F0 = mkv' / (1 - kΔt) m:質量 k:ドラッグ F0:外力 v':終端速度 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlayer : MonoBehaviour {
5
6 void FixedUpdate()
7 {
8 var hori = Input.GetAxis("Horizontal");
9 var kmph = 100f;
10 var mps = kmph*(1000f/3600f);
11 var target_velocity = mps * hori;
12 var v = new Vector3(target_velocity, 0f, 0f);
13 var rb = GetComponent<Rigidbody>();
14 var force = (rb.mass*rb.drag*v)/(1f - rb.drag*Time.fixedDeltaTime);
15 rb.AddForce(force);
16 Debug.LogFormat("velocity={0}km/h", rb.velocity.magnitude*(3600f/1000f));
17 }
18 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
v 0.5 t 0.5 1 1.5
unity 道場 バネを扱おう
バネとは、距離に比例する力のこと unity 道場 弱い 強い COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
バネをプログラムで書く unity 道場 void AddSpringForce(Vector3 target_position, float r) { var diff = target_position - transform.position; var force = diff * r; rigidbody_.AddForce(force); } COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
オーバーシュート(目標ポイントを通り過ぎる) unity 道場 x 1 2 3 t
unity 道場 オーバーシュートしないバネ係数 を知りたくなる
オーバーシュートしない条件 unity 道場 r <= mk^2 / 4 m:質量 k:ドラッグ r:バネ係数 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
【覚書】 運動方程式より ma = F 外力はバネによる外力Frと抵抗力による外力Fk ma = Fr + Fk Fr = r(x0 - x)およびFk = -mkvより ma = r(x0 - x) - mkv a = Δ^2x / Δt^2 および v = Δx / Δt より m(Δ^2x / Δt^2) = r(x0 - x) - mk(Δx / Δt) 移項して (Δ^2x / Δt^2) + k(Δx / Δt) + (r / m)(x - x0) = 0 x0 = 0とおく (Δ^2x / Δt^2) + k(Δx / Δt) + (r / m)x = 0 ・・・・・(1) y'' + ky + (r / m)y = 0 方程式y^2 + ky + (r / m) = 0が虚数解を持つとき、(1)は周期関数となり振動する y = (-k ± √(k^2 - 4r / m)) / 2 判別式Dは D = k^2 - 4r / m 振動しない条件は判別式D ≥ 0より k^2 - 4r / m ≥ 0 4r ≤ mk^2 r ≤ mk^2 / 4 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
unity 道場 回転を使おう
unity 道場 AddTorque を理解しよう
unity 道場 トルクは物体を回転させる力
unity 道場 AddForce は位置 AddTorque は回転
unity 道場 トルクは 回転軸と大きさで表す
unity 道場 AddTorque(new Vector3(2, 0, 0)) は X軸に対して2のトルク
unity 道場 トルクのすごいところ 重ねて(足して)も大丈夫!
実演パート unity 道場 飛行機の操作を作ってみよう
実演パート unity 道場 Input.GetAxis で AddTorque
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlane : MonoBehaviour {
5
6 void FixedUpdate ()
7 {
8 var rb = GetComponent<Rigidbody>();
9 var hori = Input.GetAxis("Horizontal");
10 var vert = Input.GetAxis("Vertical");
11 rb.AddTorque(new Vector3(0, hori, 0));
12 rb.AddTorque(new Vector3(vert, 0, 0));
13 }
14 }
ヨー(yaw) ピッチ(pitch) ロール(roll)
unity 道場 ロールしてしまう問題
unity 道場 外積を使おう
外積とは・・・ unity 道場 ・外積の結果はベクトル! ・AxB と表記する(ことが多い) ・xだからクロス積とも呼ぶ。英語で言うと cross product ・Unity では Vector3.Cross という関数 ・var C = Vector3.Cross(A, B); と書くと、ベクトルCはAxBになる ・ベクトルA:(Ax, Ay, Az) と B:(Bx, By, Bz) の外積を C:(Cx, Cy, Cz) とすると Cx = AyBz - AzBy Cy = AzBx - AxBz Cz = AxBy - AyBx なにやら神秘的・・・! COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
外積AxB(AとBの面に垂直、長さが平行四辺形の面積) unity 道場 AxB θ B A |A||B|sinθ COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
現在の向きがAだとして、Bの方向に向けたいときのトルクは? unity 道場 B A COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
トルクは回転軸、つまり外積の方向! unity 道場 B A COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
ほんの少ししか差がないときはトルクを小さくしたい unity 道場 B A COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
外積そのまんまで、わりとバネっぽくなる! unity 道場 AxB B A |A||B|sinθ COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
外積そのまんまで、わりとバネっぽくなる! unity 道場 90°以上でもバネが弱くなるので注意 (Atan を利用するなどで回避可能) AxB B A |A||B|sinθ COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlane : MonoBehaviour {
5
6 void FixedUpdate ()
7 {
8 var rb = GetComponent<Rigidbody>();
9 var hori = Input.GetAxis("Horizontal");
10 var vert = Input.GetAxis("Vertical");
11 rb.AddTorque(new Vector3(0, hori, 0));
12 rb.AddTorque(new Vector3(vert, 0, 0));
13
14 var left = transform.TransformVector(Vector3.left);
15 var horizontal_left = new Vector3(left.x, 0f, left.z).normalized;
16 rb.AddTorque(Vector3.Cross(left, horizontal_left) * 4f);
17 }
18 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlane : MonoBehaviour {
5
6 void FixedUpdate ()
7 {
8 var rb = GetComponent<Rigidbody>();
9 var hori = Input.GetAxis("Horizontal");
10 var vert = Input.GetAxis("Vertical");
11 rb.AddTorque(new Vector3(0, hori, 0));
12 rb.AddTorque(new Vector3(vert, 0, 0));
13 var left = transform.TransformVector(Vector3.left);
14 var horizontal_left = new Vector3(left.x, 0f, left.z).normalized;
15 rb.AddTorque(Vector3.Cross(left, horizontal_left) * 4f);
16 var forward = transform.TransformVector(Vector3.forward);
17 var horizontal_forward = new Vector3(forward.x, 0f, forward.z).normalized;
18 rb.AddTorque(Vector3.Cross(forward, horizontal_forward) * 2f);
19 }
20 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 便利関数 AddRelativeTorque
実演パート
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlane : MonoBehaviour {
5
6 void FixedUpdate ()
7 {
8 var rb = GetComponent<Rigidbody>();
9 var hori = Input.GetAxis("Horizontal");
10 var vert = Input.GetAxis("Vertical");
11 rb.AddRelativeTorque(new Vector3(0, hori, 0));
12 rb.AddRelativeTorque(new Vector3(vert, 0, 0));
13 var left = transform.TransformVector(Vector3.left);
14 var horizontal_left = new Vector3(left.x, 0f, left.z).normalized;
15 rb.AddTorque(Vector3.Cross(left, horizontal_left) * 2);
16 var forward = transform.TransformVector(Vector3.forward);
17 var horizontal_forward = new Vector3(forward.x, 0f, forward.z).normalized;
18 rb.AddTorque(Vector3.Cross(forward, horizontal_forward) * 2);
19 }
20 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
実演パート unity 道場 飛行機なので ヨーはロールしながら
実演パート
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlane : MonoBehaviour {
5
6 void FixedUpdate ()
7 {
8 var rb = GetComponent<Rigidbody>();
9 var hori = Input.GetAxis("Horizontal");
10 var vert = Input.GetAxis("Vertical");
11 rb.AddRelativeTorque(new Vector3(0, hori, -hori));
12 rb.AddRelativeTorque(new Vector3(vert, 0, 0));
13 var left = transform.TransformVector(Vector3.left);
14 var horizontal_left = new Vector3(left.x, 0f, left.z).normalized;
15 rb.AddTorque(Vector3.Cross(left, horizontal_left) * 2);
16 var forward = transform.TransformVector(Vector3.forward);
17 var horizontal_forward = new Vector3(forward.x, 0f, forward.z).normalized;
18 rb.AddTorque(Vector3.Cross(forward, horizontal_forward) * 2);
19 }
20 }
COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
unity 道場 前進!
終端速度 v’ を得るための外力(再掲) unity 道場 F0 = mkv' / (1 - kΔt) m:質量 k:ドラッグ F0:外力 v':終端速度 COPYRIGHT 2016 @ UNITY TECHNOLOGIES JAPAN
1 using UnityEngine;
2 using System.Collections;
3
4 public class SimplePlane : MonoBehaviour {
5
6 public float target_kmph_ = 100f;
7
8 void FixedUpdate ()
9 {
10 var rb = GetComponent<Rigidbody>();
11 var hori = Input.GetAxis("Horizontal");
12 var vert = Input.GetAxis("Vertical");
13 rb.AddRelativeTorque(new Vector3(0, hori, -hori));
14 rb.AddRelativeTorque(new Vector3(vert, 0, 0));
15 var left = transform.TransformVector(Vector3.left);
16 var horizontal_left = new Vector3(left.x, 0f, left.z).normalized;
17 rb.AddTorque(Vector3.Cross(left, horizontal_left) * 2);
18 var forward = transform.TransformVector(Vector3.forward);
19 var horizontal_forward = new Vector3(forward.x, 0f, forward.z).normalized;
20 rb.AddTorque(Vector3.Cross(forward, horizontal_forward) * 2);
21 var force = (rb.mass*rb.drag*target_kmph_/3.6f)/(1f - rb.drag*Time.fixedDeltaTime);
22 rb.AddRelativeForce(new Vector3(0f, 0f, force));
23 }
24 }
unity 道場 おしまい この講演のUnityプロジェクトはこちらからダウンロードできます: https://www.dropbox.com/s/3aokgqnqs05sdyg/UnityDojoSpecial2016Yasuhara.zip?dl=0