アフィリエイト広告を利用しています

現在ははてなブログで投稿しています!

広告

posted by fanblog

2017年08月02日

プレイヤーを動かす:関数の解説

なんか記事を分けるのが
面倒くさかったので関数はまとめて書きます。


やっぱ、一気に解説した方がいいのかな…?


というか、更新遅れてごめんなさい!
色々ありまして!はい、すみません!!

記事書いて、保存しようとしたら
ネットエラーが出て……。

結局保存されておらず
同じ部分を何回も書かされました……。

正直、めっちゃイラッときました!
今度からはネットが安定してる所で書こう…。
(やる気が一気に無くなります…)


……関数は、Start、FixedUpdate、Updateがあります。
順番に見ていきましょう。





Start関数


まず、Start関数はこれです!
void Start () {
 rb = this.gameObject.GetComponent<Rigidbody>();
 anim = this.gameObject.GetComponent<Animator>();
}

これはまぁ、Rigidbodyと
アニメーター(Animator)を取得して
使えるようにしてるだけなんですがね(笑)

GetComponent<取得したいコンポーネント>()

で「コンポーネント」が取得出来ます。


……コンポーネントについては、
またいつか ^_^;

近い内に記事を書きますね。
今のところはスルーでお願いします……
ごめんなさい m(_ _)m

2017/9/8 追記
コンポーネントについての記事を更新しました。
↓こちらからご覧下さい。

コンポーネントとは?


結果、「rb」には「Rigidbody」、
「anim」には「Animator」が
入っている事になるので
スクリプト内ではrbやanimと記述すれば
それぞれ Rigidbody 、 Animator が使えます。


FixedUpdate関数

void FixedUpdate () {
 //*****接地判定*****//
 if (Physics.SphereCast(this.gameObject.transform.position + new Vector3(0, 2f, 0), transform.lossyScale.x * 0.5f, Vector3.down, out hit, 2f)) {
  isGrounded = true;
 } else {
  isGrounded = false;
 }
 //*****************//
}



……なんか一行だけ
やたらと長いですが……。


まぁ、やってる事は
意外と簡単?かもしれません。




では、気を取り直して。


まず、FixedUpdateとは
何か、を説明していきましょうか。



FixedUpdateとは、
Updateよりも狭い間隔で呼ばれる関数
です。


どういう事かというと、
Updateよりも呼ばれる間隔が狭い…つまり、
Updateよりも先に呼ばれるという事ですね。


例を出すと、
Updateは一秒に一回呼ばれるとしましょう。
そうすると、FixedUpdateは0.5秒毎に
呼ばれる、みたいな感覚でしょうか。


もっと簡単に言えば、

FixedUpdate → Update

の順に更新され続ける!

と覚えて下さい(笑)


多分これで大体は合ってるかと…


話を戻しましょう。

それで、コメント化もしてありますが
FixedUpdateでは接地判定をしています。


大まかな流れとしては、
地面にキャラクターが着いているか
 h            h
 hはい         hいいえ
 ↓             ↓
isGround変数を   isGround変数を
 trueにする       falseにする

         ↓

  スクリプト内で「isGround」を使えば
    接地しているかどうかが扱える

こんな感じです。


この流れを、
FixedUpdateで処理しています。


if構文の使い方、
覚えていますか?


簡単に説明しますね。
if (条件) {
 ・・・条件が成り立つ時の処理・・・
} else {
 ・・・条件が成り立たない時の処理・・・
}


まぁ、これくらいは覚えていますよね!
……いますよね?


もし、「覚えていない!」という方は
こちらが制御構文の記事になります。

ご覧下さい。


それで、()の中が条件ですね。
その条件が一番がややこしいですが…。


まず、()内でやっている事を
軽く説明します。


使っているのは、
Physics.SphereCast()
というものです。


どういうものかと言うと、
仮想の球を飛ばしてその球が
  何かに当たるかどうか

を判定するものです。


指定した位置から、指定した方向に
向けて、指定した長さの分だけ
「仮想の球」を飛ばします。


飛ばすと言っても、
「バヒュッ」って感じでは
無くてですねー…

飛ばすというか、
伸ばすというか……。


………適当な語句が僕の
ボキャブラリーには無いので
動画のリンクを貼ります……。
そこでイメージを掴んで下さい…。



何か話がずれました、
Physics.SphereCast()は
仮想の球を飛ばすと言いましたが、
物理的な影響は一切ありません!

