2014年6月12日木曜日

SKActionを使ったサウンドの再生でハマった話。割り込み後に再生しなくなるなど。

環境:iOS 7.1.1, XCode 5.1.1
状況:SKActionを使用した音声がシステム割り込みからの復帰後に再生しなくなる

SpriteKitを使ったアプリでSEの再生をSKActionのサウンド機能を使って再生していました。
音量調節が出来ないのが難点だけど実装が楽で実に有難い。
と思っていたら思わぬ罠が。
着信などのシステム割り込みからの復帰後にSEが再生しなくなる。
調べたら出てきました。

症状
http://stackoverflow.com/questions/22978547/handling-interruptions-in-sprite-kit-cant-get-sound-effects-via-skaction-pla
対処
http://iknowsomething.com/ios-sdk-spritekit-sound/

ま た バ グ か 。

なんか遭遇しすぎて逆に本当にSpriteKit自体のバグなのか、自分が何か見落としてるだけじゃないかと不安です。
(もう一個、別の件で詰まって調べたら「SpriteKitのバグっぽい」と言われてた事があったんですが失念。思い出したら書きます。)

ともかく動いてくれなきゃ困るので上記の対策を参考にさせて頂くことに。
SKActionがBlocksを実行できることを利用した実装なので、末端のコードを書きなおさなくていいのが嬉しい。
有り難や有り難や。
というか、コレがアリならもうSKActionはなんでもありですね。

ひとまず盲目的に実装したところ、アプリ起動中にコントロールセンターを引っ張りだすと deactivateAudioSession でエラーの際に再帰呼び出しをかけてるところでエラーがいつまでも解消せず、再帰が止まらなくなりタイムアウトで落ちる。
Audio Session Programming Guide には「割り込み発生時にはシステム側で AudioSession を停止する」って書いてあるし、特定のアプリ以外は明示的に停止する必要はないらしい。 今回は特に必要でもないので soptAudio 以外では deactivateAudioSession を呼ばないように変更。
とりあえず期待通りの挙動になりました。

Appleさん、新言語のついでに bug fixも早急にお願いします。 せっかくのフレームワークも結局既存の複雑なコードを呼び出すんじゃ意味ないっス(泣)

2014年5月8日木曜日

SpriteKitでハマった話。 iOS7.1, SpriteKit, SKShapeNode, EXC_BAD_ACCESS的な。

次に何かリリースしようとSpriteKitを使って簡単なゲームを作っていたところハマりました。
先に書いておくと未解決です。ボスケテ。

環境:iOS 7.1.1, XCode 5.1.1
状況:SKShapeNodeを子に持ったSKSceneがメモリから解放される時にEXC_BAD_ACCESSで落ちる場合がある

SKShapeNodeを子に持ったSKSceneをビューで保持していない状態で別のシーンに遷移したり、意図的に開放してやったりすると
SKCSprite::removeSubSprite(SKCSprite*)
の呼び出しでEXC_BAD_ACCESSで落ちる。

こうなって
こうなる

試しにXCodeのSpriteKitのテンプレートに丸いSKShapeNodeを1つ追加してサイズと背景色だけ設定したSceneに遷移しても再現しました。

自分の使い方が間違っているのかと思い、ググってみると何やらiOS7.1固有のSpriteKitのバグかもとか言われてる・・・?
http://stackoverflow.com/questions/22399278/sprite-kit-ios-7-1-crash-on-removefromparent

確かに7.1の実機,シミュレーターだと再現し、7.0のシュミレーターだと再現しない様子。

試しに別クラスからShapeNodeを保持するようにして、上記フォーラムのやり方で先に開放するようにしても改善せず。
メモリ位置の関係なのか、ShapeNodeの生成を
・呼び出し箇所で直書き
・同一クラス内で関数化して呼び出し
・サブクラス経由で生成
と変えてみると、再現率が変わったりと不安定。
Zombiesにも引っかからないし。
いっそ全てのシーンをビューから保持したままにしてやろうかとか、頭を抱えてしまいました。

