転職を繰り返したサラリーマンの多趣味ブログ

30才未経験でSEに転職した人の多趣味ブログ

【UnityでRPG製作】レベルアップの実装方法

RPGのレベルアップの実装方法について調べると、累計経験値を使った計算式が色々でてきた。けど、これを理解して自分で使おうとするとハードルが高かったので、経験値テーブル(実際にはディクショナリ)を作って、それを使ってレベルアップを実装していこうと思う。
まず、経験値を管理する実装はこんな感じ。

// 経験値ディクショナリ
private Dictionary<int, int> needExpDictionary = new Dictionary<int, int> {

    // Lv、経験値
    {2, 6},
    {3, 16},
    {4, 28},
    {5, 48}

};

// 引数で渡されたLvに必要な経験値を返す
public int GetNeedForLvupExp(int lv) {

    return needExpDictionary[lv];

}

例えば、Lv2にあがるのに必要な経験値は6ということになる。そこで、モンスターとのバトル終了後に、GetNeedForLvupExpメソッドを呼び出す。このとき引数に渡すのは、現在のLvにプラス1を足した数。Lv1の場合、引数に2を渡してLv2に必要な累計経験値の6を取得する。取得した6と、実際の累計経験値を比較して、累計経験値が6を上回っていたらレベルアップするという実装にした。

// モンスターを倒したときのお金と経験値を取得し、レベルがあがったらtrueを返す
public bool EndBattle(MonsterModel monsterModel) {

    // 経験値とお金を取得
    model.exp += monsterModel.exp;
    model.money += monsterModel.money;

    // 現在のレベルより一つ上のレベルに必要な経験値を取得
    var moreExp = experienceComponent.GetNeedForLvupExp(model.lv + 1);

    // 現在の経験値の方が高ければレベルアップ
    if (moreExp <= model.exp) {

        // レベルをあげる
        model.lv ++;

        return true;

    } 

    return false;

}

自分はこの実装方法をとることで感じるメリットは以下の通りです。

  • 各レベルごとに必要な経験値がわかりやすい
  • モンスターを何匹倒したらレベルアップするか、調整しやすい
  • 各ステージごとに現れるモンスターの経験値を設定しやすい

これが最適化といわれればかなり微妙だけど、何かの参考になれば。

【Unity】unity1weekで作ったゲームを改良して、Google Play Storeへリリースした

約2カ月かけて、unity1weekで作ったゲームを改良してAndroidアプリを開発した。
そのアプリがこれ。

f:id:uuc1h:20210404104801p:plain

play.google.com

いわゆるウォーリーを探せ的なゲームです。全50問作ったのでボリュームは十分で、問題が進むと高難易度の問題もでてきます。
サクッとできるゲームなので、ぜひ遊んでみてください。

【Unity】Google Play Consoleにaabファイルをリリースしたらエラーになった

タイトルの通り、Google Play Consoleにaabファイルをリリースしたら、以下エラーメッセージが表示された。

f:id:uuc1h:20210404103859p:plain

リリース時には、いつも何らかのエラーが出てしまうので対応方法をメモする。
調べてみたら、対応方法はかなり簡単だった。
UnityのProject Settings / Other Settings / Target ArchitecturesでARM64にチェックを入れること。

f:id:uuc1h:20210404104345p:plain

これで無事にリリースできた!

【NBA】明日はオールスターゲームだから、お気に入りのオールスターゲームについて語りたい

タイトルそのまんまです。日本時間の8日10:00に、オールスターゲームが行われる。近年のオールスターゲームは、各チームのキャプテンによるドラフト形式でチームが決定する。今年はチームレブロンvsチームデュラント。ドラフト形式になってから、レブロンはずっとキャプテンを就任しているのも凄い。ちなみにキャプテンは、ファン投票の最多得票者が選ばれるから、レブロンはずっと人気があるってことになる。
レブロンは今36才やけど、アスリートで36才といえば人によっては引退する年だし、そもそも身体能力は確実に落ちる。しかし素人目には、レブロンの身体能力は一切落ちていないように見える。普通は落ちるはずのジャンプ力も全く落ちていないから、今でも凄まじいダンクを決めるし、ヒート時代にスパーズ相手にみせた鬼の形相のブロックも今でもする。そこに、今のレブロンは経験が加わっているから、必要な時以外はパワーを抑えていて、ここぞというときに自分が得点をとりにいく。いわゆる、試合全体を見ているし、何ならシーズンを通して優勝までを見据えてコントロールしているから、本当に史上最高のバスケットプレイヤーなんかじゃないかと思えてくる。