あくまでも「仮想」ですので、
判定のみに使う事が出来ます。


それをプレイヤーの位置から
下向きに飛ばしていき、
何かに着いたら「地面に着いている」と
判定する様にします。

無題2.png

ただ、普通に光線(Ray)も
使えるんですよ。

細い線をピーッっと飛ばしてですね、
判定も出来るんですよ。


何故使わないのかと言うと、
線なので細すぎるんですよ。

地面の端に行くと、
キャラクターが落ちなくても
「地面に乗っていない」と判定されて
しまう可能性があります。

↓こんな感じに
無題1.png

これを回避する為にわざわざ
仮想の球を使って判定する訳です!

どうです、面倒くさいでしょう?
でも、これが一番正確かと。

少し弱点もあるんですけどね…。
それは後で説明します!


では、Physics.ShereCast()の
()の中を説明していきましょう。
Physics.SphereCast(発射の原点, 仮想の球の半径, 発射する方向, 当たった物の情報, 最大距離)


上のを読めば大体分かると思います。

というか、丸っきりそのままです。


唯一、ん?と思うやつは
「当たった物の情報」ってやつですかね?


まぁこれもそのままなんですが、
「当たった物がオブジェクトか」や
「タグはGroundか」など、色々使えます。


ですが必ず必要なのが、
hitと言う変数を宣言しておく」事です。

変数の型は「RaycastHit」です。
(……確か)

覚えなくても生きていける予備知識を
下に少し書いておきます。

そこから「あ、そうなるんだ」というのを
探してみてください。
上のコードや、ここにある全コードを
見てもいいですね。



■予備知識■■■■■
変数 : RaycastHit hit;
記述 : out hit

変数 : RaycastHit _Hit;
記述 : out _Hit;
■■■■■■■■■■



()の中の一つ一つを見ていきましょう。
原点
 this.gameObject.transform.position
 ↑これでこのゲームオブジェクト(プレイヤー自身)の位置を取得し、
 それに new Vector3(0, 2f, 0)
 これ、「高さが2であとは全部0の三次元ベクトル」を足すことで、
 プレイヤー自身の位置より2だけ高い位置からRayを飛ばす様にします。

仮想の球の半径
 transform.lossyScale.x
 ↑これはプレイヤー自身の「横の」大きさですね。
 thisが付いていませんが、このオブジェクトを使っています。
 ……実は、thisとか要りません。
 分かり易くする為に書いているだけですので…。
 lossyScaleで大きさが取得出来るので、それの横、x を使っていますね。
 何故0.5を掛けて半分にしているか分かりますよね?
 プレイヤーの(横の)大きさに合わせるためですよ!
 ここで設定出来るのは「半径」なので、「プレイヤーの直径」に0.5を掛けて半分にし、半径として扱います!

発射する方向
 Vector3.down
 これは、三次元ベクトルの下、まぁつまりプレイヤーの向きに関係なく下向きに発射しろ、って事ですね。

当たった物の情報
 これはさっき少し説明したので良いかと思います。
 当たったオブジェクトの判定に使ったりします。

最大距離
 そのままですね。
 球が飛んでいける距離です。
 ここでは2fとしていますが、永遠に伸ばしていきたい時は
 Mathf.Infinity と記述すればいけますよ。
 (2f、別に f は要りません…)


無駄話が多すぎて長くなりましたが、
FixedUpdateをまとめましょう。

もう丸暗記、の方が早いです!

「ここをこうしとけば取り敢えずこうなる」

みたいな感じで!

今回で言うと、
if (Physics.SphereCast(this.gameObject.transform.position + new Vector3(0, 2f, 0), transform.lossyScale.x * 0.5f, Vector3.down, out hit, 2f)) {
 仮想の球が当たっている時の処理;
} else {
 仮想の球が当たっていない時の処理;
}


……完璧です。
もう言い残す事はありません……!




とまぁ、そんな感じで
地面に仮想の球が当たっている時は
isGroundedをtrueに、
当たっていない時はfalseにしているだけです。


FixedUpdateは以上になります。


Update関数