SKShapeNodeのサブクラスや該当のSKSceneのサブクラスで
- (void)dealloc
{
    if(self.children.count > 0){

        [self removeAllChildren];
    }
}

とかやっても結局スーパークラスで
SKCSprite::removeSubSprite(SKCSprite*)
が呼ばれてしまい駄目っぽい。
SKShapeNode本体にクラス拡張をしてみるとやっぱりこいつのdeallocで落ちている。
一応、他のSKNodeの純正サブクラスでも試しましたが、ShapeNode以外は問題ない様子。
試行回数がそれほど多くないので断言は出来ませんが。
つまり

・SKSceneがAutoReleaseで解放される際に
・開放されるSceneに含まれるSKShapeNodeにdeallocが呼ばれる
と、
・メモリの状態によりEXC_BAD_ACCESS が起きる場合がある

という状況らしい。
・・・らしい。むむむ。

海外のフォーラムでも話題になっていましたが、SKScene自体がメモリ周りが不明瞭な部分があるようで、その関連なのでしょうか?

どうにも先に進まないのでひとまず諦めて

1.CAShapeLayerでオフスクリーンに描画
2.オフスクリーンの内容をCGImageに変換
3.できたCGImageを使ってSKTexture作成
4.SKTexture使ってSKSpriteNodeを作成

とかなんとかしてSKShapeNodeは使わずにSKSpriteNodeで代替することに。
あまりに悩みすぎて「Shape」と名の付くクラスを使うのに戦々恐々としましたが、CALayerは問題ない様子。そりゃそうだ。

結局解決していない上に確定情報がなにもないというグダグダな記事ですみません。

「俺、原因知ってるZE!」
「それはお前が悪いだけだ」
「調べ方が足りないだけで解決策が既出」
など、ご指摘あればコメントいただけると幸いです。

2014年1月7日火曜日

Multi Life Counter 2.0.2 アップデート


・トレーディングカードゲーム用ライフカウンター
・2桁から5桁までの表示/入力に対応し、
 様々なTCGで使用可能
・カウンター履歴の参照と保存が可能

[詳細はこちら]




以下の修正を行いました

・設定画面で一部コンポーネントのアニメーションが不自然だった問題を修正しました

以上

ダウンロードして頂いた方、本当に有難うございます。

割りと小さな内容のため、本来であれば前回のアップデート内容と同時に申請したかったのですが、今回はコードの修正と同時にiAdの設定変更も行ったため、審査が長引いた場合に誤字が表示され続けるのがあまりに恥ずかしかったため前回のアップデートを緊急で先出ししました。

今までだとアップデートを申請した場合、状態が In Reviewになってから大体数時間程度でReady for saleになることが多かったのですが、案の定、今回はIn Reviewから3日程度かかっていました。
有難いことに ver 2.0.0 のアプデート以降ダウンロード数が増加しており、思ったより多くの方々に醜態を晒すことになっていたようで、分けて正解でした(汗)

しかもver 1.xの頃よりアップデート数の割合も大幅に増えており、実際に使って頂いている方が増えたのかな?と妄想してみたり。偶然かもしれませんが。
重ね重ね、ありがとうございます。

2013年12月31日火曜日

Multi Life Counter 2.0.1 アップデート


Multi LifeCounter / マルチライフカウンター
・トレーディングカードゲーム用ライフカウンター
・2桁から5桁までの表示/入力に対応し、
 様々なTCGで使用可能
・カウンター履歴の参照と保存が可能




以下の修正を行いました。

・日本語版にて一部誤字を修正

以上

誤字に気がついた時には時既にReady for sale。
すごく焦りました(汗)
大変失礼致しました。

2013年12月25日水曜日

Multi Life Counter 2.0.0 アップデート


Multi LifeCounter / マルチライフカウンター
・トレーディングカードゲーム用ライフカウンター
・2桁から5桁までの表示/入力に対応し、
 様々なTCGで使用可能
