ぐーるらいふ

しがないリーマンの記録。遊びのunityのメモ帳にしたい。

第三回 unity1week 「積む」に挑戦 前編 (企画編)

先週また@naichilabさんのunityroomにて、unity1weekが開催されました。
unityの勉強は継続してやっていて、このブログも出来るだけ続けていきたいなと思っているので
今回もチャレンジしていく事にしました。

積みゲーけしけし | ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

企画について

積むって。

もーこれが難しい。だって最初にパッと浮かんだのアレですよ、アレ!
f:id:ghoul_life:20170627020126p:plain
もうずーっと上位にいるネズミとかクマとかファンシーで可愛いアレのイメージが強すぎる。

とりあえずその考えを頭から振り払って、
他のことを考えよう。
荷物を積む、オブジェクトを積み上げて塔を作る、
など上にベクトルを向けるものがイメージとしてすぐに浮かぶが、
これも一杯出るだろうなぁ、と一旦振り払う。

積むんだよな、ゲームだよな、とシンプルに考えだした時
「積む+ゲーム=積みゲーをゲームにしたらどうだろう」
と思い立つ。

詳細をちょっとだけ詰める

積みゲーがただあるだけではダメだ。
それをどうにかしてゲームに落とし込まないと。
積みゲーを消化するって言うよな…。
シンプルに消化していくゲームはどうだろう。

  • 積みゲーから一本ゲームを選ぶ
  • そのゲームにパラメータが割り振ってある
  • ゲームにはクリアまでの所要時間がある
  • プレイヤーは所要時間を消費しそのパラメータ分成長する
  • 称号が手に入る(アクションゲームばかりクリアしていくとアクションマスターなど)
  • 一定期間過ぎた時に結果を振り返ることが出来る(一ヶ月など)

というゲームはどうだろうか。

だめだー

f:id:ghoul_life:20170627015135j:plain

簡単にモックにしてやってみるが、全然駄目。

  • ゲーム拘束時間が長くて、辛い。
  • 長い割に別に大した結果が出るわけでもない。
  • やれる事に比べて周りを固める要素が多く、分かりにくい。

普通の人ならちょっと触ったらもうブラウザ閉じてるわーこれは。
もうこの時点で金曜日の深夜。だけど考え直そう。

無理矢理な方向転換

もっとシンプルにしよう。所要時間も称号も捨てよう。
パラメータももっとシンプルでいい。
パズルゲーム風に要素を調整して…。

・お題が出る
・それを選ぶ
・正解なら+1 不正解なら0

としたらグッと触り心地が良くなった。
(面白いかどうかは一旦置いておいて)
後はこれでなんとか完成まで持っていこう。

開発編につづく
ghoul-life.hatenablog.com

【Unity】uGUIでimageに穴を開けたい!(くり抜く)

ルパン三世的な…?

チュートリアルなどでゲーム画面の説明をしたい。
よくある画面を暗くして見てほしい箇所にライトを当てるような演出をしたい。

f:id:ghoul_life:20170626200151p:plain

こんなんただ塗って穴開けてるだけやん。
それだけなのに、パッと実装が分からない。
Maskじゃない、なんというかMaskの逆?
uGUIだけで出来る?どうやるんだ?

  • すでにゲームは作ってあるので、そこはなるべく触りたくない
  • uGUIベースのゲームなのでuGUIでやりたい。
  • 実装はなるべくシンプルで簡単に

どうも既存機能だけでは厳しそうな感触。
なんらかの工夫が必要か。

くりぬく?

nn-hokuson.hatenablog.com
なるほど、ColorMask 0!
これでも行けそう?だけど
裏のQueueもいじらないと駄目か…。うーむ。
あ、そうか別Layerにして、サブカメラにすればいけそうかな?

ワイプ、トランジション

裏に影響なく画面全体を被せるのはこれが近いのかな?
tsubakit1.hateblo.jp
これを応用すればやりたいことが出来そう?

おお!これか!?これじゃん!
nn-hokuson.hatenablog.com
これを応用してみよう。

実装してみる

もうほとんどそのままだけどパラメータを外から設定出来るように。