さて、いよいよ最後ですね。
疲れてきたので手短にいきます。
void Update() {
 if (isGrounded) {
  InputHorizontal = Input.GetAxis("Horizontal");
  InputVertical = Input.GetAxis("Vertical");
  InputMagnitude = new Vector3(InputHorizontal, 0, InputVertical);

  jumpPower = 30f;

  //*****移動*****//
  Cam_forward = Vector3.Scale(Cam.transform.forward, new Vector3(1, 0, 1)).normalized;

  move_forward = Cam_forward * InputVertical + Cam.transform.right * InputHorizontal;

  rb.velocity = move_forward * moveSpeed + new Vector3(0, rb.velocity.y, 0);

  //移動方向に向きを変える
  if (move_forward != Vector3.zero) {
   transform.rotation = Quaternion.LookRotation(move_forward);
  }
  //***************//
 }
}


文章でダラダラ書いていると
読みにくいと思うので、新しい
解説方法を試します!
まぁ、まとめ方をちょっと
簡単にするだけなんですが。
(↑どうでもいい)


if (isGrounded) { ・・・・・・ }
if構文は、()の中がtrueの時に実行
つまり、isGroundedがtrueの時
 ↓
接地している時に {} 内を実行する!
…………以上。

InputHorizontal = Input.GetAxis("Horizontal");
Input.GetAxis("Horizontal")で
「横方向のキーの入力」がfloat型で
取得出来ます!

横方向、というのは設定次第で
変わりますが…。
主に A, D キーや←→キーの事です。

それの入力を取得し、
InputHorizontal変数に入れています。

InputVertical = Input.GetAxis("Vertical");
これは上の横方向の入力の
縦バージョンです。

W, S キーや↑↓のキーの入力を
少数型で-1〜1の間で取得し、
InputVertical変数に入れています。

良ければ↓の動画も参考にして下さい。


InputMagnitude = new Vector3(InputHorizontal, 0, InputVertical);
「横の入力 + 0 + 縦の入力」で、
その値の三次元ベクトルを作成します。

「高さ」を制御する
キー入力は無いので、y軸は0です。

これはまた後日使います。

2017/9/13 追記
記事を見直したところ、
意味の分からない事が書いてあったので
↑を書き直しました。


jumpPower = 30f;
これはなんというか……
そのままですね。

jumpPower変数に30を
代入しているだけですね。

jumpPower変数は、確かfloat型で
宣言していました。

ですので30f、floatですね。
まぁ少数点が無いのでfは無くても
良いんですけどね(笑)

Cam_forward = Vector3.Scale(Cam.transform.forward, new (1, 0, 1)).normalized;
これは少し難しいですね。

・Vector3.Scale(a, b)
 a, bどちらとも三次元ベクトルが入り、
 その二つを掛け合わせた数を出します。
 つまり、a × bですね。

aには「カメラの正面を丸ごと」
bには「新しい(1, 0, 1)の三次元ベクトル」

これを掛け合わせるので、
「yだけが0」になるんです。

もしこれが無いと、
僕の場合「カメラの正面に向かって進む」
という処理をするので、
カメラが少しでも下に向いていたら
地面にめり込んで行く始末です。
無題3.png
ですのでyだけを0にし、
向き…ですかね?
を、正面に直しています。
無題4.png

・Vector3.normalized
 三次元ベクトルの向き(角度)は
 そのままで、長さのみを全て1に直します。


何故わざわざ値を1にするのか?
それは、使う目的にあります。

変数の名前からも分かる通り、
カメラの正面、というか
カメラの向きからプレイヤーが
進める向きを算出しますよね?

その為、必要なのは「向き」です。
長さは正直どうでも良いのです。

ま、ここだけですが。
要らないのは。

後に(次の行ですが)出てくる計算で使います!
ので、全て1にし、計算しやすくしています。

(参考に)


move_forward = Cam_forward * InputVertical + Cam.transform.right * InputHorizontal;
予め一つ一つを説明しておきます。
・move_forward ・・・ 進む方向を入れておく変数
・Cam_forward ・・・ 上で算出したプレイヤーが進む、カメラの正面
・InputVertical ・・・ 縦のキー入力
・Cam.transform.right ・・・ カメラの右
・InputHorizontal ・・・ 横のキー入力

これを少し頭に入れておいて下さい。

この一行は、「入力から進む方向を決める」というものです。

カメラに対して前(奥)に入力したのか、
右に入力したのか、とかです。

それでは、少しずつばらして見ていきましょう。

・Cam_forward * InputVertical
 これのInputVerticalですが、
 縦の入力は「-1〜1」の間で取得します。

 前入力(奥側、W)をした場合は 1 、
 後ろ入力(手前側、S)の場合は -1 、
 何も入力が無い場合は 0 、と
 入力に合った数値が返ってくるので
 カメラの正面にその値を掛けています。

 入力が正の数か0か負の数かで
 前後どちらに進んでいるか分かりますね。

