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

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

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

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

Q&A

解決済

1回答

1620閲覧

Unityでオブジェクトにデータを入れることでデータベース代わりにするものを改造したいです

Namineko

総合スコア6

C#

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

0グッド

0クリップ

投稿2020/04/18 06:40

編集2020/04/18 08:28

Unity初心者です。
スラスラ読める Unity C#ふりがなプログラミング』という本を読み終わって、Unityとプログラミングになれているところです。
ゲームをいきなり作るのは無謀なのではと考えて、別の本を読みながらデータベースを練習に作ろうとしています。
それでオブジェクトに情報を入れてデータベースのようなものを作れる技術本を見ながら練習していたのですが、ちょっと使いにくいので改善したいのです。

現在のデータベースもどき

まず現在のデータベースもどきを説明します。

現在私は空のオブジェクトを作り、その中にスクリプトのコンポーネントを内包してデータベース用のオブジェクトを作りました。そしてその中に次のコードを書いています。

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCharacter : MonoBehaviour { //キャラクターの名前と、HPの数値を入力できる項目を作っています [SerializeField] string[] Name;//キャラクターの名前の入力欄 [SerializeField] int[] HP;//HPの数値の入力欄 }

これでUnityの画面を開くと、[size]という項目があられるので、そこに登録したい人数分の数値を入れると入力欄が現れます。ここでは仮に2人分のデータを入力することにします。
[size]欄に2と入力すると次の画像の画面になります。
イメージ説明
これで現在のデータベースは完成です。

どういう風に改善したいか

現在のデータベースもどきだと

▼Name
キャラクター1の名前
キャラクター2の名前
▼HP
キャラクター1のHPの数値
キャラクター2のHPの数値

という風にUnityで表示されてしまい不便なので、

▼Chara1
キャラクター1の名前
キャラクター1のHPの数値
▼Chara2
キャラクター2の名前
キャラクター2のHPの数値

という感じにしたいです。

自分でやってみたこと

for文でなんとかできないかと思い、このようなコードを書いてみたのですが、エラーが出てしまって動きませんでした。

public class test1 : MonoBehaviour { [SerializeField] int Max; void Start() { for (int r = 0; r <= Max; r++) { [SerializeField] string[] Name; [SerializeField] int[] HP; } } }

出ているエラーを出します。全部で3個です。

  1. Assets\test1.cs(11,10): error CS1513: } expected
  2. Assets\test1.cs(15,5): error CS1022: Type or namespace definition, or end-of-file expected
  3. Assets\test1.cs(16,1): error CS1022: Type or namespace definition, or end-of-file expected

データベースもどきを改造するのが私では難しすぎるならば、諦めることも含めてご助言いただけると嬉しいです。

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

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

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

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

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

m.ts10806

2020/04/18 06:44

Unityが分かるわけではないですけど、これはいわゆる「データベース」とは違うのでは? 単にオブジェクトに情報を突っ込んでいっているだけで、データの管理がされているわけではないように見受けられます。
Namineko

2020/04/18 06:54

そうだったのですか!? 「unityでつくるデータベースの本」という名前の本だったので、データベースを作っているのだと思っていたのですが、違うのですね。わかりました。
dodox86

2020/04/18 07:02

いえ、言葉の定義の話になりますけど、よくあるリレーショナルデータベースシステムではないだけで、データを恒久的に使うためにシリアライズ/デシアライズをしようとされているので、「データベース」と言って言えないこともないかとも思います。
dodox86

2020/04/18 07:08

> エラーが出てしまって動きませんでした。 私もUnityに詳しいわけではないですが、ご提示のコードをみると(失礼ながら)C#の文法的にメチャクチャだと思います。出力されるエラーも質問文中に追記してください。>質問者さん
Namineko

2020/04/18 07:10

わかりました。質問文に掲載します。 それから質問を訂正しました。よろしくお願いします。
Namineko

2020/04/18 07:24

エラー文も掲載しました。
m.ts10806

2020/04/18 07:42

あぁなるほど「自身のデータをメモリ上に持っておく」という使い方であれば「データベース」と言えますね。 ちょっとWebばかりやってきたもので、どちらかというと「MySQL」や「PostgreSQL」「Oracle」のようなデータベースサーバ側のことをイメージしてました(もちろんUnityからも利用は可能とは思いますが)
guest

回答1

0

ベストアンサー


※以下の回答は足りないものがありましたので追記しました。下方の追記部分もご覧ください。

