質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

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

Unity

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

Q&A

解決済

2回答

2027閲覧

Unity 装備にランダムオプションを複数つけたい

morikawa0208

総合スコア27

C#

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

Unity

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

0グッド

0クリップ

投稿2022/08/03 06:25

編集2022/08/16 23:15

前提

Unityでハクスラを作成中です。
ランダムオプションの付け方が分からず、考えてるところです。
ランダムオプションは、HP+〇〇、攻撃力+〇%、攻撃範囲UP(スケール拡大)など様々な形を考えており、
追加する値も1~100など範囲から抽選される形にしたいです。
最初は、装備生成時に処理内容の固有IDを装備オブジェクトに値保管して、装備時に実行すればいいかなと思ってましたが、
追加する値を保管する場所が無いなと気づき、どうするか詰まってしまいました。

実現したいこと

敵を倒す→プレハブから装備生成→そのままcloneを保持してる(実装済み)
装備ドロップ時に+0~+10をRandomでつける(実装済み)
+の数だけ、ランダムオプションを追加したい(未解決)

試したこと

・装備側にオプションからのSTR+、INT+など箱を作って合計をぶち込む
→UI上の詳細画面では個別に表示したいため断念
(1.STR+10、2.STR+15、3.INT+10なら、詳細画面は3個表示したいため別で保管したい)
・装備に全てのオプション(STR、INTや攻撃力、防御力など30個ほど)の箱を作って、値を全部保管する
→+10などで10個付ける際に、順番に保管できない?

何か検索するキーワードでもよいので教えていただけると助かります・・・
よろしくお願いいたします。

20220806追記 その後と別の問題

頂いた回答を基にもう1度考え、頂いた内容は上手く理解できず別の方法で進めました。
自分でも違うだろうと感じながら、ほかに思いつかず進めてますので、
進めている部分でもアドバイスがあれば教えていただけると幸いです。

【進めている部分↓】
・オプションごとにScript作成(STR+、INT+)→空Objectにアタッチしてプレハブ化。
Scriptには、ステータス反映用の値(int STRvalue)と装備画面表示用のテキスト(string STRtext)の2つが入ってます。
Startで値の決定とテキストへの反映。後々、装備時にステータス反映メソッドも追記予定。
・装備Objectのプレハブ毎にランダムオプションscriptをアタッチ。
ランダムオプションScriptにはランダムオプションListがあり、そのListに上のランダムオプションのプレハブを入れておく。
(装備1個ずつしないといけないので絶対違うと思いつつ、ほかの兼ね合いもあり一旦これで進めています…)
・装備Object生成時に+の数だけ子Objectとして、上のランダムオプションListからランダムに生成→本体の装備Objectのリストにまとめて追加。

【今の詰まりポイント】
装備画面にオプション1の効果、オプション2の効果~を表示させようと思い、
ListからRandomOptionList[0]などでObject取得、STRtextをGetCompornentしようと思いました。
が、リストの1番目に来るオプションがランダムなため、GetCompornent<【この部分】>が指定できず、STRtextを持ってこられません。
リストから取得したObject.nameはDebug.Logで確認できましたので、あとは文章をどうにか持ってこられれば…というところです。

そもそもランダムオプションを1つのScriptにまとめようと思いましたが、classをListに保管する方法や、同じScript内から別の処理を行う(STRなのかINTなのか)方法が思いつかなかったので断念しています。

やはりハクスラの肝となる部分なので、どうにか実装したいと考えております。
何卒よろしくお願いいたします。。。

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

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

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

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

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

guest

回答2

0

ベストアンサー

「ランダムオプション」を表すクラス(または構造体)を作り、
装備は「ランダムオプション」をList (など) で保持する。


デフォルトでは何もしないランダムオプションの抽象基底クラスを用意します。StatusOptionとしましょうか
(影響を与えるものなのでEffectのほうが名前としては良さそうですが、Optionで通します。)

装備クラスはこのクラスのリストを持ちます。optionsとしましょうか。
装備クラス(かなにか)はランダムオプションの効果が必要になるたびに、optionsの中身を順番に見て、各オプションのその状況に応じたメソッドを呼びます。
例えば「攻撃のときにOnAttack(...)を呼ぶ」、「説明文がほしければExplanatoryTextプロパティを参照する」のようにです。

装備クラスのインスタンスを生成する際に、
望む種類、個数のランダムオプションを生成してリストに格納、何らかの形で装備クラスのインスタンスに渡します。

ぶっちゃけUnityはよく知らないので純粋なC#で 説明用の コードを書きました

C#

