投稿記事

A-Nest 2021/12/18 09:54

ショート企画

どうもグラフィック担当のがふです。
ただいま絶賛製作中のショート作品なのですが
プログラムやらゲームの詰めに忙しいゆっくりみかんさんに代わり
今週は、自分の方から記事を書かせていただきます。

さて、必要なモデルを一通りそろえて後はそのモデルの詰め作業だったり
モーションを用意したり・・・

とりあえずメインキャラの全身と服を脱がす邪魔をするジャマーことポッド
造形は、概ね完成しています。
自分で言うのもなんですが思ったよりよく出来たのではないでしょうか?

ノーマルでディテールを増したりしてビジュアルはfix出来そうです。

まぁ2Bということもあり
お尻に補助ボーンを仕込んだりして

綺麗なプリケツ!
これを皆様の元へ届けられるようにより奮闘したいと思います(・ω・;)



「この臀部パーツが気になるのか?人間は不思議だな」




余談ですが、自分は胸より足と尻の方が好きです。

キャラクターがある程度出来たところで背景の作成
みかんさんに渡してUNITYで簡単にライティングをしてもらった所
思った以上にそれっぽくなった・・・・ふむ悪くない


ゲームパートもある程度形になってきていて今詰めを行っております!
完成をお楽しみに!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

A-Nest 2021/12/09 17:08

ミニゲーム作品に関して

どうも、グラフィック担当のガフです。

先週みかんさんも述べていたように、小タイトルを一本急遽作る事になりました。
自分は、ゲームの仕様などにあれこれ口をはさみつつ
ある程度ゲームが形になったところでルックなどを決めたり

さて、今回の小タイトル題材に選んだのは
ニー〇の2〇です

衣装や詰めはこれからですが
なんとなく形になってきています。

今回脱衣シューティング?ということもあって
ジャマーも作品にあわせた物が良いかなと・・・・
そこで思いつくのはこいつしかいませんね。

これも質感とかはまだこれから調整となりますが
意外と悪くない感じに仕上がってますね

とまあ、急遽始まった企画ですが
急ピッチで形になってきています。

メインプロジェクトの方に関しては、少しお待たせする形になってしまいましたが
引き続きA-Nestを応援していただけると嬉しいです!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

A-Nest 2021/12/02 01:21

実験プロジェクト

どうも、プログラマのゆっくりみかんです。

ちょっと急な立ち上がりですが、実験的に1~2週間でエロゲー作るぜ! という試みを始めています。
内容は、前作のモデルを使った3Dブロック崩しです。
大体一日でここら辺まで仕上がりました。

Unityの物理エンジンって今一挙動がわかりにくく、結局ブロック崩しに関わる物理挙動は自前でコードを書く羽目になりました。
うーむ。
そして、作って調整すらしていないので玉のホーミング具合が露骨ですね・・・w
まあ、一日の作業なのでこのぐらいかなぁ、と。

現在の所単に女の子で玉が跳ね返るだけですが、エロゲーなのでもちろん脱衣する様にしていく予定です。
期間が期間なので、どこまで練り込めるかは未知数です。
ブロック崩しじゃなくてシューティングになる可能性もあります。w
期間が長引くようなら容赦なく没プロジェクトになりますが、遊べるものをしっかり出せる様に頑張ります。
それでは!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

A-Nest 2021/11/24 23:01

進捗など

どうも、グラフィック担当のガフです。
最近すっかり寒くなってきましたね。
あと数日もすればすっかり冬になりそうな季節
体調には気を付けていきたい今日このごろ

まだまだ作らないといけない素材がまだまだたくさんあり、天手古舞になりながら作業をしております。

ゆっくりみかんさんが進めているおさわりパートのUIがある程度完成し
それ合わせに他のUIもちょこちょこと出来上がってきました。

こまごまとした、おさわりパーツのアニメーションは終わったのですが
UI素材用であったりアニメーション用だったりの素材を作るべく
メインのキャラクターのポーズを制作しようとした所で問題が起こりました。

ボーンデータが壊れてる!

これに関しては、auto rig proを使っていて基本自動で作ったリグなのですが
恐らく長い期間の製作と、度重なるツールの更新 blenderデータの更新のせいで
不整合が発生してしまったものと思われます。
これに関しては、モデルを長期に扱うなかでほいほいバージョンを変えていってしまった自分のミスですね・・・・非常に反省。

お詫びのオッパイ貼っておきますね(・ω・;)

