1日1Qiita2日目!
1日目、技術関連の話を全くしなかったことは反省しておりますorz... ってことで今日はちゃんと書きますね。
2か月前何があったの?
Unity、blender共にほぼ触ったことのない私。何を思ったかチンチロを作りたくなってGPT氏に助けを求めた。(確か運ゲーを作りたかった)
ちなみにチンチロのルールすら知らなかったのでまずそこから始まったんだけど((
さすがの私でもわかること。ダイス3つと茶碗が必要である!!!
blenderを触ってみる
ってことでまずダイスづくり。
blenderはUnityに比べたら触れたことはあったからわかる範囲で自力で進めました。
cubeだしてCtrl+Bで角丸めて(ベベルとかいう名前らしい)
形はできた…けど…..テクスチャってどうやって張るんだ!?
とりあえずサイコロの展開図をつくったら張れるのでは??と展開図を作成。
今まで一応マテリアル?と言われる奴は作ったことがあったので、その画像を今作った展開図に変えたい。と思ってガチャガチャしてたら...
でけた。
いやなんせ2か月前だからさ!もう紆余曲折とか覚えてないんだよね!!(ド無能)
確かUV展開がわからなくてGPTに助けを求めていた気がする。
立方体だからまだ助かった。
次はお椀
ただサイコロで疲弊していたわたくしはこのサイトでフリーのお皿を探して使わせていただきました。
https://www.cgtrader.com/free-3d-models/food/miscellaneous/damboo-bowl
↑こちらです。
Unityに戦場を移して本番開始
とりあえず置いただけの状態がこれ。
相変わらずY軸とZ軸が紛らわしくて発狂もの。
出目の取得はあとでやることにして、当たり判定をつけていく
コンポーネントを追加、ダイスにはBoxColliderとRigidbody、お椀にはMeshColliderを適用して重力と当たり判定をつけた。これですり抜けは回避できた。
しかし今は上から落とすだけ。しかも動きがもっさりしている。何故?
現実で考えてみるとたいてい空気抵抗がでかいとき、もっさりした動きになる気がする。ってことはこれ実物大的にはクソデカなのでは???
うわ縮めなきゃ。めんどい...
そうだ!もうこのプロジェクトのセカイの重力を変更しちゃえばいい。
編集→プロジェクト設定→Physics Setting...
これ真ん中デフォルトだと確か-9.81とかなんだけどね
-30にしてやったわ!!
大体3倍。力業すぎるけどこういうのがおもろいねん。これにてもっさり感とはおさらば~~
のちに調べましたが、Transformのscaleが元のオブジェクトからの倍率との情報がありました。
これを真と考えると一般的なお椀が15センチであることと、僕のお椀のScaleが207なことから、
15*207=3105 ...31メートル?
俺氏「31 mってどのくらい?」
GPT氏 「大型観光バス2台ちょい」
(;゚Д゚).......
あ、あとで悪影響が出た時対処法考えればええねん。次だ次。
次設定したのは、動摩擦力、静止摩擦力、弾性力。
こちらはAssetsに物理マテリアルっていうのを作ってその中で設定するらしい。
これはダイスの物理マテリアル設定
動摩擦低いのでよく滑ります。弾性力もダイス、お椀、どちらも約0.5あるのでよく跳ねますね。
まあ物理なんて記憶の彼方。それっぽい動きになるまで値を動かしまくったわけです。
お椀も同様にガチャガチャいじっていい感じになりました。
論理的な人たちに後ろから刺されそうですね!
しかし初めから思っていたこと。物理演算だから何回やっても同じ結果になるやろがい!!!
あえて目をそらしていましたが向き合う時です。というか今の状態じゃサイコロ振った感が出ません。
さあてまずはカメラを上空に設置して、サイコロを投下する座標を決められるようにしよう。
そしてそこそこの初速と、ランダムな回転を加えながら落とそう。
まあスクリプトを作成するわけだけど、もちろんGPT氏に頼みます。
using UnityEngine;
public class DiceDropManager : MonoBehaviour
{
public GameObject dicePrefab; // サイコロのプレハブ
public Transform dropHeightRef; // 高さの基準点(空中のTransform)
void Update()
{
if (Input.GetMouseButtonDown(0)) // 左クリック
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
Vector3 dropPos = hit.point;
dropPos.y = dropHeightRef.position.y; // 高さ固定
DropDice(dropPos);
}
}
}
void DropDice(Vector3 position)
{
GameObject dice = Instantiate(dicePrefab, position, Random.rotation);
Rigidbody rb = dice.GetComponent<Rigidbody>();
rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
rb.angularVelocity = new Vector3(Random.Range(10f, 30f), Random.Range(10f, 30f), Random.Range(10f, 30f));
}
}
わぁすごい。
レイキャストってのが間にあるけど、これでヒット位置をわりだしているっぽい?
GameObject dice = Instantiate(dicePrefab, position, Random.rotation);
この部分でプレハブからサイコロ生成して、加えてランダムで角度決めてますね。多分。
コンマ区切りの1行で書けるのはなんか意外という感想。
そしてチンチロといえばダイスが3つ必要だから、それもお願いした。
using UnityEngine;
public class DiceDropManager : MonoBehaviour {
public GameObject Cube; // サイコロのプレハブ
public Transform Owan; // 高さの基準点(椀の中心とか)
public float spawnSpread = 0.3f; // サイコロのばらけ幅
void Update() {
if (Input.GetMouseButtonDown(0)) { // 左クリック
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit)) {
Vector3 basePos = hit.point;
basePos.y = Owan.position.y + 4; // 高さ固定
DropMultipleDice(basePos);
}
}
}
void DropMultipleDice(Vector3 basePos) {
for (int i = 0; i < 3; i++) {
Vector3 offset = new Vector3(
Random.Range(-spawnSpread, spawnSpread),
0,
Random.Range(-spawnSpread, spawnSpread)
);
Vector3 spawnPos = basePos + offset;
GameObject dice = Instantiate(Cube, spawnPos, Random.rotation);
Rigidbody rb = dice.GetComponent<Rigidbody>();
if (rb != null) {
// 適当に回転と下向きの力を与える
rb.AddForce(Vector3.down * 10f, ForceMode.Impulse);
rb.angularVelocity = new Vector3(
Random.Range(10f, 30f),
Random.Range(10f, 30f),
Random.Range(10f, 30f)
);
}
}
}
}
ループで生成のところを3回回すだけかと思いきや回転と下向きの力もわかりやすくなって戻ってきた。すげえ。ちなみに中身全部理解できてない。
高さとかばらけの値は自分で調節しました。
うぉーすげえいい感じにダイスが3つ!!
目なし、弱い。
めっちゃやったけど結局ピンゾロは出ていません。
ションベン率が高すぎる問題
チンチロにおけるションベンとは、お椀からサイコロがはみ出ること、無条件で負けになってしまいます。そんなものがポンポン出てたらたまったもんじゃねーわ!!
ということでGPT氏と相談しながら最終的に「クリック位置とお椀の中心との距離の中央値」を基準に投下するように修正しました。(ついでに高さも調整してた)
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit)) {
Vector3 basePos = hit.point;
basePos.y = Owan.position.y + 4; // 高さ固定
DropMultipleDice(basePos);
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
Vector3 basePos = Vector3.Lerp(hit.point, Owan.position, 0.3f);
basePos.y = Owan.position.y + 3.3f; // 高さは固定(茶碗の上)
DropMultipleDice(basePos);
}
これにて、いい感じにダイスを振ることに成功!
いやあ、長かったですよ。まあ2か月前の話なんですけど、そしてダイスを振ったら次やること、出目の取得ですね。
これがとんでもなく強敵で、修正の仕方もわからなくて、というかそもそも間違えている気がして...
という話はまた次回。なぜかって?挫折してるからだよ!!2か月!!
いつ解決できるかもわからない、次には解決してるかもしれないし、挫折理由だけで終わるかもしれない。
すべては今日明日の自分の頑張り次第です。
ここまで読んでくださった方、ありがとうございます。
ではまた。