・Cam.transform.right * InputHorizontal
 これはさっきの縦入力の横バージョンですね。

 Cam.transform.rightでカメラの右側を取得し、
 InputHorizontalの横入力値を掛けています。

 横入力は、左(-1、A)、右(1、D)です。
 これで左右どちらに進むのかが分かります。

それで、縦の進む方向と横の進む方向を
足していますが...。

個人的には、これは感覚の方が大切かと思います。

なんか、縦と横で足しとけば斜めとかでも進めそうじゃん

これで一発です。

rb.velocity = move_forward * moveSpeed + new Vector3(0, rb.velocity.y, 0);
rbがありますね!
まず初めに!

rbには何が入っていましたっけ?
忘れてませんよね、「Rigidbody」
つまり「物理演算」です。

velocityとは、「速度」の事です。

学校で習ったんですが、速度には
「進む方向」と「進む速さ」の二つが
必要らしいです。

それは少し置いといて、
「rb.velocity」で速度を取得出来ます。

それに
「進む方向」×「進む速さ」+「重力」
の値を取得した速度に代入しています。

余談ですが、進む方向は
-1とか0とか1とかの次元です。
これだけでは進めません。

だから、速さを掛けるわけですね。

if (move_forward != Vector3.zero) { ・・・・・・ }
これは、move_forward変数が
Vector3.zero、つまり Vector3(0, 0, 0) で
無ければ { } の中を実行する、という
事になっています。

条件の方を少し詳しくやりましょう。

move_forward変数が (0, 0, 0)に
なるのは、進む方向が無い時。

つまり、ほとんどありません…。
(詳しい事は分からないので恐らくですが…。)

まぁ言葉に直すと、
「回転する必要がある時」
に実行されます。

そういえば、「!=」覚えていますか?
「左辺と右辺が等しくない」です。

覚えておきましょう。

transform.rotation = Quaternion.LookRotation(move_forward);
少し飛びますが、
Quaternion.LookRotation(三次元ベクトル)」
で三次元ベクトルをQuaternionとして
扱うことが出来ます。

どういう事かというと…。
まず頭に入れておいて欲しいのが
それぞれの「」です。

今まで使ってきた型は、
「Vector3」です。
ですが、回転を扱える型は
「Quaternion」です。

この二つ、(将来的にも)大切です!

そして、変えたいのはなんでしたっけ?
「進む方向に、向き・・を」
変えたいんですよね?

それで、進む方向として
扱ってきた変数の型はなんですか?

Vector3ですよね?

ですから、
「Vector3をQuaternionにする」
いう事が必要です。

そこで、この一行が
役に立っている訳ですね。

あとはやっている事は簡単です。
transform.rotationで
このオブジェクトの回転を取得、
Vector3からQuaternionに直した値を
代入して実際に角度を変更しています。





終わりに

長い記事を読んで頂き、
ありがとうございました!


お疲れ様でした!








投稿コメント
* 気軽にコメントくださいー *

※ ブログに表示されるのは、主の承認が必要なので時間がかかります!
  コメントに気づかない場合もありますので、返信が遅れる場合も...

お名前:

メールアドレス:


ホームページアドレス:

コメント: 必須項目

この記事へのトラックバックURL
https://fanblogs.jp/tb/6550515
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック
検索
プロフィール
ピノまっちゃさんの画像
ピノまっちゃ
どうも、ピノまっちゃ(PinoMatcha)です!
ゲーム制作をちょこまか頑張ってる大学生で、プログラミングも独学です。
ですので実力は全然ですが、最善を尽くして頑張っております!

名前の由来はピノの抹茶味が好きだからじゃなくて、ピノと抹茶が好きだからです!


更新 : 不定期!
プロフィール
新着記事
最新のコメント
更新事項
2018/8/2 定期更新への変更の報告に追記しました。

2018/5/10 「続きを読む」機能の使い方がやっと分かりました。

2017/9/14 プレイヤーを動かす:関数の解説の一部を書き直しました。

2017/8/1 【unity5】カメラ移動・回転させる方法に多数の画像を追加しました。
カテゴリーアーカイブ
YouTubeチャンネル
Fantiaリンク
よければ応援お願いします!

Pixivアカウント
現在、調整中です…
×

この広告は30日以上新しい記事の更新がないブログに表示されております。