序盤でレブロンについて語ってしまったが、本当に語りたいことはお気に入りのオールスターゲームのことだ。自分が一番好きなオールスターゲームは、やはり初めてみたオールスターゲームだ。それは2005年にデンバーで行われた、アレン・アイバーソンがMVPをとったオールスターゲームだ。
まず何がいいって、入場が死ぬほどかっこいい。。2005年は、ベンチメンバーも一人ずつ入場するスタイルだった。そこで各選手が思い思いのポーズをとるのだが、アレン・アイバーソンの入場は格別だ。

実際の試合内容もこれぞオールスターゲームという内容。序盤はディフェンスゆるめで、各選手がダンクを派手に決めたり、シャックがポイントガードをやったりと。で、後半になると真剣モードになる。豪華メンバー同士の真剣勝負がオールスターゲームの醍醐味だと個人的に思う。真剣勝負といえば、2007年にラスベガスで行われたオールスターゲームで、コービーがジョージョンソンとの1on1でぬきさり、ダンクを決めたのも思い出す。

けど、2014年ごろから真剣勝負が見られなくなった。常にディフェンスに手をぬき、3ポイントをうつだけのつまらないものになってしまった。2017年なんて200点近く点が入ったんだから確実にディフェンスしていない。この状態をファンもリーグも問題視し、ついに昨年改革が行われた。勝利チームは、施設に寄付ができるという特典がついて、両チームがきちんと勝負する目的を作ったのだ。これが功をそうして、終盤だけでなく終始真剣勝負を見ることができた。だから、2020年のオールスターゲームもお気に入りだ。今年のオールスターゲームのルールはまだ見ていないが、今年もスター選手たちの真剣勝負を見たい。

言葉が出てこないときってありますよね?

最近、記憶力の低下に悩んでいる。言葉が本当に出てこない。結婚して3年たつが、妻とは「アレ」で意思疎通ができるようになってきてしまった。これも、言葉が出てこない原因なのではないかと思う。
これはいかんと思い、記憶力の強化を目的とした日記をつけ始めた。ブログやnoteではなく、手書きの日記だ。Twitterで、1日の振り返りがいいというつぶやきを見つけたのが手書き日記のきっかけだ。

2月14日から始めたので、間も無く1ヶ月がたとうとしている。日記を書くにあたり、自分が決めたルールはこれ。

  • 日記は事実だけを書く。(何時に起きて、朝食は何を食べたかなど)
  • 日記を書かない日があっても気にしない。
  • 日記は布団で寝転びながら書く。

最後の布団で寝転びながら書くのは、日記を書くという行為のハードルを下げてくれている。これは、セブンルールで新川帆立さんがあげていた「小説はベッドで横になって書く」を丸パクリしたものだ。

www.ktv.jp

この「机に向かう」というハードルを無くすのは本当に効果的だと思う。自分は何か新しいことを始めるとき、様々なことを理由にすぐにやめてしまう。いつも、続かないことが日常なのだ。けど、続けれないことを分析して、障害になっている問題点を取り除こうとする努力を怠っていたことが、何事も長続きしない最大の原因だったのだ。

 これを機に、自分の様々な問題点に向き合って考えるようになってきた。「作ったゲームのダウンロード数が伸びない」→「ダウンロード数が伸びない原因は、そもそもゲームの存在を知られていないから」→「まず認知されないとダメなので、次のゲームリリース時には、メディアにプレリリースを配信してみよう」など。

やっぱり、何事も考えないとダメっすね。と、言葉が出てこないことを発端に、自分の中で新たな指針ができたので、記憶力の低下も悪いもんじゃないね。

【Unity】ゲームを作ってリリースしました。

Unityでゲームを作って、Androidアプリとしてリリースしました!
超絶シンプルですが、今の自分ができることを詰め込みました。無料で広告なしなので、ぜひぜひ遊んでみてください。

play.google.com

f:id:uuc1h:20210204231232p:plain

 