ルックをどう落とし込むか、実はまだ悩み中でして
少しリアルよりにするか、少しトゥーンよりにするか・・・

そしてちょっと前作のキャラも登場したり?

UIに関しては、前作非常に不満があったので
今回はしっかりとデザインしてます!

だいぶ見やすくまとまったかな
そんなこんなで形はできています!

さて、今年もあとわずか・・・
残り作業も気合入れていきましょう!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

A-Nest 2021/11/16 22:17

開発者向け - インターフェイスの使い方2

どうも、プログラマのゆっくりみかんです。
さて、前回の話の続きをしていこうかと思います。
今回の内容は、Unityの2019.3以降である事が前提となっています。

インターフェイスの使い方

実際にインターフェイスを自分で使って行こうとすると、どういう感じで使う事になるでしょうか。
前回も書いた通り、中々イメージがし辛い機能なわけですが、簡単な例を出してみましょう。

まず、uGUIのボタンがあったとします。

こんな具合ですね。
こういった感じでボタンやらスライダーやらを色々と配置してGUIをUnityでは作っていくわけですが、押しても反応して欲しく無い場合があったとします。
例えば、

//ゲームモードの定義
public enum GameMode {
	InGame,		//ゲーム中
	Talking,	//会話シーン
    Menu,		//メニュー
    Pause,		//ポーズ
}

こんな風にゲームモードの定義があって、

//ゲーム全体に係る管理マネージャ、シングルトンクラスとする
public class GameManager : SingletonObject {
	[SerializeField]
    private GameMode _currentGameMode;	//現在のゲームモード
    public GameMode CurrentGameMode => _currentGameMode;
}

こんなゲームのマネージャで現在のゲームモードを管理していたとします。
そして、ゲーム中のボタン・・・ 例えば、魔法を使うボタンとか。
そういうものがあったとして、それは会話シーンとかメニューとかポーズ画面で使えちゃ困るわけです。
そういった時、どうするか?
そのまま、普通の実装だとこうなると思います。

//魔法使用ボタン
public class SpellButton : MonoBehaviour {
	[SerializeField]
    private Button _spellButton;	//uGUIのボタンの参照

	[SerializeField]
	private SpellData _spellData;	//魔法データを持ったスクリプタブルオブジェクト

	private Enemy _targetEnemy;		//ターゲットとなる敵
	public Enemy TargetEnemy {		//公開用のターゲットとなる敵プロパティ
		get => _targetEnemy;
		set => _targetEnemy = value;
     }
    
    void Start() {
    	//onClickイベントへの登録
    	_spellButton.onClick.AddListener(() => {
        	//ゲームモードがInGameの時だけ実行
        	if(GameManager.Instance.CurrentGameMode == GameMode.InGame) {
				_spellData.CastSpell();	//呪文を唱える
            }
		});
    }
}

こんな感じですね。
さて、この実装に問題はあるでしょうか?
まあ別にこれでもいいのですが、問題は
「じゃあ他の似たようなボタンはどうするの?」
という事です。
攻撃ボタンがあったとしましょう。その時も

	//ゲームモードがInGameの時だけ実行
	if(GameManager.Instance.CurrentMode == GameMode.InGame) {
		//~何らかの攻撃処理~
	}

このコードをわざわざ挿入するのでしょうか?
じゃあ、もしゲームモードに変更が入って
「Bossモードを追加して、そっちでも使える様にしよう」
とかなった時、全てのコードを書き換えるのでしょうか?
めんどくさいし、管理が大変ですよね。
さて、考えてみましょう。
攻撃ボタンと魔法ボタンで共通した「機能」は何でしょうか?
それは
「特定の状況でのみクリック可能である事」
です。
さて、インターフェイスとはどういう機能だったでしょうか?
「クラスの機能を明示的に宣言して、共通の形で扱える様にするもの」
です。
先ほどの
「特定の状況でのみクリック可能である事」
というのは、じゃあどの様にインターフェイスとして実装すれば良いのでしょうか?

実装例

まず、
「特定の状況でのみクリック可能である事」
を示すインターフェイスを実装してみましょう。

//クリック可能かどうかを示すインターフェイス
public interface IClickable {
	public bool NowClickable { get; }	//クリック可能かどうかを示すプロパティ
}

とりあえずはこれだけでも十分です。
さて、このインターフェイスをどう実装するかというと、こうなります。

