🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

1604閲覧

Unity ゲームの難易度を徐々に難しくする方法。C#

rrr66

総合スコア16

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/09/26 18:43

unityでミニオンラッシュのような、キャラクターが自動で走行するゲームを作っています。
このゲームはひたすら敵をよけ続けて走行距離を伸ばしていくゲームです。
走行するステージはあらかじめ作成したいくつかのプレハブをランダムで出現させています。
しかし、今の私のスクリプトでは、常にステージの難易度が一定です。
ステージの難易度を走行距離が進むにつれて難しくなるようにしたいです。
具体的には、0m~1000mの間はレベル1ステージプレハブからランダムに選んで、ステージを作成。
1001m~2000mの間はレベル2ステージプレハブからランダムに選んで、ステージを作成。
このようなスクリプトはどのようにしたらできますか?
もし少しでもヒントになるようなことを知っている方がいましたら教えてください。(_ _)

ステージをランダムに出現させるスクリプト

c#

1using UnityEngine; 2using System.Collections; 3using System.Collections.Generic; 4 5public class StageGenerator : MonoBehaviour 6{ 7 const int StageTipSize = 100; 8 9 int currentTipIndex; 10 11 public Transform character; 12 public GameObject[] stageTips; 13 public int startTipIndex; 14 public int preInstantiate; 15 public List<GameObject> generatedStageList = new List<GameObject>(); 16 17 void Start () 18 { 19 currentTipIndex = startTipIndex - 1; 20 UpdateStage(preInstantiate); 21 } 22 23 void Update () 24 { 25 // キャラクターの位置から現在のステージチップのインデックスを計算 26 int charaPositionIndex = (int)(character.position.z / StageTipSize); 27 28 // 次のステージチップに入ったらステージの更新処理をおこなう 29 if (charaPositionIndex + preInstantiate > currentTipIndex) 30 { 31 UpdateStage(charaPositionIndex + preInstantiate); 32 } 33 } 34 35 // 指定のIndexまでのステージチップを生成して、管理化に置く 36 void UpdateStage (int toTipIndex) 37 { 38 if(toTipIndex <= currentTipIndex) return; 39 40 // 指定のステージチップまでを作成 41 for (int i = currentTipIndex + 1; i <= toTipIndex; i++) 42 { 43 GameObject stageObject = GenerateStage(i); 44 45 // 生成したステージチップを管理リストに追加し 46 generatedStageList.Add(stageObject); 47 } 48 49 // ステージ保持上限内になるまで古いステージを削除 50 while (generatedStageList.Count > preInstantiate + 2) DestroyOldestStage(); 51 52 currentTipIndex = toTipIndex; 53 } 54 55 // 指定のインデックス位置にStageオブジェクトをランダムに生成 56 GameObject GenerateStage (int tipIndex) 57 { 58 int nextStageTip = Random.Range(0, stageTips.Length); 59 60 GameObject stageObject = (GameObject)Instantiate( 61 stageTips[nextStageTip], 62 new Vector3(0, 0, tipIndex * StageTipSize), 63 Quaternion.identity 64 ); 65 66 return stageObject; 67 } 68 69 // 一番古いステージを削除 70 void DestroyOldestStage () 71 { 72 GameObject oldStage = generatedStageList[0]; 73 generatedStageList.RemoveAt(0); 74 Destroy(oldStage); 75 } 76}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

横から失礼します。
◆ プレハブ管理について
現在は**「 GameObject[] stageTips; 」**な感じで一次元で管理してる様ですが、
Lvごとに管理する二次元配列で管理すれば取得する時に分かりやすいです。
**「 public List<GameObject[]> stageTips; 」**こんな感じでどうですか?
個人的には「List<List<GameObject>>」の方が、追加・削除がやりやすいと思います。
▼ GenerateStage 関数を、2次元配列に対応させてみました

C#

1 // 現在のLv ※ 0~1000mで「0」、1000~2000mで「1」が入るイメージ! 2 public int levei = 0; 3 // Lvごとにプレハブを配列で持つ ※List<List<GameObject>>の方がステージ追加しやすいと思う 4 public List<GameObject[]> stageTips; 5 6  // 一部だけ変更しています 7 GameObject GenerateStage(int tipIndex) 8 { 9 GameObject[] stageTips_Get = stageTips[levei]; 10 int nextStageTip = Random.Range(0, stageTips_Get.Length); 11 12 GameObject stageObject = (GameObject)Instantiate( 13 stageTips_Get[nextStageTip], 14 new Vector3(0, 0, tipIndex * StageTipSize), 15 Quaternion.identity 16 ); 17 18 return stageObject; 19 }

◆走行距離ごとにレベル(Lv)を上げていく方法
**「 走行距離/1000 = 現在のLv 」で行けると思います。
もし、走行距離を変数として持っていない場合は、
プレハブを作成した回数を記憶して、10個ごとにLvを1上げてはいかがでしょうか?
「 const int StageTipSize = 100; 」**これを見る限り、1つのプレハブ=100mと仮定して話します。
▼ UpdateStage 関数にレベル更新処理を追記

C#

1 // プレファブを作成した個数 2 public int PrefabMakeCnt = 0; 3 // 現在のLv ※ 0~1000mで「0」、1000~2000mで「1」が入るイメージ! 4 public int levei = 0; 5 6 // 指定のIndexまでのステージチップを生成して、管理化に置く 7 void UpdateStage (int toTipIndex) 8 { 9 // レベル変数更新 10 PrefabMakeCnt++; // ここで加算すれば、プレハブを作成した数になる 11 if (PrefabMakeCnt%10==0) 12 { 13 levei++; 14 PrefabMakeCnt = 0;// 走行距離を記録するなら初期化しなくてもいい! 15 } 16 17 if(toTipIndex <= currentTipIndex) return; 18 19 // 指定のステージチップまでを作成 20 for (int i = currentTipIndex + 1; i <= toTipIndex; i++) 21 { 22 GameObject stageObject = GenerateStage(i); 23 24 // 生成したステージチップを管理リストに追加し 25 generatedStageList.Add(stageObject); 26 } 27 28 // ステージ保持上限内になるまで古いステージを削除 29 while (generatedStageList.Count > preInstantiate + 2) DestroyOldestStage(); 30 31 currentTipIndex = toTipIndex; 32 }

※あくまで、走行距離を記録していない場合に使ってみてください

以上で質問内容の処理はできると思います。

投稿2019/09/27 06:53

編集2019/09/27 07:02
Youbun

総合スコア125

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Unity の仕様ついては分からないので本当にただのアイデアと局所的なコードだけですが、以下の2つが思いついたので置いておきます。

  1. stageTips に全レベルのプレハブを保持。ただし、各レベル同数のプレハブを保持している必要がある。
  2. stageTips を2次元ジャグ配列 として全レベルのプレハブを保持。

(stageTips というのがそのプレハブの配列ということですよね?)

1つ目の方法ですが。
レベルごとに同数のプレハブ(例えばLv.1用が10個なのだとしたら、Lv.2用もLv.3用もちょうど10個ずつ)を保持していることが前提として、GenerateStage メソッド内でこのような生成方法をとると良いと思います。

int level = Math.Max(Math.Ceiling(dist / 1000), 1); int nextStageTip = Random.Range((level-1)*stageCntPerLevel, level*stageCntPerLevel);

Ceiling というのは切り上げの関数ですが、これをすることで 1000m ごとに Lv. 1 ずつ上昇させることができます。
stageCntPerLevel は各レベルのプレハブの個数を保持している変数で、これは何度も言っていますが各レベルのプレハブは個数が等しい必要があります
stageCntPerLevel を 10 と仮定すると、Lv. 1 のとき [0, 10), Lv. 2 のとき [10, 20)... と、レベルが上がるごとに 10個 ずつランダムにプレハブを選ぶようにすることができます。
ちなみに dist は走行距離ですが、開始地点の座標を記録しておいて、進行方向の座標軸だけの差分を取ると良い気がします。
また、0m のときだけ Lv. 0 になってしまうことを防ぐため、結果が 1 より小さい場合には最大値関数によって 1 に補正されます。

2つ目の方法ですが、stageTips へのプレハブの格納方法が分からないので、もしかすると不可能かもしれません。
リンクを貼ったので見ていただければ分かると思いますが、ジャグ配列は行ごとに要素数を指定できる代わりに、行ごとに1次元配列を宣言する必要があります。

GameObject[][] stageTips = new GameObject[10][]; stageTips[0] = new GameObject[10]; stageTips[1] = new GameObject[8]; ...

もしジャグ配列でも問題なくプレハブを保持できるのであれば、各レベル同じ個数のプレハブを用意する必要がないので楽です。

int level = Math.Max(Math.Ceiling(dist / 1000), 1); int nextStageTip = Random.Range(0, stageTips[level-1].Length); GameObject stageObject = (GameObject)Instantiate( stageTips[level-1][nextStageTip], new Vector3(0, 0, tipIndex * StageTipSize), Quaternion.identity );

ただ、この 1, 2 の方法はどちらも、想定していた走行距離より長く走行されると、OutOfRangeException が発生して落ちます。
(Lv. 10 のプレハブまでしか用意していなくて 10001m まで走行されたとき、Lv. 11 を参照しようとして・・・)
走行距離を計算するときに、最小値関数を使って想定している最大の走行距離に補正することがもっとも良いと思いますが、ここはゲームの仕様の問題だと思いますので、質問者様の思うように・・・。
一応アイデアですが、

int dist = Math.Min(10000, currentPos.X - startPos.X);

のようにすれば、走行距離が 10000m 以下の場合そのままになりますが、10000m を超過すると 10000m に補正されますので、Lv. 10 のまま止まって安全です。
1 の方法であれば、

int dist = Math.Min(1000 * stageTips.Length / stageCntPerLevel, currentPos.X - startPos.X);

とすれば、プレハブを追加しても stageCntPerLevel の更新だけで済みます。
2 の方法であれば、

int dist = Math.Min(1000 * stageTips.Length, currentPos.X - startPos.X);

で十分ですね。

投稿2019/09/26 21:37

編集2019/09/26 21:41
mystasly48

総合スコア25

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問