Shader "Custom/HoleViewShader"
{
	Properties{
		_BackColor("background color", Color) = (0, 0, 0, 0) // 背景色
		_HoleX("Hole Position X", float) = 0 // 穴の位置X
		_HoleY("Hole Position Y", float) = 0 // 穴の位置Y
		_Radius("hole radius", float) = 0 // 穴の大きさ
		_ScreenW("Screen Width" , float) = 960.0 // 画面の幅
		_ScreenH("Screen Height" , float) = 640.0 // 画面の高さ
		}

	SubShader{
			Tags{ "Queue" = "Transparent" } // alphaに対応するのに必要

			Blend SrcAlpha OneMinusSrcAlpha // alphaに対応するために必要
			Pass{
				CGPROGRAM

				#include "UnityCG.cginc"
				#pragma vertex vert_img
				#pragma fragment frag

				// Propertiesの値をShaderに渡す
				float _HoleX;
				float _HoleY;
				fixed4 _BackColor;
				float _Radius;
				float _ScreenW;
				float _ScreenH;

				fixed4 frag(v2f_img i) : COLOR{

					i.uv.x *= _ScreenW / _ScreenH; // アスペクト比を計算してあげる

					if (distance(i.uv, fixed2(_HoleX, _HoleY)) < _Radius){
						discard; // 指定位置より一定距離以内だったら処理を飛ばすだけ
					}
					return _BackColor;
				}
				ENDCG
			}
		}
}

値を渡すスクリプト側はこんな感じ。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class HoleView : MonoBehaviour {

    void Start()
    {
        // 外部から設定する
        SetHole(new Vector2(480, 320), 0.2f);
    }

    public void SetHole(Vector2 pos, float radius)
    {

        // 画面との比率を出す
        var pinPos = new Vector2(pos.x / Screen.width, pos.y / Screen.height);

        // アスペクト比の問題なのか、位置的にはこのあたりで調整すると思った位置になるので計算してあげる
        // x range 0.45 - 1.05 この値が画面端から画面端でいい感じの所
        // y range 0.3 - 0.7

        // 比率と範囲値を計算して値を出す
        pinPos.x *= (1.05f - 0.45f);
        pinPos.y *= (0.7f - 0.3f);

        // 最下値を足して範囲に入れる
        pinPos.x += 0.45f;
        pinPos.y += 0.3f;

        // shaderに値を渡す
        var img = GetComponent<Image>();
        img.material.SetFloat("_HoleX", pinPos.x);
        img.material.SetFloat("_HoleY", pinPos.y);
        img.material.SetFloat("_Radius", radius);
        img.material.SetFloat("_ScreenW", Screen.width);
        img.material.SetFloat("_ScreenH", Screen.height);
    }
}

githubにもさくっと。
github.com



Inspectorはこれだけ!
Image一個あればOK!

f:id:ghoul_life:20170626190258p:plain

これで超簡単!後からちょい載せで使えるヤーツの完成です。
uGUI同士ならCanvasのSortOrderとかで順番をいい感じにしてあげてください。

注意事項として

  • ホールの形

え、星型にくり抜きたい?shaderで書くんだ!ってのは嘘で、
複雑な形にくり抜きたいならLayer&サブカメラ&ColorMask0でやったほうがいいかも。

こればっかりはどうしようも無い?
汎用的に外部パラメータ化してスクリプトから渡すように。
後は実際にゲーム画面を見ながらスクリプト側で調整してあげて下さい。

【Unity】Inputをいい感じにしたい

UnityでInputを取りたいなぁ。なんて思ったら
void Update()
などで
Input.GetMouseButton(0)
とか書くだろう。

そしてif分で押したらこのイベントをして…
なんていう処理を書くだろう

そしてそれが複数必要になることだってあるだろう。
そして仕様上それら全てを一時的に無効にしたいタイミングが来たりしたら
とっても大変だろう。(pause中とかね)

なので、Input周りはWrapperを使うようにしている。

自分はこんな感じで。

SingletonMonoBehaviorはこちら。
ghoul-life.hatenablog.com



シンプルだけど重宝している…。
simple is best.

どっからでもアクセス出来て、on/offも一括だし。
一括on/offは

Input.simulateMouseWithTouches = false

これでももしかしていける?使ったこと無いけど。

とりあえずこれはmouseだけど、touchとかも入れていけば
mobileにも対応できそう?
なんかそのままでもmobileでとりあえずは動いちゃうとか
聞いたこと有る。

一部だけ有効にしたい、とか
マルチタッチに対応したい、とか
DownとUpの差を見てフリック判定する、とか(時間も要るか)

