code ソーシャル

Unityアプリcodetips(6)

スポンサーリンク

チキンレース〜キャットエスケープを分解しています。

現在目の疲労改善サプリを3種類ほど私で人体実験中です。

一つ効果があると実感できるものがあるので、他のものと成分の違いを確認し、何が効果があるのか、価格への反映はどの程度なのかを確認中です。

効果があると実感できるものは、1日分あたりの分量換算で他製品の1.5倍程度価格が高くなっています。

今後コロナをきっかけに、さらに人類の液晶画面と向き合う時間は増加するので、面白いマーケットだと見ています。

//tips

//簡単なゲームオーバーの表示方法

UIテキストにゲームオーバーを表示させたい時は、ゲーム中の表示条件またはゲームオーバーの条件が分かっていると作りやすい。

チキンレースの場合は、ゴールを超えてしまったらゲームオーバーと表示させたいため、逆にいうと
float length = this.flag.transform.position.x - this.car.transform.position.x;
length>=0であればゲーム続行で、マイナスになった際にゲームオーバーと表示させればいいことがわかる。

なので、if~elseで表され、
void Update()
{
float length = this.flag.transform.position.x - this.car.transform.position.x;
if(length >= 0)
{
this.distance.GetComponent<Text>().text = “ゴールまで” +length.ToString(“F2”)+”m”;
}
else
{
this.distance.GetComponent<Text>().text =“ゲームオーバー”;
}
}

//オブジェクトのコンポーネントを取得する際に例外表記が許されるtransform

transformはcar.transform.position.xのようにcarオブジェクトにアタッチされているTransformコンポーネントが持つ座標にアクセスできる。

しかし、一般的にオブジェクトにアタッチされているコンポーネントを取得したい時には
car.GetComponent<AudioSource>();
のようにGetComponentを使わなければならない。

transformはGetComponent<>()の使用を短縮してtransformで表すことができる。

//スクリプト内の作成済みメソッドの呼び出し方

オブジェクトにアタッチしたスクリプト内のメソッドを呼び出したいときには
car.GetComponent<CarController>().Run()
のように記述する。

carオブジェクトにアタッチされたCarControllerスクリプトをコンポーネントとして呼び出し、そのスクリプト内に書かれたメソッドであるRun()を呼び出している。

スクリプトもコンポーネントの一つであることを理解するとわかりやすい。

//ワールド座標系レイヤーの設定

初期時点で背景画像とプレイヤーオブジェクトの前後関係がうまくセットできないことがあるが、それはレイヤーの操作によって改善される。

ワールド座標系ではレイヤーが大きい番号であればあるほど最前面に表示され、最後面は0となっている。

プレイヤーオブジェクトのインスペクターSprite Render項目のOrder in Layerの数値を変更することで順番を変えることができる。

Sprite RenderのSpriteは画像のことで画像をどのように2D,3Dに表すのかを調整する項目となっている。

//GetMouseメソッドと同様のGetKeyメソッド

GetMouseメソッドと同様にキー操作もInput.GetKeyの形で表す。

GetKeyDown:押した瞬間
GetKey:押している間
GetKeyUp:離した瞬間

これらのメソッドの引数にとれるのが、
KeyCode.UpArrow:上矢印キー
KeyCode.Space:スペースキー
KeyCode.A:Aボタン
となっており、

GetKeyDown(KeyCode.LeftArrow)のように表される。

これに動かす力も加えて設定したい場合、ifで方向の条件を下記、trueを返した場合、動きを加える形に設定する。

void Update()
{
if(Input.GetKeyDown(KeyCode.LeftArrow))
{
transform.Translate(-3,0,0);
}
if(Input.GetKeyDown(KeyCode.RightArrow) )
{
transform.Translate(3,0,0);
}
}
//Physicsを使わずに落下動作を組む

Physicsの重力落下をアタッチしなくても、スクリプトで落下をさせることができる。

スクリプトの方が柔軟な設定ができるという利点がある。

例えばスクリプトにすることで下記のようなものを書くことができる。
void Update()
{
transform.Translate(0,-0.1f,0);

if(transform.position.y < -5.0f)
{
Destroy(gameObject);
}
}
マイフレーム下に0.1移動し、y座標が-5以下になった時にオブジェクトを破棄する。

//オブジェクト同士の衝突判定と衝突応答の設計

オブジェクトの輪郭線に接したかどうかを検出するのは計算量が膨大になってしまうので、円や円柱などの形で簡易的に表されることが多い。

円を使用した当たり判定の場合、円の半径を使って当たり判定をすることができる。

双方のオブジェクトの中心座標の距離が、双方のオブジェクトの半径を足したものより小さくなれば、それは各々の円が一部かぶっていることを示すので、当たり判定とする。

双方の中心座標の距離を三平方の定理magnitudeを使うことで求めることができる。

vector2 p1 = transform.position; //矢の中心座標
vector2 p2 = this.player.transform.position; //プレイヤーの中心座標
vector2 dir = p1 - p2;

float d = dir.magnitude;

float r1 = 0.5f; //矢の半径
float r2 = 1.0f; //プレイヤーの半径

if(d < r1 + r2)
{
Destroy(gameObject);
}
このifの中身で双方の半径の和より中心座標間の距離が小さければ、当たりとみなし、オブジェクトを消滅させている。

//ジェネレータースクリプトでPrefabをもとに1秒間隔でインスタンス生成

上から降る矢を1秒間隔で生成するスクリプトを考える。