【技術書メモ】配列とList<T>の操作まとめ

普段めちゃめちゃよく使う、配列とList。これは自分だけかも知れないが、普段の仕事で書くコードにあまり配列を使わない印象がある。Listの使用率が圧倒的に多い。
けど、配列が使えないと困る部分はあるので、一緒にまとめていく。

配列あるいはListに同じ値を設定する

あまり使用頻度が少なそうだが、同じ値の要素をもったリスト、配列の作り方。

// -1が20個あるリスト
var numbers = Enumerable.Repeat(-1, 20).ToList();

// -1が20個ある配列
var numbers = Enumerable.Repeat(-1, 20).ToArray();

ちなみに、-1を20個要素にもったリストを作ろうとすると、以下のように書く。
うん、これはだるい。

var numbers = new List<int> {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, };

配列あるいはListに連続した値を設定する

ここからのやつは、かなり出番がありそう。

// 1から20まで連続した値をもったリスト
var list = Enumerable.Range(1, 20).ToList();

// 1から20まで連続した値をもった配列
var array = Enumerable.Range(1, 20).ToArray();

平均値を求める

こっから、よく使うやつたちです。

var numbers = new List<int> {1, 2, 3, 4, 5, };
var average = numbers.Average();

合計を求める

var sum = numbers.Sum();

最小値、最大値を得る

var min = numbers.Min();
var max = numbers.Max();

条件に一致する要素をカウントする

var count = numbers.Count(n => n == 0);

条件に一致する要素があるか調べる

bool exists = numbers.Any(n => n % 7 == 0);

すべての要素が条件を満たしているか調べる

bool isAllPositive = numbers.All(n => n > 0);

2つのコレクション(リストや配列など)の要素が等しいか調べる

bool equal = numbers1.SequenceEqual(numbers2);

条件に一致する最初 / 最後の要素を取得する

var text = "The quick brown fox jumps over the lazy dog";
var words = text.Split(' ');

// 文字列overが取り出される
var word = words.FirstOrDefault(x => x.Length == 4);

// 文字列lazyが取り出される
var word = words.LastOrDefault(x => x.Length == 4);

条件に一致する最初 / 最後のインデックスを求める

var numbers = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, };
// 戻り値は2
var firstIndex = numbers.FindIndex(n => n < 0);
// 戻り値は8
var lastIndex = numbers.FindLastIndex(n => n < 0);

条件を満たしている間だけ要素を取り出す

これはちょっとつまづいたので、説明を入れる。TakeWhileメソッドを使えば、引数に与えた条件を満たしている間の要素を取り出せる。しかし、先頭から順番に条件に当てはまるか調べるが、先頭がすでに条件から外れていたら、その時点で処理をストップする。だから、以下コードのようになる。

var numbers = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, };
// 9, 7を取り出す
var selected = numbers.TakeWhile(x => x > 0);

// 何も取り出さない
var selected = numbers.TakeWhile(x => x < 0);

条件を満たしている間は要素を読み飛ばす

今度は、条件を満たしている間は要素を読み飛ばす。ただ、先頭が条件に合わないと処理がストップする動きは同じ。

var numbers = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, };
// -5, -4, 2, 5, 4, 0, -4を取り出す
var selected = numbers.SkipWhile(x => x > 0);

// 9, 7, -5, -4, 2, 5, 4, 0, -4を取り出す
var selected = numbers.SkipWhile(x => x < 0);

リストの重複を排除する

var numbers = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, };
var result = numbers.Distinct();

コレクションを並び替える

この並び替えは、めちゃめちゃ使うと思う。かなり重要。

// 昇順にソート
var numbers = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, };
var selected = numbers.OrderBy(x => x).ToList();
selected.ForEach(Console.WriteLine);

// 降順にソート
var selected = numbers.OrderByDescending(x => x);

2つのコレクションを連結する

var numbers1 = new List<int> { 9, 7, -5, -4, 2, 5, 4, 0, -4, };
var numbers2 = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, };

var all = numbers1.Concat(numbers2).ToList();
all.ForEach(Console.WriteLine);

ここに書いたものが、すっと出てくるようになれば競プロもだいぶ解けるようになるんじゃないかと思う。反復あるのみですね。
配列とList、完璧に理解した。