要望は尽きない。メンテナンスしていきたい所。
なんかパッと書けちゃいそうだけどねーこのレベルだと。
でも自分用にメモっとこう。

【Unity】SingletonMonoBehaviourでUnityObjectにアクセス

ゲーム全体を管理するGameManagerであったり、Inputであったりと

  • 一意で管理したい
  • 好きな所からサクッとアクセスしたい

なんて場合に重宝する。

これだけだけど、メモっておこう

f:id:ghoul_life:20170618002503p:plain

仕事についての駄文

次回は

Unity 1週間ゲームジャム | ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

次回は6/19かららしい。
少し間があるので、適当なことでも書いちゃおう。

プロジェクト

今のプロジェクトに参加して三年ほどになるが、
プロジェクト自体はすでに五年目に突入していてそれなりに大きな規模になっている。
開発環境自体も洗練されていて、補助ツールなども充実。
また、立ち上げから参加している先輩も多く、長い人は検討段階から含めて6年ぐらい
これ一本でやってる人なんてのもいたりする。

運用が主で、三ヶ月~半年に一度ぐらいverUp業務で追加機能を実装する。
人が必要なのか?という感じだが、フロントとバックエンド含めて十人ぐらいはいる。
企画やデザインチームも含めると二十人ぐらいだろうか。
人が多いんでは無いか?と思うかもしれないが、2ver先の開発をしていたり、
追加された機能を運用に載せるためのツールを作ってたり、負荷を見直していたりと
やることは多い。

だが、基本的に弛緩した空気は流れている
障害や問題が起こることもあるが、
想定内というか予想外の出来事が起きることもなく、淡々と解決してしまう。
安定していると言えば聞こえはいいが、正直退屈ではある。

周りを見ると

社内の話になるが、新プロジェクトはしょっちゅう立ち上がっている。
UnityやVRのプロジェクトもあるらしい。

言いたいこととしては

  • 社外と一緒にやってたりする(楽しそう)
  • 入るメンバーは中途の新人だったりする
  • 正直うらやましい

こういったプロジェクトにお金をせっせと運ぶのはやぶさかではないが、
うらやましい、自分も入りたい。
今のプロジェクトは嫌いじゃないが、飽いている。新しい刺激がほしい。
逆に新しい人をこっちに入れて、今いる人を少しずつ開放して循環させてほしい。

とかなんとか思っているけど

これも甘えなのかな。面談や飲み会でこんな話をすることもあるけど、
上司「俺が一番そう思ってるよ」(5年目)である
評価はされているので、金銭面や待遇で不安はないけども。

こういう不満が積み重なった結果、会社ごと離れてしまう人が出るのかな。

f:id:ghoul_life:20170607004832p:plain

【Unity】UnityのAnimationがわかんないよ

ずっと避けていた。
自作スクリプトでやっちゃったり、iTweenで代用していた。
プログラマーとしてはそれでいいと思っていた。
細かい制御、イベント発行だって自由自在だし、困ったことも無かったし。
何よりよく分からないし。
何度か挑戦はしてみたが、いつも思った動きが作れないので諦めてしまっていた。

が、このままではずっと出来ない。
もう一度挑戦してみよう。

作りたいもの

作りたいものはこれだ。
出来とるやん、って突っ込まない。

f:id:ghoul_life:20170526150208g:plain

一枚の画像がリズムを取るように上下scaleが伸縮するだけ。
もちろんposition , rotation , scaleをいじっても
それに追従して動いてくれるものじゃないと使い物にならない。
相対で動いてくれるものが絶対だ。

自分がやった手順をまとめておく

触ってこなかったので、調べながら見よう見まねでやってみたのをまとめておく。

配置~初期設定
  1. 適当なpngを画面にD&Dでinspectorに配置する
  2. Window > AnimationでAnimationタブを開く
  3. 1で配置したGameObjectを選択している状態でCreateを押下して、適当な.Animファイルを作る
  4. Add PropertyでTransform > Scaleを選択。

ここまではいいだろう。思ったまま操作すればいい。簡単だ。
問題はこっからだ。

パラメータ

まずは全体の長さを確認。何もせずそのまま実行する
ちょっとアニメーションの長さが長いので 0:40に短くしたい。
右側にある最後のキーフレームをグイッと0:40の所まで持っていけばOKだ。

さて、では実際にリズムを取るアニメーションを作る