・カウンター履歴の参照と保存が可能





以下の修正を行いました。

・デザインを変更しました
・カウンター画面の操作方法を変更しました
・カウンター画面から履歴が確認できるようになりました
・対戦ごとの履歴を保存できるようになりました
・カウンター画面を除く一部画面に広告が表示されます
・一人分のカウンターのみ表示する画面を廃止しました

以上

ダウンロードいただいている方、本当に有難うございます。
不具合やご意見がありましたらアプリ詳細ページ等でコメントして頂ければと思います。
以前からアップデート分でも告知させて頂いた通り、大幅な修正を行いました。

・デザインの変更
iOS7に合わせてフラットなデザインに変更しました。


トップ画面も変更しました。

一人分のカウンターのみ表示する画面の廃止
デザイン画面デザインと入力方法の変更に伴い、必要性が感じられなくなったため、以前のバージョンであった「一人分のカウンターのみを表示する画面」は廃止しました。

・入力方法の変更
カウンターの画面で数字を減らしたり増やしたりする操作方法を変更しました。
今までは
「表示されている画面から入力用の画面へ移動してから変更、確定、戻る」
という流れでしたが、カウンターの画面から直接数値の変更ができるようになりました。

カウンターの画面で
ライフ(変更したいカウンター)をタップするとボタンがでます。
減らしたり増やしたりして、
もう一回ライフをタップすると戻ります。

どうでしょうか。
桁数が多いとこんな感じ。

以前のバージョンで課題だった

 - -1 / -5 ボタンで楽に入力したい
 - 画面にたくさんのボタンを配置するスペースがない
 - ゲームに必要な桁数を自由に設定したい

を解決しようとした結果、こんなふうしてみました。
この仕様は他の作者様の「最初から画面に -1 / -5 ボタンが出ている」カウンターに比べると「ボタンを出す/消す」操作が多いですが、逆にこの

「ボタンを消す」

ときにカウンターの履歴を更新しているため、ログを確認する機能を付けることができました。

・ログの参照、保存機能の追加
カウンター画面で中央上部のログボタンを押すことで、その時点までのカウンターの履歴を確認することが出来ます。
これを押すと、
下から ニュっとログが出ます。

リセットボタンを押すか、リセットせずにトップ画面に戻ろうとすると保存するか聞かれるので「保存する」を選べばそのゲームのログが保存が出来ます。
保存されたログはトップ画面の「保存ログ」から確認ができます。

一覧画面では名前の変更、削除ができます。
・iAdについて
今回から一部画面に広告が表示されるようになりました。
ご理解、ご協力を頂ければ幸いです。
とかいいつつ、iAdだけだとそもそもあまり表示されない・・・?
iAdを表示させるためにUITableViewControllerをUIViewControllerで実装しようとした上でUITableViewCellにテキストフィールド仕込んだら割りと死にそうになった話とかはまた別で記事にするでしょう。
調べてもすぐにヒットしなかったので備忘録的に。

2013年11月24日日曜日

Multi Life Counter 1.0.2 アップデート



Multi LifeCounter / マルチライフカウンター
・トレーディングカードゲーム用ライフカウンター
・2桁から5桁までの表示/入力に対応し、
 様々なTCGで使用可能

[詳細はこちら]



以下の問題を修正しました。
機能の変更、追加はありません。

・設定画面でサポート範囲外の値が入力された場合の処理が不適切だった問題を修正

以上

ダウンロード頂いている方、ありがとうございます。

バグというほどではないのですが内部処理がよろしくなかった部分を修正しました。
また、アップデートの文章でもお知らせさせて頂いていますが、次回のアップデートでデザインを大きく変更するする予定です。

・iOS7に合わせたフラットデザイン化
・入力の簡素化

を行う予定で、デザインの変更についてはiOS7に寄せたデザインに変更する予定です。
また、最近Storeのレビューで

「タップすると1ずつ減るようにして欲しかった」