私自身の都合で今現在Unityをインストールしてなく、Unity用のコードではないので恐縮ですが、for文で希望の人数Max?人分のNameHPフィールドを初期化したいのですよね。
恐らく以下のようなことがやりたいのではないかと思いました。(Visual Studio 2019 のC#コンソールアプリケーションです)

[SerializeField]の属性が使えないため、単なるコメントにしています。

C#

1namespace ConsoleApp3 2{ 3 class Program 4 { 5 // [SerializeField] 6 int Max = 5; 7 // [SerializeField] 8 string[] Name; 9 // [SerializeField] 10 int[] HP; 11 12 // Name, HPフィールドを初期化するメソッド 13 public void InitializeFields() 14 { 15 Name = new string[Max]; 16 // nullだとちょっと危険かもしれないので一応 ""で初期化(好きに修正してください) 17 for (int i = 0; i < Name.Length; i++) 18 { 19 Name[i] = string.Empty; 20 } 21 22 HP = new int[Max]; 23 } 24 25 // UnityのMonoBehaviourでいうStart()相当メソッド 26 private void Start() 27 { 28 // フィールドをMax人分で初期化 29 InitializeFields(); 30 } 31 32 static void Main(string[] args) 33 { 34 var obj = new Program(); 35 36 obj.Start(); 37 } 38 } 39}

データベースもどきを改造するのが私では難しすぎるならば、諦めることも含めてご助言いただけると嬉しいです。

諦めることなんて無いと思います。既存のものから改造、改良していくのは、正しいひとつのやり方です。
ただ、基本的な文法はちゃんと理解されることを強くお勧めします。そうでないと理解に無駄な時間を過ごしてしまいます。


追記しました: 2020-04-19: 16:28

先の私の回答は「質問者さん提示のC#コードでは、フィールドの初期化のコードが間違っている」との指摘のみだったので、私のサンプルのコードも最終的にやりたい
こととしては恐らく不適切なものでした。ご要望に沿ったかたちでUnityで実装してみましたので、ひとつの案としてご紹介します。

そもそも要望としてはキャラクター1つに対して以下のような管理をしたいということなので、

▼Chara1 キャラクター1の名前 キャラクター1のHPの数値 ▼Chara2 キャラクター2の名前 キャラクター2のHPの数値 ...

まず、名前とヒットポイント(HP)をもつキャラクターを表すクラスCharacterを作成します。

C#

1// Character.cs 2// 名前とヒットポイント(HP)をもつキャラクターのクラス 3public class Character 4{ 5 // ※プロパティの方が良いが、簡単にする為、単なるフィールドで。 6 public string Name = string.Empty; 7 8 public int HP = 0; 9}

次に、Characterクラスを配列で管理するCharacterListを作成します。これがデータベースのコンポーネント本体です。Databaseオブジェクトにアタッチします。
※実際には配列は、Listクラスを使った方が扱いやすいかもしれません。

C#

1using UnityEngine; 2 3// Databaseオブジェクトで使うCharacterListコンポーネント 4// Characterクラスを配列/リストで管理する 5public class CharacterList : MonoBehaviour 6{ 7 // publicフィールドにしたので[SerializeField]属性は不要(?) 8 // https://docs.unity3d.com/jp/460/ScriptReference/SerializeField.html 9 //[SerializeField] 10 public int Max = 5; 11 12 //[SerializeField] 13 public Character[] Characters; 14 15 public void Initialize() 16 { 17 Debug.Log("CharacterList.Initialize()"); 18 19 Characters = new Character[Max]; 20 for (int i = 1; i <= Max; i++) 21 { 22 // "Name1", "Name2", ...の名前を生成 23 Character character = new Character(); 24 character.Name = string.Format("Name{0}", i); 25 } 26 } 27 28 void Start() 29 { 30 Debug.Log("CharacterList.Start():"); 31 } 32} 33

で、ゲーム(?)の本体でDatabaseオブジェクトをtargetObjectとして参照し、CharacterListクラスであるコンポーネントを呼び出します。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Runner : MonoBehaviour 6{ 7 public GameObject targetObject; 8 9 // Start is called before the first frame update 10 void Start() 11 { 12 Debug.Log("Runner.Start(): started."); 13 14 // "Database"オブジェクトを探す 15 targetObject = GameObject.Find("Database"); 16 if (targetObject == null) 17 { 18 // Databaseオブジェクトが見つからない 19 Debug.Log("Runner.Start(): unable to find Database"); 20 return; 21 } 22 23 // "CharacterList"コンポーネントを取得 24 CharacterList list = targetObject.GetComponent<CharacterList>(); 25 if (list == null) 26 { 27 // Databaseオブジェクト中のCharacterListコンポーネントが見つからない 28 return; 29 } 30 31 // Databaseオブジェクト、CharacterListの初期化 32 list.Initialize(); 33 34 Debug.Log("Runner.Start(): done."); 35 } 36 37 // Update is called once per frame 38 void Update() 39 { 40 41 } 42}

Unityエディターの状況です。
イメージ説明

最終的に質問者さんがやりたいことに合致しているか分かりませんが、恐らくこんな感じになるのではなかろうか、と。(C#のコードはあえて冗長な書き方にしました)
上記回答では納得できないかもしれませんし、Unityに詳しい他の回答者さんに私より適切な回答をいただけるかもしれません。しばらく質問を閉じずにいても良いかと思います。

投稿2020/04/18 08:33

編集2020/04/19 07:29
dodox86

総合スコア9256

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

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

dodox86

2020/04/18 11:09

いや、すみません。この回答はご要望と違いますね。後で修正を試みます。※低評価対象かも 適切な回答を別の方がしてくださるかもしれませんが。
Namineko

2020/04/18 12:01

返事が遅くなりすみません!ご親切にコードを載せていただきまして、励ましの言葉とともにとても感謝と感激しております! さっそくUnityに組み込んでみます!
dodox86

2020/04/19 07:31

追記しました。Naminekoさんの最終的なご要望からは外しているかもしれませんので、参考程度にしてください。
Namineko

2020/04/19 12:54

わざわざ二日間も貴重な時間を割いてくださいましてありがとうございます! 自分でも調べてみて、classとListとDictionaryあたりでもしかしたら実装できるかもしれない?と思って、本を読み返しながら組んでいたところに、こんなにすごいお手本が来てくれたので、本当にありがたいし嬉しいです!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問