//戦闘中だけクリック可能なIClickable
public class BattleClickable : IClickable {
	public bool NowClickable => GameManager.Instance.CurrentGameMode == GameMode.InGame;
}

こんな感じですね。
では、これをどの様に実際のボタンに実装すれば良いでしょうか?

//魔法使用ボタン
public class SpellButton : MonoBehaviour {
	[SerializeField]
    private Button _spellButton;	//uGUIのボタンの参照

	[SerializeField]
	private SpellData _spellData;	//魔法データを持ったスクリプタブルオブジェクト
    
    [SerializeReference]
    private IClickable _clickable;	//クリック可能かどうか

	private Enemy _targetEnemy;		//ターゲットとなる敵
    
    void Start() {
    	//onClickイベントへの登録
    	_spellButton.onClick.AddListener(() => {
        	//クリック可能な状態か判定
        	if(_clickable.NowClickable) {
				_spellData.CastSpell();	//呪文を唱える
            }
		});
    }
}

こういう感じになります。
SerializeReferenceというのは、インターフェイスや抽象クラスだけで使える特別なシリアライズ属性です。
インターフェイスや抽象クラスではないメンバ変数にこれを付けても、特に意味はありません。
また逆もしかりで、インターフェイスにSerializeFieldを付けても無意味です。
抽象クラスは、唯一このどちらも受け付けますが、それによる使い分けに関してはまた追々。
さて、このボタンスクリプトを実装してコンポーネントとしてボタンに登録すると、どの様になるでしょうか?

こんな感じになります(SpellDataは省略しているのでインスペクタにはありません)。
さて、このインスペクタ画像の

この赤線に注目してみましょう。Nullになっています。
これは、定義が

    private IClickable _clickable;

こうなっており、ただのインターフェイスの入れ物でしかないからです。中身がからっぽなわけですね。
では、ここをクリックしてみましょう。すると、こういったメニューが出ます。

リストに、先ほどサンプルとして挙げたBattleClickableが入っていますね。
これを選ぶと

この様に、インターフェイスの中身としてBattleClickableが入ります。
すると、先ほどの様に

        	if(_clickable.NowClickable) {
				_spellData.CastSpell();	//呪文を唱える
            }

と書いた箇所のNowClickableを呼び出したら、BattleClickableの

	public bool NowClickable => GameManager.Instance.CurrentGameMode == GameMode.InGame;

このコードが呼び出され、bool値として値を返すわけです。
さて、先ほど例として挙げた
「Bossというモードを追加し、そこでも使える様にしたい」
場合はどうすれば良いでしょうか?

	public bool NowClickable =>
    	GameManager.Instance.CurrentGameMode == GameMode.InGame || 
        GameManager.Instance.CurrentGameMode == GameMode.Boss;

この様に、IClickableを継承したBattleClickableを書き換えるだけで良いのです。
さて、こういった事に対して
「クラス継承するだけでも似たような事は出来るジャン? ジャンジャン?」
と思う方もいるかも知れません。
しかし、こちらの方には

  • 一部のロジックを外に出せる
  • 簡単にバリエーションを追加できる

というメリットがありますし、無理に継承で実現しようとすると難しいケースも発生してきます。

インターフェイスのメリット

さて、これらのメリットはどういう事でしょうか?
まず、ロジックを外に出せる、というのは一言で言うと
「使い回しがしやすくなる」
という事です。
「簡単にバリエーションを追加できる」
という例も含めて、実際にコードを書いていきます。

先ほどの例のSpellButtonを
「場合によってクリック出来たり出来なかったりするボタン」
という汎用的なクラスで作りたいとしましょう。
インターフェイスを使うとこんな風に汎用化出来ます。
命名があんまり適切じゃない感じがしますが、ご容赦を。

//クリック出来たり出来なかったりするボタン
public class ClickableButton : MonoBehaviour {
	[SerializeField]
    private Button _button;	//uGUIのボタンの参照

    [SerializeReference]
    private IClickable _clickable;	//クリック可能かどうか
    
    [SerializeReference]
    private IOnClickProcess _onClick;	//OnClickの処理

    void Start() {
    	//onClickイベントへの登録
    	_button.onClick.AddListener(() => {
        	//クリック可能かどうかで分岐
        	if(_clickable.NowClickable) {
				IOnClickProcess.Process();	//何らかの処理
            }
		});
    }
}

さて、Clickableは先ほどの説明通りですね。
そこに加えて、今回はIOnClickProcessというメンバ変数が追加されています。
IOnClickProcessというインターフェイスは、中身はこんな感じです。

