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

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

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

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

Q&A

解決済

1回答

1341閲覧

魔法の修得と変更方法

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

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

1グッド

2クリップ

投稿2020/03/19 01:40

現状

魔法の書に触れると魔法修得リストに追加、ボタン押すと切り替え
モンスター側タグによってダメージ変更

実現したいこと

現状だと魔法が増えると目的の魔法を使うために何回も押さないといけないので魔法セット画面でキャンバスのボタンを押すことで魔法を3つほどセットしたいと思っているのですがボタン押した時に3つまでをどういう風にリストに追加していけばいいのか分からずに進まなくなってしまいました
モンスター側もこのままタグで管理するよりかいい方法があるのではないかなと迷ってしまっています
現状でも動作は問題ないのですがきれいにまとめれるようになりたいので参考程度でいいので考え方などを教えて頂きたいなと思っています

コード

unity

1プレイヤーコード 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.UI; 6 7public class Player : MonoBehaviour 8{ 9 // 10 public float moveSpeed; 11 private Vector3 velocity; 12 public Joystick joystick; 13 public Animator animator; 14 public Image Aboid; 15 public float avoidtime = 5; 16 public float invincible = 2; 17 public float deltainvincible = 0; 18 19 // 20 public float span = 2; 21 public float delta = 0; 22/////////////////////魔法部分///////////////////////////// 23 private GameObject Magic; 24 private GameObject nearObj; 25 public List<string> magic = new List<string>(); 26 public int i; 27////////////////////////////////////////////////////// 28 29 // 30 int maxHp = 100; 31 int currentHp; 32 int maxMana = 100; 33 int currentMana; 34 public Slider hpslider; 35 public Slider manaslider; 36 37 void Start() 38 { 39 animator = this.gameObject.GetComponent<Animator>();// 40/////////////////////魔法部分///////////////////////////// 41 magic.Add("Magic/NomalBall"); 42 i = 0; 43 Magic = (GameObject)Resources.Load(magic[i]);// 44///////////////////////////////////////////////////////// 45 hpslider.value = 1; 46 currentHp = maxHp; 47 manaslider.value = 1; 48 currentMana = maxMana; 49 } 50 51 void Update() 52 { 53 54 //joy stickの動き 55 Vector3 moveVector = (Vector3.right * joystick.Horizontal + Vector3.forward * joystick.Vertical); 56 57 //WASDの動き 58 velocity = Vector3.zero; 59 if (Input.GetKey(KeyCode.W)) 60 velocity.z += 1; 61 if (Input.GetKey(KeyCode.A)) 62 velocity.x -= 1; 63 if (Input.GetKey(KeyCode.S)) 64 velocity.z -= 1; 65 if (Input.GetKey(KeyCode.D)) 66 velocity.x += 1; 67 // 68 if (Input.GetKey(KeyCode.Space)) 69 OnAvoid(); 70 // 71 if (Input.GetKey(KeyCode.C)) 72 OnChangeMagic(); 73 74 if (moveVector != Vector3.zero) 75 { 76 //ここはキャラのアニメ遷移 77 animator.SetBool("Run", true); 78 79 //transformのrotationに入れる。 80 transform.rotation = Quaternion.LookRotation(moveVector); 81 82 //移動…movespeedは移動速度のパラメータ。 83 transform.Translate(moveVector * moveSpeed * Time.deltaTime, Space.World); 84 85 // 86 if (deltainvincible <= 2) 87 { 88 deltainvincible += Time.deltaTime;//時間経過 89 } 90 if (this.deltainvincible > this.invincible) 91 { 92 EndAvoid(); 93 } 94 95 if (currentMana <= 99) 96 { 97 currentMana += 1; 98 } 99 delta = 2; 100 nearObj = null; 101 } 102 else if (velocity.magnitude > 0) 103 { 104 //ここはキャラのアニメ遷移 105 animator.SetBool("Run", true); 106 107 //transformのrotationに入れる。 108 transform.rotation = Quaternion.LookRotation(velocity); 109 110 velocity = velocity.normalized * moveSpeed * Time.deltaTime; 111 112 // プレイヤーの位置(transform.position)の更新 113 transform.position += velocity; 114 115 // 116 if (deltainvincible <= 2) 117 { 118 deltainvincible += Time.deltaTime;//時間経過 119 } 120 if (this.deltainvincible > this.invincible) 121 { 122 EndAvoid(); 123 } 124 125 if (currentMana <= 99) 126 { 127 currentMana += 1; 128 } 129 delta = 2; 130 nearObj = null; 131 } 132 else if (velocity.magnitude < 0.1 || moveVector != new Vector3(1, 1, 1)) 133 { 134 //動いていない場合は走らない。 135 animator.SetBool("Run", false); 136 EndAvoid(); 137 Aboid.fillAmount += 1.0f / avoidtime * Time.deltaTime; 138 if (delta <= 2) 139 { 140 delta += Time.deltaTime;//時間経過 141 } 142/////////////////////魔法部分///////////////////////////// 143 Magic = (GameObject)Resources.Load(magic[i]);// 144////////////////////////////////////////////////////// 145 //最も近かったオブジェクトを取得 146 nearObj = SerchTag(gameObject, "Enemy"); 147/////////////////////魔法部分///////////////////////////// 148 if (currentMana >= 25 && this.delta > this.span && nearObj != null && i == 0) 149 { 150 NomalMagic(); 151 } 152 if (currentMana >= 40 && this.delta > this.span && nearObj != null && i == 1) 153 { 154 BallMagic(); 155 } 156 if (this.delta < this.span) 157 { 158 animator.SetTrigger("EndMagic"); 159 } 160 } 161////////////////////////////////////////////////////////// 162 manaslider.value = currentMana / (float)maxMana; 163 164 if (nearObj == null) 165 { 166 return; 167 } 168 else 169 { 170 //対象の位置の方向を向く 171 transform.LookAt(nearObj.transform); 172 } 173 } 174 175 //指定されたタグの中で最も近いものを取得 176 GameObject SerchTag(GameObject nowObj, string tagName) 177 { 178 float tmpDis = 0; //距離用一時変数 179 float nearDis = 0; //最も近いオブジェクトの距離 180 GameObject targetObj = null; //オブジェクト 181 182 //タグ指定されたオブジェクトを配列で取得する 183 foreach (GameObject obs in GameObject.FindGameObjectsWithTag(tagName)) 184 { 185 //自身と取得したオブジェクトの距離を取得 186 tmpDis = Vector3.Distance(obs.transform.position, nowObj.transform.position); 187 188 //オブジェクトの距離が近いか、距離0であればオブジェクト名を取得 189 //一時変数に距離を格納 190 if (nearDis == 0 || nearDis > tmpDis) 191 { 192 nearDis = tmpDis; 193 targetObj = obs; 194 } 195 196 } 197 //最も近かったオブジェクトを返す 198 return targetObj; 199 } 200 201 202 // 203 public void OnAvoid() 204 { 205 if (Aboid.fillAmount == 1) 206 { 207 animator.SetTrigger("Avoid"); 208 moveSpeed = 8; 209 deltainvincible = 0; 210 Aboid.fillAmount = 0; 211 } 212 } 213 public void EndAvoid() 214 { 215 animator.SetTrigger("EndAvoid"); 216 moveSpeed = 4; 217 } 218 219/////////////////////魔法変更部分///////////////////////////// 220 public void OnChangeMagic() 221 { 222 if (magic.Count < 2) 223 { 224 return; 225 } 226 if (i < magic.Count-1) 227 { 228 i += 1; 229 } 230 else if (i >= magic.Count-1) 231 { 232 i = 0; 233 } 234 } 235/////////////////////////////////////////////////////// 236 237/////////////////////魔法習得部分///////////////////////////// 238 public void OnCollisionEnter(Collision collision) 239 { 240 if (collision.gameObject.CompareTag("FireBall")) 241 { 242 magic.Add("Magic/FireBall"); 243 Destroy(collision.gameObject.transform.root.gameObject); 244 } 245 if (collision.gameObject.CompareTag("IceBall")) 246 { 247 magic.Add("Magic/IceBall"); 248 Destroy(collision.gameObject.transform.root.gameObject); 249 } 250 if (collision.gameObject.CompareTag("EathBall")) 251 { 252 magic.Add("Magic/EathBall"); 253 Destroy(collision.gameObject.transform.root.gameObject); 254 } 255 } 256////////////////////////////////////////////////////////// 257 258 public void NomalMagic() 259 { 260 Vector3 playerPos = this.gameObject.transform.position; 261 262 Instantiate(Magic, new Vector3(playerPos.x, playerPos.y + 3, playerPos.z), Quaternion.identity); 263 animator.SetTrigger("FireBall"); 264 currentMana -= 25; 265 delta = 0; 266 } 267 public void BallMagic() 268 { 269 Vector3 playerPos = this.gameObject.transform.position; 270 271 Instantiate(Magic, new Vector3(playerPos.x, playerPos.y + 3, playerPos.z), Quaternion.identity); 272 animator.SetTrigger("FireBall"); 273 currentMana -= 40; 274 delta = 0; 275 } 276}

unity

1モンスターコード 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.UI; 6 7public class TutorialMonster : MonoBehaviour 8{ 9 public Animator animator; 10 int maxHp = 100; 11 int currentHp; 12 public Slider hpslider; 13 public float destroycount; 14 15 // Start is called before the first frame update 16 void Start() 17 { 18 animator = this.gameObject.GetComponent<Animator>();// 19 hpslider.value = 1; 20 currentHp = maxHp; 21 } 22 23 // Update is called once per frame 24 void Update() 25 { 26 hpslider.value = currentHp / (float)maxHp; 27 if (currentHp <= 0) 28 { 29 animator.SetBool("Dead",true); 30 destroycount += Time.deltaTime; 31 } 32 if (destroycount >= 2) 33 { 34 Destroy(this.gameObject); 35 } 36 } 37 38 public void OnCollisionEnter(Collision collision) 39 { 40 if (collision.gameObject.CompareTag("NomalMagic")) 41 { 42 currentHp -= 25; 43 animator.SetTrigger("Damage"); 44 } 45 else 46 { 47 animator.SetTrigger("EndDamage"); 48 } 49 50 if (collision.gameObject.CompareTag("FireBall")|| collision.gameObject.CompareTag("IceBall") || collision.gameObject.CompareTag("EathBall")) 51 { 52 currentHp -= 50; 53 animator.SetTrigger("Damage"); 54 } 55 else 56 { 57 animator.SetTrigger("EndDamage"); 58 } 59 } 60 61} 62
mimi_no_naka👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

魔法セット画面でキャンバスのボタンを押すことで魔法を3つほどセットしたい

こちらに関してまずは実装する際の要素を書き出してそれを記述していくと良いです。
・クリックした魔法名は引数で渡す
・既に登録済みの魔法を選択した場合はリストから削除する
・セット数は三つまで

詳細な仕様が違っていたら申し訳ないのですがこれをコード化すると下記のようになります。

C#

1 // クリックした魔法名を引数で渡す 2 public void OnRegisterMagic(string magicName) 3 { 4 // 既に登録済みの魔法を選択した場合はリストから削除する 5 foreach (var v in magic) 6 { 7 if (v == magicName) 8 { 9 magic.Remove(v); 10 return; 11 } 12 } 13 14 // セット数は三つまで 15 if (magic.Count < 3) 16 { 17 magic.Add(magicName); 18 } 19 }

この関数をボタンイベントに設定します。
するとそこから引数を設定出来るようになるのでNomalBallのボタンであればMagic/NomalBallの様に入力して下さい。

まずは全魔法を魔法セット画面に並べてListの追加・削除をテストしてみると良いかと思います。


モンスター側もこのままタグで管理するよりかいい方法

魔法クラスを作成してそれを使って管理する方が良いです。
下記の様な変数が多数あるクラスです。

C#

1using UnityEngine; 2 3public class MagicStatus : MonoBehaviour 4{ 5 public Attribute attribute; 6 public string name; 7 public int useMana; 8 public int damage; 9} 10 11public enum Attribute 12{ 13 Normal, 14 Element 15}

Attributeのような列挙型を作成して上手く利用するとコードを簡略化できます。
NomalMagicであればNormal、FireBall,IceBall,EathBallであればElementを設定してそれを条件式に使うと現状より簡潔に書けます。

ただ利便性や使い方が判らなかったり、個人で作成している段階では別に今のままで良いと思います。

投稿2020/03/19 10:01

編集2020/03/19 11:52
Hawn

総合スコア1222

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

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

退会済みユーザー

退会済みユーザー

2020/03/19 10:17

返答ありがとうございます 明日試してみたいと思います 質問なんですが1つ目の回答のコードはplayerのスクリプト内でしょうかそれとも新しくスクリプトを作るんでしょうか。 2つ目も似たような質問なんですがどうやってノーマルとかを取得して認識させるんでしょうか 勉強不足ですみません自分でも調べてみますが時間があれば回答お願いします
Hawn

2020/03/19 10:29

1つ目の回答のコードはplayerのスクリプト内です。 List<string> magicを参照する必要があるので新しくスクリプトを作る際にはそれを考慮する必要があります。 役割毎にクラスを分けたいところですが最初は取り敢えず想定通りに動かすを目指すで良いと思います。
退会済みユーザー

退会済みユーザー

2020/03/19 10:31

そうですよね。 listの参照は難しそうなのでプレイヤー内に作ります 2つ目のも各モンスター内に作っていくということでしょうか
Hawn

2020/03/19 13:08 編集

2つ目のものはMagicStatusという名前で新しくスクリプトを作ってください。 クラス内の変数へのアクセスは通常プロパティと呼ばれるものを追加するのですが最初は全てpublicに変えて下さい(コード修正しました) これをMagicフォルダに作成しているであろう魔法PrefabにアタッチすればInspectorから値を設定出来ます。 同じように全ての魔法にアタッチして値を設定していって下さい。 値を設定したPrefabをゲーム再生中にInstantiateするとそれを持った状態でシーンに生成されます。
Hawn

2020/03/19 11:01 編集

・スクリプト内でMagicStatusクラスの変数を使う方法 TutorialMonster内のpublic void OnCollisionEnter(Collision collision)で `var magicStatus = collision.gameObject.GetComponent<MagicStatus>();`をおこないます。 その後`Debug.Log(magicStatus .damage);`で確かめて設定した値が出れば成功です。
Hawn

2020/03/19 10:59

上手くいっていれば以下の様に書き換えられる筈です。 if (collision.gameObject.CompareTag("FireBall")|| collision.gameObject.CompareTag("IceBall") || collision.gameObject.CompareTag("EathBall")) ↓ if (magicStatus .attribute == Attribute.Element)
退会済みユーザー

退会済みユーザー

2020/03/19 17:29

夜分にすみません 一つ目しか試していないですがボタンで魔法を追加できました! ここでまた質問していいのか分からないのですが2つほど詰まりました 1つ目は魔法習得した時にスクロールバーの中に魔法選択ボタンを生成する方法が調べても分からなかったのと 2つ目は i (魔法の所持している番号) で魔法を打っているため3つ目の魔法が打てない(スクリプト記述していない)ので後のことを考えるとセットされている名前によって消費するマナとかを変えれるようになりたいという質問です 2つ目の質問は教えていただいたMagicStatusをプレイヤーに応用して解決できそうなら教えて頂きたいです
退会済みユーザー

退会済みユーザー

2020/03/20 04:51

2つ目の回答でDebug.Log(magicStatus .damage);でダメージ出ました public void OnCollisionEnter(Collision collision) { var magicStatus = collision.gameObject.GetComponent<MagicStatus>(); if (magicStatus.attribute == Attribute.Normal) { currentHp -= magicStatus.damage; animator.SetTrigger("Damage"); } else { animator.SetTrigger("EndDamage"); } if (magicStatus.attribute == Attribute.Element) { currentHp -= magicStatus.damage; animator.SetTrigger("Damage"); } else { animator.SetTrigger("EndDamage"); } } これだと敵のhpが減らないんですがどうすれば良いでしょうか。
Hawn

2020/03/20 06:04 編集

>これだと敵のhpが減らないんですがどうすれば良いでしょうか。 数字が正常に取れているのならば前と処理が変わらないので敵のHPが減らないという事は無い筈です。 クラスの変数値を見直して頂ければと思います。 若しくは「currentHp -= magicStatus.damage;」の上か下にDebug.Log(magicStatus .damage);を置いてその出た数字を教えて下さい。
Hawn

2020/03/20 06:08 編集

>1つ目は魔法習得した時にスクロールバーの中に魔法選択ボタンを生成する方法が調べても分からなかったのと >2つ目は i (魔法の所持している番号) で魔法を打っているため3つ目の魔法が打てない(スクリプト記述していない)ので後のことを考えるとセットされている名前によって消費するマナとかを変えれるようになりたいという質問です この二つは新たに質問立てて頂いた方が良いです。 スクロール要素の動的生成は若干難度高いのでここだけだとちょっと伝えきれないかと思います。
退会済みユーザー

退会済みユーザー

2020/03/20 06:32

すみません変数見直したら減りました! ただ動作は問題ないのですがエラーが出てしまっていて敵を多く出すとエラーがすごいことになります NullReferenceException: Object reference not set to an instance of an object TutorialMonster.OnCollisionEnter (UnityEngine.Collision collision) (at Assets/Scripts/Tutorial/TutorialMonster.cs:41) 41は if (magicStatus.attribute == Attribute.Normal) { currentHp -= magicStatus.damage; Debug.Log(magicStatus.damage); animator.SetTrigger("Damage"); } ifの部分です
退会済みユーザー

退会済みユーザー

2020/03/20 06:35

2つの質問は少し考えて調べてからまた質問することにします! スクロール要素の自動生成は難しいとのことなので 魔法を所持していないときはボタンを暗くして押せないようにするのを考えています
Hawn

2020/03/20 07:41

>エラーがすごいこと 魔法以外の衝突判定も発生しているのでエラーが出ているかと思います。 ・魔法以外はmagicStatusがnullになるので、nullチェックを行いnullならば処理を中断させる ・Magicタグを作成し魔法全てにそれを付けてエラー箇所をそれを使ったif文内に入れる どちらか行うと良いです。
Hawn

2020/03/20 07:45

タグの方は以前の使い方とは違い魔法という大枠であれば、コードの冗長・複雑化には繋がらないのでそういった使い方は問題ありません。
退会済みユーザー

退会済みユーザー

2020/03/20 07:59

タグの方を実装させていただきました! とても優しく何度も質問に回答いただいてありがとうございます! また機会があれば関わってください!
退会済みユーザー

退会済みユーザー

2020/03/20 08:08

最後に一ついいでしょうか ボスを倒した後に魔法を魔法習得キャンバスの中にランダムに持っていない魔法の習得ボタン3を生成したいのですが簡単な方法があれば教えて頂きたいです
Hawn

2020/03/20 09:40 編集

その質問の実装項目を書き出すと下記3つがあるので順番に作って下さい。 1.ボス撃破タイミングを判別出来るようにして撃破時に2を呼び出す 2.未習得の魔法を重複無しでランダム抽選する 3.2で選ばれた魔法の習得ボタン3つを生成してUIとして配置する
Hawn

2020/03/20 09:41 編集

1はボスタグを用意してそれを使った条件式とif(currentHp <= 0 )で出来ると思います。 魔法みたいにEnemyStatusクラスを用意してやっても良いです。 2は未収得の魔法用のListを用意すると良いです。 public List<string> unLearnedMagic = new List<string>(); これにゲーム開始時全ての魔法がある状態にして習得毎にRemoveで減らしていって下さい。 そのうえで下記サイトのコードを参考にして未習得魔法を抽選する関数作って下さい。 単純に3回ループではなく未習得が2個以下の時も想定して作る必要があります。 ・重複なしでランダムに5個出力するサンプル https://tech.pjin.jp/blog/2018/02/01/unity_random-number_nonoverlap/#_11005 3は全魔法のボタンをResourcesフォルダにPrefabで作っておき、2で抽出した文字列を使って生成してやれば良いです。 魔法ボタンは最初の質問時に作成したと思うのでそれを使って良いのですが、ボタンイベントは習得の関数がおこなわれる様にする必要があります。
退会済みユーザー

退会済みユーザー

2020/03/20 10:27 編集

調べながらしてみます! 長い時間ありがとうございました 教えて頂いたスクリプトで属性相性もできそうです var magicStatus = collision.gameObject.GetComponent<MagicStatus>(); if (collision.gameObject.CompareTag("Magic")) { if (magicStatus.attribute == Attribute.Fire) { currentHp -= magicStatus.damage+20; } else if (magicStatus.attribute != Attribute.Fire) { currentHp -= magicStatus.damage; } else { } }
退会済みユーザー

退会済みユーザー

2020/03/20 09:41

ご丁寧にありがとうございます! だいぶ知らないことも知れてゲームも進みそうです! ありがとうございます
Hawn

2020/03/20 10:11

Twitterの方はプログラム関係無い経済の話しかしないので申し訳無いのですが特に親しい人は作らないようにしています。 とはいえ、エンジニアは人脈有利な局面多いので今後も積極的に知り合い増やしていって下さい。
退会済みユーザー

退会済みユーザー

2020/03/20 10:27

ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問