0:25 , 0:30 , 0:35の箇所3つにAdd keyしてkeyframeを作る
赤い線を持っていって、右クリックしてAdd Keyだ。
カーソルの位置ではなく赤い線の箇所に作られちゃうぞ!
そして、0:30にまた赤い線を合わせて、transformのscale.yを0.5にする。
これで良さそうだ。

実行してみる。

f:id:ghoul_life:20170526150546g:plain

おお、それなりに合ってる。もうちょっと感覚を狭くしたら良さそうだ。
調査段階なのでこれでとりあえずいいだろう。

実験

ちゃんと実用に耐えられるかテストしてみよう。

移動してみる

先程のAnimatorを付けたものを移動させてみる
こんなん。

  if (Input.GetKey(KeyCode.LeftArrow))
  {
      var p = this.transform.position;
      p.x += MOVE_VALUE * Time.deltaTime;
      this.transform.position = p;
  }
  else if(Input.GetKey(KeyCode.RightArrow))
  {
      var p = this.transform.position;
      p.x -= MOVE_VALUE * Time.deltaTime;
      this.transform.position = p;
  }

f:id:ghoul_life:20170526151032g:plain

おお、問題なく動くぞ!(当たり前)

回転させてみる

無茶な傾きではどうか

f:id:ghoul_life:20170526151147g:plain

これも問題なし!
Unity最高だな

拡大させてみる

問題はここだ。
scale値を2,2,2にしたオブジェクトをAnimationさせたらどうなるのか。

f:id:ghoul_life:20170526152146g:plain

はい、死にました。

scale2なら
2 -> 1.5 -> 2
と動いてほしい。

相対的に設定するには…?

なんかあるはずだ。Unityは馬鹿じゃない。
何かしら方法があるはずだ…!

tsubakit1.hateblo.jp

あったあああ!
これだ!神がいた!こうすればいけるはずだ!

早速設定して実行!

f:id:ghoul_life:20170526152944g:plain


……
………

なんだこれは

BlendingをAditiveに設定すると、初期値からの移動量でアニメーションを行う

つまり、初期値からy:-0.5縮んでくれればいいのだ。
が、結果

0 -> -0.5 -> 0

になってしまった。
何故だ。初期値はtranformの2じゃないのか、一体初期値とはどこにあるんだ。

ガクッ。

結果

他で紹介されているのと同じように親オブジェクトの下でAnimation動かせばいいんだ。
そして、親オブジェクトのtransformをいじれば何ら問題ない。

もうそれだけでいいんだ。

f:id:ghoul_life:20170526153455p:plain

うーん、出来そうなんだけどなぁ。わかんね。

f:id:ghoul_life:20170604000704g:plain

【Unity】フェードイン・アウトを簡単に実現

前回のunity1weekチャレンジで作りたかったけど断念した
この機能を今のうちに用意したいな、なんか無いかなと思ったら
神おったーおったー!
kan-kikuchi.hatenablog.com
参考にさせてもらいます!

参考にして実装

そのまま使いたい所だが、それでは勉強にならない。
参考にしつつ自分なりにカスタマイズして身にしていきたい。

  • 好き勝手なタイミングでFadeInOutさせたい。
  • FadeInした後、待機時間を得てからOutしたい
  • スッキリと1クラスにまとめる

というわけで実装コード。
詳しく解説は書かないけどシンプルなコードなので読めばわかると思う。


呼び出しはこんな感じで

    public Fade fade;

    public void Fire()
    {
        fade.FadeInStarted += FadeInStart;

        fade.FadeInFinished += () => { Debug.Log("Fade in finished"); };
        fade.FadeOutStarted += () => { Debug.Log("Fade out started"); };

        // 2つのメソッドを呼ぶことも可能
        fade.FadeOutFinished += FadeOutFinished1;
        fade.FadeOutFinished += FadeOutFinished2;
        fade.FadeStart();
    }

    private void FadeInStart()
    {
        Debug.Log("Fade in started");
    }

    private void FadeOutFinished1()
    {
        Debug.Log("Fade out finished 1");
    }
    private void FadeOutFinished2()
    {
        Debug.Log("Fade out finished 2");
    }

動作画面は割愛するけど、イベントはしっかり発行されているのを確認。

f:id:ghoul_life:20170530124437p:plain

これは次に使いたいって事でメモ。
f:id:ghoul_life:20170530233421p:plain