//OnClickの処理インターフェイス
public interface IOnClickProcess {
	public void Process();
}

この実装として

//呪文処理
public class SpellProcess : IOnClickProcess {
	[SerializeField]
    private SpellData _spellData;	//呪文データのスクリプタブルオブジェクト
    
    [SerializeField]
    private Enemy _targetEnemy;	//ターゲットの敵

	//クリック時の処理
    public void Process() {
    	_spellData.CastSpell(_targetEnemy);	//呪文を唱える
    }
}

こんな呪文のクラスや

//攻撃処理
public class AttackProcess : IOnClickProcess {
	[SerializeField]
    private Weapon _weapon;	//装備している武器
    
    [SerializeField]
    private Enemy _targetEnemy;	//ターゲットの敵

    public void Process() {
    	_weapon.Attack(_targetEnemy);	//攻撃!
    }
}

こんな実装があるとします。
するとどうでしょう、先ほどの汎用クラスのインスペクタでonClickを選択し、SpellProcessやAttackProcessを選ぶ事によって、どちらのボタンにも早変わりも出来るわけです。
しかも、無効化するタイミングも自由自在です。
IClickableインターフェイスを継承したクラスを書いて、それをインスペクタから選ぶだけです。
ボタンクリック時の処理の場合なら、攻撃、魔法以外にも特技というボタンを作りたければ、IOnClickProcessを実装したSkillProcessというクラスを実装してやれば、後はクリックして設定するだけです。
これが
「簡単にバリエーションを追加できる」
という事です。

そして、ClickableButtonというクラスは、特定のゲームでしか使えない独自の何かを含んでいるでしょうか?
最初の例だとGameModeという列挙型を実行の可否の条件にしていますが、GameModeなどは、今回作るゲームと次回作るゲームで内容が違ってきて当然です。
しかし、ClickableButtonには、そういった
「ゲームによって違う」
コードが極力含まれていません。
これはつまり、次回の作品でもそのまま使い回せる可能性が高い事を意味します。

これを通常の継承で実現出来るでしょうか?
中々難しいと思います。
なぜなら、C#においては
「継承は一つしか出来ない」
という、多重継承を許さない制約があるからです。
上手くやらないと、どこかで破綻が起こります。
それと比べ、インターフェイスはこの例外で、いくつでも継承可能なのです。

ちなみに、こういったインターフェイスを使って独自処理を追い出すやり方を
「依存性注入(Dependency Injection)」
と呼びます。このワードで検索をすると、色々ヒットするので調べてみるのも良いでしょう。

使い回ししやすいコード資産を作る為に

使い回ししやすいコードである、という事は非常に重要な事です。
毎回毎回、ゲーム独自のコードを含んでいると、そのコードを次回利用したい場合に
「これは今回は使わないから消して・・・ 今回はあれがあるから追加して・・・ 今回のこの要素は前回とは別のロジックで組んでるから、ここも書き直して・・・」
みたいな作業が発生して、結局一から書くのと大差ない、みたいになりがちです。
また、そういった作業は新しいバグを仕込みがちです。
インターフェイスを上手く使ってクラスを汎用化しておくと、ゲームに依存する部分だけをインターフェイスの実装として書けば、それで事足ります。
便利!

めんどくさい

インターフェイスの唯一の難点は、めんどくさい感じがする、という事です。
何というか、そのまま素直に書くのと違って遠回りをしている様な気分にさせられる感じがします。
しかし、こういった事はまあ慣れですし、インターフェイスを活用すればするほど、めんどくささも消えて自然にインターフェイスを活用出来る様になっていく事でしょう。

というかまあ、正直僕も
「めんどくせー」
ってなってインターフェイス化せずに書いてしまう事が多々あったりします。
実際問題、わざわざインターフェイス化する程の事でもないものをそうしたって意味がないので、使いどころ、という要素はあります。
その辺りの見極めは僕もまだまだ甘いですが、経験を積めば積むほど
「ここはインターフェイス化しておいた方が後々楽かなー」
みたいな見極めが出来る様になっていくんだと思います。

終わり

というわけで、インターフェイスを実際に使った例でした。
他にも色々プログラムのノウハウを書くかどうかは未定ですが、気が向いたらまた色々書くかも知れません。

開発する皆様、お互い頑張りましょう!
僕も頑張ってプログラミングします!

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

1 2 3 4 5 6 7

月別アーカイブ

記事を検索