ReactHooksを勉強し始めた(1週間くらいたった)ので途中まで記録
部署移動があってゲーム開発からインフラよりの人になった。 AWSの資格取ったりいろいろあったが、今は趣味(友達の影響)でReactの勉強をしている 例によってUdemyの講座を利用しているのだが、結構情報量が増えてきたので備忘録を残す
ReactHooksについて
まずReactというものがある。これはフロントエンド向けのJavaScriptライブラリのことらしい。ちなみに僕はjsはまったくわからん。 htmlとcssはなんか一時やろうとして途中でめんどくさくなって投げだしたのだが、その程度でも知識がないと学習きついかも。以下概要 https://www.webstaff.jp/guide/trend/webit/react/
Webアプリ作ろうと思ったときに使えるいろいろ便利なものという認識。 なんかよく知らんがこれやっておけばフロントエンド側は大体できるらしい。
これを使って綺麗なフロント側をつくる。あくまでフロント側なのでバックエンドは別途作成が必要。 友達はMicrosoft Azureとかのクラウドでいろいろやってるらしい。僕はあずーる分らんからバックエンドはAWSで作る予定。
フロント側、今までC#やってきたからそれ使えばいいんじゃね?という気持ちもあった。 が、僕はアプリ開発じゃなくてUnityの内部コード作ってただけなのでガワの知識がナイ。 あと今までなんどかPythonのプロジェクトとか作ろうとしたときに開発環境整える時点でダルすぎたので、あんまり使いたくない 少し触った感じReactの方がめちゃくちゃ分かりやすいのでこれで行きます。
開発環境の構築
やることは多いが、比較的楽。一個一個があまり重くないので。
・Node.jsの最新LTS版をインストールする ・コマンドプロンプトでnpxコマンドを使って任意の改装にreactプロジェクトフォルダを作る ・Visual Studio Codeを入れる ・VSCodeでプロジェクトフォルダを開く ・ターミナルを開いてnpm startコマンドを入力 ・reactの初期画面(というかブラウザ表示できる最初のテンプレート画面みたいなやつ)がブラウザで起動する ※ちょこちょこ拡張機能入れたりがある ここまでが準備
プロジェクトフォルダー構造
プロジェクトフォルダ内のsrcフォルダに、index.html, .css, .js などが存在する。この辺は基本いじらなくていいみたい(少なくとも現時点までは) index.jsを見ると、App.jsを参照し、これをhtmlに飛ばしていることが分かる。 要するにApp.jsでどういう表示をしたいかを書いていけばいいということらしい
Functionalコンポーネント
classコンポーネントというのもあるが、ReactHooksではFunctionalしか使わなくて大丈夫(そこがウリらしい) classと対比されることから、処理の塊を指すとみてよさそう Reactの基礎【コンポーネント】 だいたいあってるっぽいな...処理やデータの扱いが記述されたオブジェクトのことを指す。 これの組み合わせでページを作っていける。
コンポーネントにデータと処理がまとまっていたりするので拡張やメンテナンスが容易でいいよねというようなことを言われていた気がする Functionはまあ、メソッドだね
用語
Props:引数と思ってよい。propertiesの略 イベントハンドラー:ボタンオブジェクトのonClickとかonChangeとか。これはC#のイベントハンドラーと大体一緒。発生したイベントに応じてハンドラを引数として渡してくれる仕組みがあるので、これを使っていろいろやろうねって話 state:クラス(コンポーネント)内変数みたいなもの。厳密には子や孫が干渉できることになるが、まあざっくりそんな感じ useState:stateを更新するための関数。引数に受け取った値をstateにぶっこむ。 アロー関数:ラムダ式での関数定義のこと。"関数名= (引数) => {処理}"のアレね。 useEffect:レンダリングの度に実行される処理。Update的なアレ。すべてのレンダリングで反応するが、第二引数に[(監視するstate)]としておくことで、レンダリング前後でそのstateに変化があった場合のみ処理させる、ということができる。(レンダリング)=>(ユーザー操作とか何らかのトリガーでstateが変わる)=>(レンダリング※useEffectの監視対象なら実行)という流れ useContext:コンテキストで囲われたコンポーネントたちは、その範囲内で共通のvalueを使用可能になる。プロバイダーとコンシューマーという概念があり、createContextでコンテキストのプロバイダーを作成できる。囲われたコンポーネント側でコンシューマーとして使用を宣言すれば、valueを参照可能になる useReducer:stateに対し、あらかじめトリガー&それによってstateをどう変更するかを作成しておける(この定義をreducerとよぶ)。useStateとの違いは、useStateは引数を単にセットするだけだが、useReducerは引数を受けて何をするか、という風に広範な使い方を決めておける。
書き忘れていたが、変数を定義するときにいちいち型を指定しなくていい。勝手に向こうで扱ってくれる。これはpythonっぽいね
ライブラリや機能の話
APIデータを取得する方法
大きく二つある。 axiosという外部ライブラリを使う方法と、javascriptのfetchを使う方法。
axios.get(API取得用のURL) .then(res => { // 何か素敵な処理 }) axiosを使うと、jsondata形式でデータを取得できる。これをstateに入れておくことで、適宜情報の取り出しができる。
fetch(API取得用のURL) .then(res => res.json()) .then(res => { // 何か素敵な処置 }) fetchを使う場合、帰ってくるのがHTML型のデータなので、使い勝手を考えて.json()でjson形式に変換する。
useReducerとuseContextの組み合わせ
useReducerを使用可能なスコープは、普通にやるとreducerを定義したコンポーネント内に限定される。 親コンポーネントで作成したreducerを子以下のコンポーネントでも呼び出し、親のstateに何かしらの状態変化を起こせるようにできたら便利だね、ということでuseContextを併用して実現する。
AppContextのProviderで、引き渡すvalueを宣言する際にstate変数と、それに対するdispatch(reducer処理)を設定しておく。 AppContextコンポーネントで囲われた
VisualStudioでaws開発しようとしたけど無理だった
lambdaのサンプルコードを実行するとaws-sdkパッケージが見つからないと表示される。
docs.aws.amazon.com このチュートリアルにしたがってaws-sdkパッケージをインストールする
https://www.nuget.org/profiles/awsdotnet
どれを入れればいいか分らんのでとりあえずAWSSDK.Coreというやつをインストールしてみる
dotnet add package AWSSDK.Core --version 3.7.300.25
やってみたら「プロジェクトが見つかりませんでした」とエラーが出る
nugetパッケージマネージャーをアンインストール->再インストールしてみる teratail.com
無理でした(4日くらい格闘した)
結論:aws開発にVisualStudioは使うな(環境構築が本当にだるい)
VisualStudioからAWS関連の開発をするための環境を整えるDay2,3
とりあえずLambda向けのスクリプトの作り方を勉強する必要がある。 公式チュートリアルを見つけたのでやってみる
cドライブ配下にMyLambdaAppディレクトリを作成 その配下にslotassets.zipを解凍する。slotassetsフォルダが作成され、その中にいろいろ入った状態になる。 C:\MyLambdaApp/slotassetsができる その中にAWSの認証情報を用いてjsonファイルを作成する必要がある
docs.aws.amazon.com このチュートリアルに従って認証情報を取得する
でもIAMロールってどこから見るんだっけ... docs.aws.amazon.com まずS3で作る必要があるっぽい
だめだやり方がわからん ちゃんと本とか買ってやるか...マジで環境構築とかの本筋じゃないところをやるのが一番だるい
aws向けの開発環境を整える方法を調べてみた。まずはこれに沿ってやってみよう aws.amazon.com
IAMで新しく開発用にユーザーを作成した。








とりあえずここまででいいのかな?引き続き頑張る所存
Visual StudioでのAWS開発環境構築(C#でやりたかったけどjs使うことにした)
あくまで備忘録
初めはC#で開発しようと思った。他に書ける言語ねえし。 とりあえず公式ドキュメントに書かれているままにdotnetのなんやかんやをインストール docs.aws.amazon.com
でも、Lambdaのテンプレ関数使った結果、ランタイムがnode.jsになってるし(不本意)、node.js向けにJavaScriptでいろいろ作る方がナレッジがいっぱいでてきそうだな... ということでnode.js触ってみることに方向転換。VisualStudioでの開発環境を整える
ちょっと調べたらVisualStudioでAWS向けの開発が快適になる拡張機能が出てきたからとりあえず入れておく。js扱う上では必須ではない。 「これインストールできひんで~」というエラーが出た。最近家で開発とか全くやってなかったからVSのバージョンが古くなってたみたい。更新したらすんなり入った。
役に立つのかはこの時点では知らない。インストールしたら思考停止再起動や

さて、jsの開発環境整えるで ぐぐったらこんなんでてきたので参考にする
とりあえずnode.jsをインストール。VS入れたときについでに入れたような気もするけどまあええやろ... こういうときハイスペ大容量PC買っておいてよかったなと思う。

そしたらvisual studio installerからnode.js開発を構成に追加して...
なんかこう、アフィリエイトかってくらいリンク貼ってるな。
プログラミング独学~とかってさ~~~コードの勉強始める前のこの手の環境設定が一番だるいよな~~~ インストールエラーとかが解決できなかったらその時点で勉強やめるよな~~~めんどくせ~~~~
気を取り直してvisual studio起動。[新しいプロジェクトの作成]からテンプレート選んで...あっ


ゲーム制作会社に入ったことだし、VTuberでもみるか
久々すぎる。
過去に作ったしょーもないゲームのおかげもあって(あったか?)無事ゲーム制作会社に入社した。もうすぐ半年が経つ。
新卒で入社した会社の副社長が言っていた通り、「人間が変わるには環境を変えるしかない」という言葉の通り、環境を変えることで否応なしに毎日UnityとC#を使ってコードを書きまくっている。ありがてぇありがてぇ…
さて、最近は通勤時間にVtuberの動画を見るのが日課になっている。あなたの推しは誰ですか?僕は兎田ぺこらと猫又おかゆを推しています。
さて、VTuberを支えているのはUnityらしいということを風のうわさで聞いた。
Live2Dという入力された音声によって自動で2Dのキャラクターが動くやつを使っているらしく、しかもこれはUnityをPCに入れてさえいれば素人でも触ることができるらしい。ちょうどいいのでこれをぽちりながらいろいろやってみようと思い立った。
すでに1週間かかった
と軽い気持ちで手を出してみることにしたが、初期設定?の時点でめちゃくちゃ苦労した。同じ轍を踏む人が減ればいいなというのと、備忘録としてやったことの記録をつけておく。
今は「設定された音声ファイルに合わせてキャラが口パクする」というところまでいった。
ここまで一行もコードを書いていないので、私と同レベルの方も安心してほしい。
ただし、なんか知らんが全然動かんくて一度は匙を投げようとしたので、粘り強さだけは持っておいてほしい。
1. まず、Unityの推奨バージョンをインストールします
いろいろ振り返ると、ここが最重要だった。僕は自分での学習のためにUnity2020.~~とかのバージョンを使っていたが、どうも配布されているSDK(Live2Dを動かすための魔法のプログラム群。無料。なんで???)をインポートするときはUnityの推奨バージョンである2019.4~~くらいのを使ったほうがいいみたい。この辺は多分に憶測を含むが、いいからこれ使っといて。
2.こちらの記事を参考に、モデルデータのインポートまでやる
qiita.com多分なんだけど、この記事が少し前に書かれたこともあっていろいろ現在の仕様ではすんなり模倣できないんじゃないか。
この記事通りに貫いてやってみてもいいんですけど、僕は「プレゼンスを上げる」の「口パクの実装」のところでつまづいた。
具体的に言うと、入力された音声に合わせて口が動かなかった。
パラメータを見ると音声に応じて値を書き換えてはいるのだが、Gameビューでは口がほとんど動かなかった。
どのくらい動いていなかったかというと、カメラで5倍くらいに拡大してようやく「動いてる気がする」というレベルで動いていなかった。
途中からはこちらの公式リファレンスを参考に
docs.live2d.comというわけで、一度Unityをアンインストールして、使用するSDKやモデルデータをすべて再インストールしてゼロからプロジェクトを作り直した。そしてモデルの配置の後はこのページを参考にしていろいろと設定をした。
クッソ雑だがこれでとりあえず音声に応じて口がパクパクするようになった。
Live2Dのいいところは、「公式が日本」というところだと思う。
僕程度の英語力では海外の記事がヒットされても一ミリも理解できねえ。
僕のような無課金勢でも手厚く対応してくれるので積極的に公式を見ていこう。
ということで、もし困っている人がいたら
・とりあえずUnity再インストールして推奨バージョンにしよう
・なんかおかしいと思ったら大人しく使用するいろいろなファイルを再インストールしよう
・無理だったら公式を頼ろう。多分この分野、作る人より使う人の方が多いからネットで見つかる情報は玉石混合だ
以上。
UniRxを勉強しよう8(完結)
めっちゃくちゃ間が空いたが、ようやく電卓アプリがひと段落したのでコードを公開してみる。
Githubにも上げているが、もしGithubからいろんな情報が流出したら怖いのでいったんここで公開する。
こんな感じになりました
入力検知クラス
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using System;
using UnityEngine.UI;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Diagnostics;
public class PassPushedButton : MonoBehaviour
{
[SerializeField] List<Button> NumberKeys;
[SerializeField] List<Button> operaterKeys;
[SerializeField] List<Text> texts;
//このクラスからOnNextで別クラスに処理を渡せるようSubjectを用意
private Subject<string> sendCalcSubject = new Subject<string>();
private Subject<int> sendOperaterSubject = new Subject<int>();
//なんだっけこれ…プロパティ?外部クラスからアクセス(getのみ)できるようにしておく
public IObservable<string> NumberKeyClicked
{
get { return sendCalcSubject; }
}
public IObservable<int> OperaterKeyClicked
{
get { return sendOperaterSubject; }
}
void Awake()
{
for (int i = 0; i < NumberKeys.Count; i++)
{
SetMonitoringNumberKeyClicked(i);
}
for(int i =0; i < operaterKeys.Count; i++)
{
SetMonitoringOperatorKeyClicked(i);
}
}
void SetMonitoringNumberKeyClicked(int i)
{
NumberKeys[i].onClick.AsObservable()
.Subscribe(count => sendCalcSubject.OnNext(texts[i].text))
.AddTo(gameObject);
}
void SetMonitoringOperatorKeyClicked(int i)
{
operaterKeys[i].onClick.AsObservable()
.Subscribe(count => sendOperaterSubject.OnNext(i))
.AddTo(gameObject);
}
}ディスプレイへの表示クラス
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using UnityEngine.UI;
using System.Diagnostics;
public class ShowDisplay : MonoBehaviour
{
//メッセージのやりとり対象はInspector画面から設定する。
public Text displayPanelText;
private int operatorFlg = 0;
[SerializeField] private PassPushedButton passPushedButton;
[SerializeField] private Caculater calculater;
void Awake()
{
//監視対象スクリプトからOnNextが飛んで来たら下記Subscribe処理を実行
passPushedButton.NumberKeyClicked
.Subscribe(KeyCode => ShowToDisPlay(KeyCode))
.AddTo(gameObject);
calculater.CalculateResult
.Subscribe(result =>
{
displayPanelText.text = result;
operatorFlg = 1;
})
.AddTo(gameObject);
}
private void ShowToDisPlay(string value)
{
//イコールの後に数値が入力されたとき
if (operatorFlg == 1)
{
//小数点が入力されたら
if (value == ".")
{
//小数点が既に存在していたら何もせずに終了
if (displayPanelText.text.Contains(".") && value == ".") return;
//表示中の数字に小数点をつける
displayPanelText.text += value;
}
//整数が入力されたら
else
{
//ディスプレイを一度クリアする
displayPanelText.text = "";
}
operatorFlg = 0;
}
//小数点が二つ以上なら入力を無視する
if (displayPanelText.text.Contains(".") && value == ".") return;
//入力値が小数点でなければ先頭の0は消す
else if (displayPanelText.text == "0" && value != ".")
{
displayPanelText.text = value;
}
else
{
displayPanelText.text += value;
}
}
}計算クラス
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using System;
using UnityEngine.UI;
public class Caculater : MonoBehaviour
{
//メッセージのやりとり対象はInspector画面から設定する。
public Text displayPanelText;
[SerializeField] private PassPushedButton passPushedButton;
private Nullable<double> calculatedValue;
private Nullable<int> operationSymbol;
private string displayText;
private Subject<string> sendCalculateSubject = new Subject<string>();
public IObservable<string> CalculateResult
{
get { return sendCalculateSubject; }
}
void Awake()
{
//演算記号の入力を検知
passPushedButton.OperaterKeyClicked
.Subscribe(operateKeyNum => Calculate(operateKeyNum))
.AddTo(gameObject);
}
private void Calculate(int newOperationSymbol)
{
displayText = displayPanelText.text;
//正負の入れ替えが選択されたとき
if (newOperationSymbol == 7)
{
displayText = (double.Parse(displayText) * -1).ToString();
sendCalculateSubject.OnNext(displayText);
}
//Clearが入力された場合
else if (newOperationSymbol != 5)
{
//数値・演算記号が共に入力済みだったとき
if (calculatedValue.HasValue && operationSymbol.HasValue)
{
//+
if (operationSymbol == 0) calculatedValue += double.Parse(displayText);
//-
if (operationSymbol == 1) calculatedValue -= double.Parse(displayText);
//×
if (operationSymbol == 2) calculatedValue *= double.Parse(displayText);
//÷
if (operationSymbol == 3)
if(double.Parse(displayText) == 0 )calculatedValue = 0;
else calculatedValue /= double.Parse(displayText);
//=
if (operationSymbol == 4) calculatedValue = double.Parse(displayText);
//今回入力された演算記号を格納
operationSymbol = newOperationSymbol;
//AC(演算記号リセットのため、これだけ判定タイミングをずらす)
if (operationSymbol == 6)
{
calculatedValue = 0;
operationSymbol = null;
}
//showdisplayに計算結果を送信する
sendCalculateSubject.OnNext(calculatedValue.ToString());
}
else
{
calculatedValue = double.Parse(displayText);
operationSymbol = newOperationSymbol;
sendCalculateSubject.OnNext(calculatedValue.ToString());
}
}
//Cが入力されたとき、変数の値は書き換えずにディスプレイのみクリアする
else sendCalculateSubject.OnNext("0");
}
}以上!
修正点はいくつかあるが、大きなところとしては
- 「イコール」で結果表示後に小数点を入力するとディスプレイ上の数値がクリアされる点を改善
- 0で除算を行った場合に「Err」と表示される点を改善
という修正を実施した。
自分で動かした範囲ではうまいこと動いている。
さて、今回電卓を作るなかでUniRxで四苦八苦したわけだが、次第に慣れてくるとInspectorをポチポチしなくてもイベント関連の処理を定義していけるのは結構便利だった。
使いこなせているかというとまだ微妙だが、いろいろなサイトを参考にしたおかげで何とか形になった。
今からUniRxを勉強する人はここまでで紹介した記事を参照してみたらやりやすいと思います。
とりあえず、簡単だが今日はここまで!
UniRxを勉強しよう7
は~~~~~~い
今日もやっていくぞ!
完成までの流れ
1. まずは簡単に見た目だけ作る
2. ボタンを押下した際にこれを検知する
3. 押下されたボタンから数値や記号を取得する
4. 引数に渡された数値がディスプレイに表示されるようにする
5. 検知した数値や記号から四則演算を実施できるようにする
6. 見てくれを整える
7. 書き出す
昨日は5を実現するためのフローチャートを作り、機能を考えるところで終わっていた。今日はその実装と微調整だ。
完成したものがこちらになります
まず概要だが、今回作成した電卓は大きく3つのスクリプト(クラス)で動作が決まっている。
1. PassPushedButton
電卓のボタンが押下されたことを検知する
2. ShowDisplayButton
電卓のディスプレイに値を表示する
3. Calcurater
計算の実処理を行う
まず一つ目!PassPushedButtonから
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using System;
using UnityEngine.UI;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
public class PassPushedButton : MonoBehaviour
{
[SerializeField] List<Button> buttons;
[SerializeField] List<Button> operaterKeys;
[SerializeField] List<Text> texts;
//このクラスからOnNextで別クラスに処理を渡せるようSubjectを用意
private Subject<string> sendCalcSubject = new Subject<string>();
private Subject<int> sendOperaterSubject = new Subject<int>();
//なんだっけこれ…プロパティ?外部クラスからアクセス(getのみ)できるようにしておく
public IObservable<string> KeyClicked
{
get { return sendCalcSubject; }
}
public IObservable<int> OperaterKeyClicked
{
get { return sendOperaterSubject; }
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void Awake()
{
for (int i = 0; i < buttons.Count; i++)
{
ButtonCheck(i);
}
for(int i =0; i < operaterKeys.Count; i++)
{
OperatorKeyChecked(i);
}
}
void ButtonCheck(int i)
{
buttons[i].onClick.AsObservable()
.Subscribe(count =>
{
//定義したSubjectからOnNextでメッセージを出す
sendCalcSubject.OnNext(texts[i].text);
})
.AddTo(gameObject);
}
void OperatorKeyChecked(int i)
{
operaterKeys[i].onClick.AsObservable()
.Subscribe(count =>
{
sendOperaterSubject.OnNext(i);
})
.AddTo(gameObject);
}
}次にShowDisplay。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using UnityEngine.UI;
public class ShowDisplay : MonoBehaviour
{
//メッセージのやりとり対象はInspector画面から設定する。
public Text displayPanelText;
private int operatorFlg = 0;
[SerializeField] private PassPushedButton passPushedButton;
[SerializeField] private Caculater calculater;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void Awake()
{
//監視対象スクリプトからOnNextが飛んで来たら下記Subscribe処理を実行
passPushedButton.KeyClicked
.Subscribe(KeyCode => ShowToDisPlay(KeyCode))
.AddTo(gameObject);
calculater.CalculateResult
.Subscribe(result =>
{
displayPanelText.text = result;
operatorFlg = 1;
})
.AddTo(gameObject);
}
private void ShowToDisPlay(string value)
{
//演算記号が入力されたら一度ディスプレイをクリアする
if (operatorFlg == 1)
{
displayPanelText.text = "";
operatorFlg = 0;
}
//入力値が少数点でなければ先頭の0は消す
//else
if (displayPanelText.text=="0" && value !=".")
{
displayPanelText.text = value;
}
else
{
displayPanelText.text += value;
}
}
}最後にCalcurater
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using System;
using UnityEngine.UI;
public class Caculater : MonoBehaviour
{
//メッセージのやりとり対象はInspector画面から設定する。
public Text displayPanelText;
[SerializeField] private PassPushedButton passPushedButton;
private Nullable<double> calculatedValue;
private Nullable<int> operationSymbol;
private string displayText;
private Subject<string> sendCalculateSubject = new Subject<string>();
public IObservable<string> CalculateResult
{
get { return sendCalculateSubject; }
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void Awake()
{
//演算記号の入力を検知
passPushedButton.OperaterKeyClicked
.Subscribe(operateKeyNum => Calculate(operateKeyNum))
.AddTo(gameObject);
}
private void Calculate(int newOperationSymbol)
{
displayText = displayPanelText.text;
if (newOperationSymbol != 5)
{
//数値・演算記号が共に入力済みだったとき
if (calculatedValue.HasValue && operationSymbol.HasValue)
{
//+
if (operationSymbol == 0) calculatedValue += double.Parse(displayText);
//-
if (operationSymbol == 1) calculatedValue -= double.Parse(displayText);
//×
if (operationSymbol == 2) calculatedValue *= double.Parse(displayText);
//÷
if (operationSymbol == 3) calculatedValue /= double.Parse(displayText);
//=
if (operationSymbol == 4) calculatedValue = double.Parse(displayText);
//今回入力された演算記号を格納
operationSymbol = newOperationSymbol;
//AC(演算記号リセットのため、これだけ判定タイミングをずらす)
if (operationSymbol == 6)
{
calculatedValue = 0;
operationSymbol = null;
}
//showdisplayに計算結果を送信する
sendCalculateSubject.OnNext(calculatedValue.ToString());
}
else
{
calculatedValue = double.Parse(displayText);
operationSymbol = newOperationSymbol;
sendCalculateSubject.OnNext(calculatedValue.ToString());
}
}
//Cが入力されたとき、変数の値は書き換えずにディスプレイのみクリアする
else sendCalculateSubject.OnNext("0");
}
}
各コードについての解説をコメントで書いた。
今回はフローチャートを作成してからスクリプトを作成したのだが、これがとても楽しい…
先に色々考えておいて、コードを書いてみてカチッと動きがはまるとたまらん!(まあ適宜ロジック修正したけど)
期限は明日となっているのでコードをきれいに書きなおし、また見た目も整えていきたいと思う。