とのご意見をを頂きました。
レビューを書いて頂いた方、本当に有難うございます。
このご意見、至極ごもっともで、開発中もとても悩んだんです。

例えばMagic: the Gatheringのようなライフの大きくないゲームの場合、
・ライフの表示もしくは同一画面の中の+1/+5とかのボタンをクリックで増減
にすれば
・画面遷移を伴わないので操作が煩わしくない
・分かりやすい
・見やすい
と、いいところだらけです。
実際、他のアプリを見てみてもそのような操作になっているカウンターが多いですね。

今回、敢えてそうしなかったのは
「ライフ桁数が大きいゲームにも対応したものを作りたかったから」
です。
乱暴な例えをすると初期ライフ8000のゲームで2000ダメージを食らった場合、2000回押すのかという問題。
「+5」ボタン作っても400回。
他のアプリの中には「+100」「+500」「+1000」「+5000」…
と、たくさんボタンを作られている方もいらしゃいました。
ただ、ボタンを増やすと画面スペースが足りなくなるわけです。
各コンポーネントの表示も小さくせざるを得なくなりますし。

この問題に際して「UIPickerViewを使ったらいいんじゃね?」という着想から作り始めたのが今回のアプリだったわけです。
UIPickerView iOS7 / iOS6
桁ごとに手動で回しちゃえば問題を解決できるんじゃないかと。
が、実際に使ったり周りで使ってみてもらったりするとやっぱり使いづらい部分が浮き彫りになってきました。
特に
・操作が煩雑、手順が多い
ということ。
手動で回すほかに、ダメージ値を直接入力できるようにもしたせいで専用の入力画面への遷移が発生し、入力から完了までの手順がやたら多く、かつ解りづらくなってしまいました。

というわけで、この点を解消するべくデザインと操作の変更を進めています。
画面遷移を伴わずに入力できるようにし、手順を減らし、かつ画面もごちゃごちゃしないようになる予定です。
1人表示の画面も大幅に変更予定。

使用感に対してご意見、ご要望あればコメントいただけると嬉しいです。
また、今後の改善や機能追加の方向性を見定めるために
「どのTCGで使おうとしてダウンロードして頂いたのか」
などのコメントも頂ければ有難いです。

そして更新の文面で告知させて頂いているもう一点。
iAdの勉強も兼ねて広告の挿入をさせて頂く予定です。
当然、対戦中に影響のないように、カウンター画面以外に表示させて頂くつもりです。
ご理解頂ければ幸いです。

2013年11月4日月曜日

感謝、1000ダウンロード。

完全に趣味でリリースさせて頂いたMulti Life Counter


Multi LifeCounter / マルチライフカウンター
・トレーディングカードゲーム用ライフカウンター
・2桁から5桁までの表示/入力に対応し、
 様々なTCGで使用可能

[詳細はこちら]



リリースから一ヶ月あまり。
10月29日の時点で1000ダウンロードを超えました。
ダウンロードしていただいた方、本当に有難うございます。

ほかのアプリに比べれば大したこと無い数だと思いますが、全くダウンロードされないことを覚悟していたので完全に予想外です。
日本のみならず海外からも多数のダウンロードをして頂いています。
やってよかったローカライズ。

ローカライズといえば、日本語UIがなんだか不格好に見えてしまう気がするのが何とかしたいのですが、どうしたものか。
しかもiOS7でコンポーネントがフラットデザインになり、特にボタンがボーダーレスになったことで日本語フォントでの表示によりいっそう気を使わなければならなくなった気がします。
理想を言えばアイコンだけですべての機能が分かってもらえるといいのですが、なかなかそうもいかず。。。
この辺りはアプリ自体のフラットデザイン化とあわせて検討したいと思います。

というわけで、これからもUIや機能の調整など、改善できそうな点は手を入れていくつもりです。
改善要望や不具合の発覚など、お気づきの点があれば当ブログのアプリのページのコメント欄よりご連絡頂ければと思います。
こんなアプリでも使って頂ける奇特な方がいらっしゃればお付き合い願えれば幸いです。