1using System.Collections.Generic; 2 3public abstract class StatusOption{ 4 public virtual string ExplanatoryText{get{return "";}} 5 public virtual void OnAttack(/* 引数に何を取るかは私が決められることではないので頑張って設計してください */){ 6 // なにもしない 7 } 8 public virtual void OnDamaged(/* 引数に何を取るかは私が決められることではないので頑張って設計してください */){ 9 // なにもしない 10 } 11} 12 13public class StrOption : StatusOption{ 14 private int value; 15 public StrOption(int value){ 16 this.value = value; 17 } 18 public override string ExplanatoryText{get{return "攻撃力+" + value.ToString();}} 19 public override void OnAttack(/* 引数に何を取るかは私が決められることではないので頑張って設計してください */){ 20 // 攻撃力を上げる処理 21 } 22} 23 24public class DefenceOption : StatusOption{ 25 private int value; 26 public DefenceOption(int value){ 27 this.value = value; 28 } 29 public override string ExplanatoryText{get{return "防御力+" + value.ToString();}} 30 public override void OnDamaged(/* 引数に何を取るかは私が決められることではないので頑張って設計してください */){ 31 // 防御力を上げる処理 32 } 33} 34 35 36 37public class Hello{ 38 public static void Main(){ 39 // Your code here! 40 41 var options = new List<StatusOption>{new StrOption(1), new DefenceOption(2)}; 42 43 44 foreach(var op in options){ 45 System.Console.WriteLine(op.ExplanatoryText); 46 } 47 } 48}

投稿2022/08/03 07:23

編集2022/08/09 05:42
ozwk

総合スコア13512

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

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

morikawa0208

2022/08/03 08:11

ご回答ありがとうございます! なるほど・・・クラスをListに入れられることを知りませんでした・・・ ちょっと今出先で試せないので、また夜に試してみます!
morikawa0208

2022/08/05 19:41

ご回答いただいてから返答が遅くなり申し訳ございません。 自分がうまく理解できず、別の方法で一応質問時点からは少し進みました… (違うだろうと感じながら…) その後でまた詰まった点があり、質問文に追記しておりますので、 もし宜しければ見ていただけると助かります… 何卒よろしくお願いいたします。
morikawa0208

2022/08/16 14:07

お盆休みでお返事が遅くなり申し訳ありません… 教えていただいた内容そのままではありませんが、 ヒントにさせていただいて、何とか現時点での実装はできました! 自分の書いているコードがベターではないというのは明確だったため、 質問内容にコードを記載しておりませんでしたが、 そのうえで追記までご回答いただいて大変助かりました。 出来るだけ自力でと考えて調べながら進めておりますが、 もしまた何かございましたらまたお力を貸していただければと思います。 本当にありがとうございました!
guest

0

雑なコードですが、参考になればと。

Test1スクリプトを作成してコピペ、空のオブジェクトにアタッチしてみて下さい。
一般的にはファイルとクラスで1つづつにするかと思いますが、変にややこしくなるかと思いましたので一つのスクリプトとしています。

Unity

1using System.Collections.Generic; 2using UnityEngine; 3using System.Linq; 4namespace TestScript 5{ 6 public class Test1 : MonoBehaviour 7 { 8 [SerializeField]public List<Item> items = new(); 9 private void Start() 10 { 11 var player = GameObject.CreatePrimitive(PrimitiveType.Cube); 12 CreateEnemy(); 13 } 14 public void CreateEnemy() 15 { 16 var enemy = GameObject.CreatePrimitive(PrimitiveType.Sphere); 17 enemy.transform.position = new Vector3(5.0f, 0, 0); 18 enemy.AddComponent<Rigidbody>().useGravity = false; 19 enemy.AddComponent<Enemy>(); 20 } 21 } 22 23 public class Enemy : MonoBehaviour 24 { 25 private void Update() 26 => transform.Translate(Vector3.left * Time.deltaTime); 27 28 private void OnCollisionEnter(Collision collision) 29 { 30 var test1 = FindObjectOfType<Test1>(); 31 test1.items.Add(ItemFactory.Create()); 32 Debug.Log("ゲットしたアイテム : " + string.Join(" : ", test1.items[test1.items.Count - 1].Effects.Select(_ => _.Text))); 33 Destroy(gameObject); 34 test1.CreateEnemy(); 35 } 36 } 37 38 public static class ItemFactory 39 { 40 public static Item Create() 41 => new Item("アイテムの名前", CreateEffects()); 42 43 public static List<ItemEffect> CreateEffects() 44 { 45 List<ItemEffect> effects = new(); 46 for (int i = 0; i < Random.Range(0, 4) + 1; i++) 47 { 48 effects.Add(new ItemEffect("ランダムオプション", Random.Range(1, 10), (ItemEffect.EffectType)Random.Range(0, 2))); 49 } 50 return effects; 51 } 52 } 53 54 [System.Serializable] 55 public class Item 56 { 57 [SerializeField] 58 string name; 59 public string Name => name; 60 [SerializeField] 61 List<ItemEffect> effects = new(); 62 public IReadOnlyList<ItemEffect> Effects => effects; 63 public Item(string name, List<ItemEffect> effects = null) => (this.name, this.effects) = (name, effects); 64 } 65 66 [System.Serializable] 67 public class ItemEffect 68 { 69 public enum EffectType 70 { 71 STR = 0, 72 DEF, 73 } 74 75 [SerializeField] 76 string name; 77 public string Name => name; 78 [SerializeField] 79 string text; 80 public string Text => text; 81 [SerializeField] 82 int value; 83 public int Value => value; 84 [SerializeField] 85 EffectType type; 86 public EffectType Type => type; 87 public ItemEffect(string name, int value, EffectType type) => (this.name, this.text, this.value, this.type) = (name, $"{type.ToString()} + {value}", value, type); 88 } 89}

空のオブジェクトに入れたTest1(Script)インスペクター上でitemsの項目を展開すればどのように情報が管理されるかが見えます。
Debug.Logはテキスト表示する場合の加工とか?

追記の方法でいくとInterfaceを利用すれば可能ではないかと思います
ですが、説明も面倒ですし質問者様のコードもない状態では回答を得るのは難しいかと思います。

投稿2022/08/15 18:35

Morimori

総合スコア10

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

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

morikawa0208

2022/08/16 14:15

ご回答ありがとうございます! 今回の質問内容は何とか実装できましたが、 ほかで応用できないか頂いた内容をちゃんと確認させていただきます! 自分のコードがおかしいのは明らかだったので、 甘える形での質問でしたが、今後はちゃんとコードも載せて質問させていただきます。 interfaceも言葉を理解できていなかったので勉強になりました。 改めてご回答ありがとうございましたm(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問