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

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

詳細はこちら
C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Unity

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

Q&A

解決済

1回答

2265閲覧

Unity:戦略シミュレーションゲームで、攻撃範囲にいる敵を検索→攻撃対象選択→攻撃を実行したい

zenobread

総合スコア44

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Unity

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

1グッド

0クリップ

投稿2019/09/18 07:36

やりたいこと

戦略シミュレーションゲームでよくある
「敵対象の近くまで移動→攻撃範囲内にいる敵を検索→その中から攻撃対象を選択→攻撃実行」
以上を実装したいと考えています。
現在、移動と検索までは実装することが出来ました。
問題は「攻撃範囲にいる敵を選択しその敵に対し攻撃行動を実行」の部分が全く分かりません。

特に、全てマスのクリックで完結させたいと考えているので、「配列内の攻撃対象をボタンで選択」ではないやり方を模索しております。

以下は該当スクリプトです。

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.Tilemaps; 6 7public class Test_player_tile : MonoBehaviour 8{ 9 [SerializeField] private Tilemap atk_area_color;//移動と攻撃タイルを設置するマップ 10 [SerializeField] private Tilemap map;//キャラクターが移動するマップ 11 [SerializeField] private Game_Manager manager; 12 [SerializeField] private Test_tilemap tile; 13 [SerializeField] private Log_Manager logsc; 14 [SerializeField] private Tile atk_tile;//移動範囲タイル 15 [SerializeField] private Tile gren_tile;//攻撃範囲タイル 16 17 public bool mouse_onoff; 18 public int atk = 50; 19 public int hp = 100; 20 public Vector3Int position; 21 22 private bool atk_bool=true; 23 private bool behave_bool = true; 24 private bool ui_bool = false; 25 private bool calic_sign; 26 private int atk_area_int = 2;//移動範囲 27 private int behave_int = 1;//攻撃範囲 28 private int a_i, b_i, c, d, area_length, gth; 29 private GameObject[] enemys; 30 private Vector3Int atk_area; 31 public Status Ch_Status; 32 Gridman[] grids; 33 34 public enum Status//オブジェクトの状態 35 { 36 Waiting, 37 Move, 38 Wait_for_Behave, 39 Behaving, 40 False, 41 } 42 // Start is called before the first frame update 43 44 public struct Gridman 45 { 46 public int x, y; 47 } 48 public struct Enemy 49 { 50 public Vector3 pos; 51 public GameObject name; 52 } 53 54 void Start() 55 { 56 enemys = GameObject.FindGameObjectsWithTag("Unit"); 57 } 58 59 public void Caliculator(int ans,int x,int y) 60 { 61 //移動と攻撃範囲を計算 62 ans *= ans; 63 var cal = (x - position.x) * (x - position.x) + (y - position.y) * (y - position.y); 64 if (ans >= cal) 65 { 66 ++gth; 67 Array.Resize(ref grids, gth); 68 grids[gth-1] = new Gridman() { x = x, y = y }; 69 //Debug.Log("ans:"+ans+"\tcal:"+cal+"\tgrids_number:"+gth+"\tgrids_x:"+grids[gth-1].x+"\tgrids_y:"+grids[gth-1].y); 70 } 71 else 72 { 73 //Debug.Log("error\t" + "ans:" + ans + "\tcal:" + cal + "\tx:" + x + "\ty:" + y); 74 } 75 } 76 77 // Update is called once per frame 78 void Update() 79 { 80 //移動タイルを設置した後「Move」状態となり、マウス座標と一致した移動となる 81 if (mouse_onoff == false) this.transform.position = new Vector3(map.WorldToCell(this.transform.position).x + 0.5f, map.WorldToCell(this.transform.position).y + 0.5f, -1f); 82 if (this.Ch_Status==Status.Move) this.transform.position = new Vector3(manager.mouse_position.x + 0.5f, manager.mouse_position.y + 0.5f, -1f); 83 } 84 85 public void Cursol_1(ref bool mouse) 86 { 87 if (this.Ch_Status == Status.Waiting) 88 { 89 //移動計算。このオブジェクトから見て周囲2マス程度を移動範囲とする 90 this.Ch_Status = Status.Move; 91 Debug.Log(this.Ch_Status); 92 gth = 0; 93 area_length = (2 * atk_area_int + 1) * (2 * atk_area_int + 1);//9(n=1),25(n=2),49(n=3),81(n=4) (int+(int+1))*(int+(int+1)) (2x+1)^2 94 grids = null; 95 grids = new Gridman[0]; 96 position = map.WorldToCell(this.transform.position); 97 for (var i = position.x - atk_area_int; i <= position.x + atk_area_int; i++) 98 { 99 for (var z = position.y - atk_area_int; z <= position.y + atk_area_int; z++) 100 { 101 Caliculator(atk_area_int, i, z); 102 } 103 } 104 //移動範囲にタイル設置 105 foreach (Gridman grideach in grids) 106 { 107 var tile_position = new Vector3Int(grideach.x, grideach.y, (int)atk_area_color.transform.position.z); 108 atk_area_color.SetTile(tile_position, atk_tile); 109 } 110 } 111 else if (this.Ch_Status == Status.Move) 112 { 113 //移動終了行動、マウスとともに移動し、マウスの座標に先ほど設置したタイルがなければ移動できない 114 Vector3Int mon = new Vector3Int(manager.mouse_position.x, manager.mouse_position.y, (int)atk_area_color.transform.position.z); 115 Debug.Log(mon); 116 if (atk_area_color.HasTile(atk_area_color.WorldToCell(mon)) == false) 117 { 118 this.mouse_onoff = true; 119 Debug.Log("ここにはおけません"); 120 } 121 else if (atk_area_color.HasTile(atk_area_color.WorldToCell(mon)) == true) 122 { 123 atk_area_color.ClearAllTiles(); 124 this.Ch_Status = Status.Wait_for_Behave; 125 mouse_onoff = false; 126 } 127 } 128 else if (this.Ch_Status == Status.Wait_for_Behave) 129 { 130 //攻撃範囲計算、このオブジェクトに対して上下左右1マスを範囲として設定。 131 gth = 0; 132 var x = behave_int; 133 area_length = (2 * behave_int + 1) * (2 * behave_int + 1);//9(n=1),25(n=2),49(n=3),81(n=4) (int+(int+1))*(int+(int+1)) (2x+1)^2 134 grids = null; 135 grids = new Gridman[area_length]; 136 position = map.WorldToCell(this.transform.position); 137 for (var i = position.x - behave_int; i <= position.x + behave_int; i++) 138 { 139 for (var z = position.y - behave_int; z <= position.y + behave_int; z++) 140 { 141 Caliculator(x, i, z); 142 } 143 } 144 //攻撃範囲にいる敵オブジェクト座標にタイル設置。 145 foreach (Gridman grid in grids) 146 { 147 var tile_position = new Vector3Int(grid.x, grid.y, (int)atk_area_color.transform.position.z); 148 foreach (GameObject enemy in enemys) 149 { 150 if (tile_position == map.WorldToCell(enemy.transform.position) && this.gameObject.name != enemy.name) 151 { 152 atk_area_color.SetTile(tile_position, gren_tile); 153 } 154 } 155 } 156 }//攻撃範囲に設置したタイルを削除し、もう一度タイルを設置 157 else if (this.Ch_Status == Status.Wait_for_Behave) 158 { 159 atk_area_color.ClearAllTiles(); 160 Debug.Log(this.Ch_Status); 161 } 162 } 163}

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.Tilemaps; 5 6public class Game_Manager : MonoBehaviour 7{ 8 9 [SerializeField] private Test_tilemap testmap; 10 [SerializeField] private GameObject player; 11 [SerializeField] private Test_player_tile player_script; 12 [SerializeField] private Tilemap map; 13 [SerializeField] private Tilemap atk_color_map; 14 15 public Vector3Int mouse_position; 16 17 private Test_player_tile test; 18 private Vector3 position; 19 private Vector3 screenToWorldPointPosition; 20 21 bool mouse_having; 22 GameObject clickobject; 23 Test_player_tile a; 24 // Start is called before the first frame update 25 void Start() 26 { 27 mouse_having = false; 28 test = null; 29 } 30 31 // Update is called once per frame 32 void Update() 33 { 34 position = Input.mousePosition; 35 position.z = 10f; 36 screenToWorldPointPosition = Camera.main.ScreenToWorldPoint(position); 37 mouse_position = testmap.ClickedAction(screenToWorldPointPosition); 38 Ray ray = Camera.main.ScreenPointToRay(position); 39 RaycastHit2D hit2d = Physics2D.Raycast((Vector2)ray.origin, (Vector2)ray.direction, 10f); 40 41 if (Input.GetMouseButtonDown(0)&&mouse_having==false) 42 { 43 Debug.Log(mouse_position); 44 clickobject = null; 45 if (hit2d) 46 { 47 clickobject = hit2d.transform.gameObject; 48 //クリックで移動するオブジェクトを選択 49 a = clickobject.GetComponent<Test_player_tile>(); 50 if (clickobject.transform.tag=="Unit"&&mouse_having==false) 51 { 52 Debug.Log(a.Ch_Status); 53 a.Cursol_1(ref mouse_having); 54 }else 55 { 56 Debug.Log("エラー"); 57 } 58 } 59 } 60 } 61}
hyubyu-n1👍を押しています

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

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

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

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

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

izmktr

2019/09/18 09:01

具体的に何がわからないのでしょうか 普通、この手のゲームは自ユニット選択→敵ユニット選択で、勝手に敵のそばに移動し攻撃すると思います 移動可能マスと攻撃可能マスの洗い出しが済んでいれば、敵ユニットを選択した時点で攻撃可能かはわかりますし、 敵のマスから攻撃射程の範囲で移動可能なマスが移動するべきマスになります
zenobread

2019/09/18 10:07

分かりにくい書き方で申し訳ありません。 私が開発しているスクリプトでは 「自ユニット選択」→「敵ユニット選択」→「移動」→「攻撃」 ではなく 「自ユニット選択」→「移動」→「敵ユニット選択」→「攻撃」 となっております。 例えば移動した先で、周囲の敵情報を検索したのち、仮に 「敵ユニット1」「敵ユニット2」「敵ユニット3」 が攻撃可能範囲にいるとします。 そのなかで1か2か3か選んで攻撃するとした場合、どうやってプレイヤーに攻撃対象を選択させることが出来るか、といったところです。 例えば現在マウスで自ユニットをクリックすることで 移動範囲・攻撃範囲を表示させているのですが、 攻撃範囲を表示させている状態で、敵ユニットをクリックし攻撃対象とする ということについてどうすれば実装できるか分からない状態です。
izmktr

2019/09/18 18:57

自ユニットや移動地点のクリックが出来るのに、敵ユニットのクリックが出来ない、というのがいまいちよくわかりません クリックした位置からどのユニットやマス目になるのかの変換ができていれば、敵ユニットに応用するのはさほど困難ではないはずです その部分は他の誰かが制作していて、自分ではその辺の仕組みを理解していない、というケースなのでしょうか?
zenobread

2019/09/18 23:52

大変失礼しました。自己解決することが出来ました。 このファイルは 「GameManagerが自ユニットをクリックすることで、GameManagerのclickobjectに自ユニットが選択され、そのユニットのCursol_1関数を呼び出し、自ユニットのenum StatusがWaitingからMoveとなり自ユニットはマウスの動きに追従する。 その状態だとマウスカーソルの座標と自ユニットの座標が共通するので、もう一度クリックすると自動的に自ユニットをクリックすることとなり、自ユニットのCursol_1関数を呼び出し移動完了となる。」 という動きを取っています。 ですので敵ユニットをクリックすると、自ユニットの関数を呼び出すことが出来ないのでダメージ計算をどうすればよいか分かりませんでした。 そのため正確には 「敵ユニットをクリックしたとき、自ユニットの関数を呼び出すにはどうすればよいか」 でした。 自己解決として、攻撃範囲にいる敵ユニットを配列に入れ、「GameMnagerのclickobjectに配列に入っている敵ユニットが代入された場合Debug.Logで確認する」ということをUpdate関数で行いました。 ご返事していただきありがとうございます。
guest

回答1

0

ベストアンサー

「質問への追記・修正の依頼」の内容を踏まえての回答です。

「自ユニットのCursol_1関数を呼び出し移動完了」のタイミングでGame_Managerに既に用意してある変数のprivate Test_player_tile test;へその選択していた自キャラのクラスを渡して敵キャラ選択後はそれを参照すれば良いかと思います。

投稿2019/09/19 09:01

編集2019/09/19 09:24
Hawn

総合スコア1222

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

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

zenobread

2019/09/22 08:00

ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問