public GameObject arrowPrefab;
float span = 1.0f;
float delta = 0;
1秒間隔で生成したいのでspanを1とし、間隔を数えるためにdeltaを作成する。

void Update()
{
this.delta += Time.deltaTime;
if(this.delta > this.span)
{
this.delta = 0;
GameObject go = Instantiate(arrowPrefab) as GameObject;
int px = Random.Range(-6,7);
go.transform.position = new Vector3(px, 7, 0);
}
}
Time.deltaTimeは直前のフレームと今のフレーム間で経過した時間[秒]を返す。
そのためthis.deltaの中にフレームが変わるごとに時間がどんどん蓄積され、spanで設定されている時間を超えるとifの結果の処理に移るようになっている。

処理内容としては
・蓄積されたthis.deltaの値を0に初期化する
・InstantiateメソッドでarrowPrefabのインスタンスを生成
・生成先を指定するためpx変数を作り、x座標のRandom.Rangeで-6以上7未満に範囲を指定
・生成したオブジェクトの位置を(x,y,z)で指定するためにnew Vector3で指定

ここでなぜnewではなくInstantiateを使用しなければいけないかというと、MonoBehaviorクラスを使用しているからで、

public class Rule : MonoBehaviour
{
public Rule(int i)
{

}
}
public Rule rulePrefab;
Rule rule2;
void Start()
{
rule2 = Instantiate(rulePrefab) as Rule;
}

ここまでがMonoBehaviorクラスを使用している場合の対応例。

If you don't inherit from MonoBehaviour, you should use the new keyword to create new instance of it. Now, you can use the parameter in the constructor if you want.
つまり、MonoBehaviour以外の場合は、下記。

public class Rule
{
public Rule(int i)
{

}
}
Rule rule2 = null;

void Start()
{
rule2 = new Rule(3);
}
で表すことができる。

英語だが下記の説明が参考になる。

https://stackoverflow.com/questions/37398538/unity-null-while-making-new-class-instance/37399263#37399263

https://stackoverflow.com/questions/44273613/unity3d-c-whats-the-difference-between-instantiating-a-prefab-as-a-gameobje

これでGameObject hogeGameObject = new GameObject("Hoge”);などのようにnewでオブジェクトを生成しない理由がわかった。

さらにas GameObjectとInstantiate()の後に続く理由は、Instantiate で返されるオブジェクトは Object型のためそのままでは操作できないからとされていたが、アップデートによって生成元と同じものが返されるようになり、特に必要なくなっているという話もある。

旧来のものの説明は下記が参考となる。
https://qiita.com/Gok/items/f732964d175bf99ffba9

//UIオブジェクトのImageにあるFill機能を利用して画像の表示領域を変化させる

Fill Methodは画像の表示領域を変化させることでゲージの増減を示すことができる。

Horizontal:横方向に画像を切り取る
Vertical: 縦方向に画像を切り取る
Radial 90:90度扇型に画像を切り取る
Radial 180:半円形に画像を切り取る
Radial 360:円形に画像を切り取る

UIのimageからimagetypeをFilledに選択し、FilledMethodをRadical 360などとする。

ダメージ判定をこのhpGaugeに反映させる必要があるので
UIを監督するスクリプトを作成し、DecreaseHP()メソッドを追加していく。

public class GameDirector:MonoBehavior
{
GameObject hpGauge;

void Start()
{
this.hpGauge = GameObject.Find(“hpGauge”);
}
public void DecreaseHp()
{
this.hpGauge.GetComponent<Image>().fillAmount -= 0.1f;
}
}
監督スクリプトの中でFindを使用してhpGaugeのアクセスを確保し、ダメージを受けたらfillAmountを減少させる新しいメソッドを作成している。

ただこれは減少が発生するトリガーについては記載されていないので、このメソッドが実行されるタイミングがない。

そのため、矢のコントローラスクリプトの当たり判定の際に一緒にこのDecreaseHpメソッドを呼び出す処理を行う必要がある。

これは
if(d < r1 +r2)
{
GameObject director = GameObject.Find(“GameDirector”);
director.GetComponent<GameDirector>().DecreaseHp();

Destroy(gameObject);
}
と追加処理を行うことで当たり判定時にうまく減少処理を行える。

人気の記事

1

皆さん、ついに、エアラインでも、サブスクリプションが始まったのはご存じですか? まだ実験段階ですが、ANAが、定額全国住み放題サービスを提供する「ADDress」と組んで、国内線を4回まで定額利用可能 ...

2

無料でネットショップを開けるアプリとして多くの人に驚きを与えたBASE株式会社が、2019年10月25日東証マザーズに上場しました。2020年2月時点で90万店を超えるショップを抱えるまでに成長してい ...

3

2011年にサービスを開始してから圧倒的な成長率を誇るインテリア通販サイト 【FLYMEe/フライミー】を皆さんご存じでしょうか。 「自分のイメージするインテリア、本当に欲しいインテリアがどこにあるの ...

4

ついに、noteの月間アクティブユーザー数が4400万人(2020年3月時点)に到達しました。 そもそも、「note」とは、クリエイターが、文章やマンガ、写真、音声を投稿することができ、ユーザーはその ...

5

ボードゲームカフェが1日2回転で儲かるという記事をみつけたので興味を持ち、調べてみました。 まずは、需要がどれくらいあるのか、市場のようすからみていきましょう。 世界最大のボードゲーム市場はドイツで、 ...

-code, ソーシャル
-,

Copyright© BUSINESS HUNTER , 2023 All Rights Reserved Powered by AFFINGER5.