Skeyllのブログ

インディーデベロッパー

The GOD AIM(日本語)


f:id:Skeyll:20190815214136p:plain

f:id:Skeyll:20190815214353j:plain




アプリ情報

モバイルFPS向けのエイムトレーニングアプリ。
反動、カメラ感度、UIの設定、銃声、キャラクターモデルのオンオフが可能。
レーニングのモードは三種類。
ランキング機能あり(難易度Hardのみ)。
アプリサイズは20MB前後で、インターネットに接続していない場合でもプレイ可能。

モードの説明

youtu.be

Standard
・的がランダムに出現
・6回当てるごとに的の出現数が増加
・得点
当てた場合
10+(2*継続回数)

外した場合
マイナス5
継続回数のリセット


React
・的がランダムに出現
・10回当てるごとに的の出現数が増加
・得点
当てた場合
10+(2*継続回数)

外した場合
マイナス5
継続回数のリセット

当てずに的が消えた場合
マイナス5
継続回数のリセット


Track
・的がランダムに左右に移動
・停止するたびに移動速度が上昇
・得点
当てた場合
10+(継続回数)

外した場合
マイナス5
継続回数のリセット


ダウンロード

Android
play.google.com
iOS
公開次第追加

更新情報

ver 1.33
GooglePlayにログインするタイミングをMenu変遷時に変更
リーダーボードを修正(NameSpaceを追加)
x84への対応をやめる(スマホ1、時計っぽいのが5つ非対応に)

ver1.32
ゲーム内でスコア詳細だけを画像保存する機能を削除
プライバシーポリシーを詳細に更新(英、日のみ。中、韓はそのうち追加予定)
テーマダークに配慮してゲーム結果表示の際に背景を追加
Auto射撃のプログラムを少し変更(ボタンを押すたびに射撃システムを一巡させていたのをゲームモード移行時点で一部メモリ上に保存)
ターゲットの当たり判定をプログラムから明示的に管理(一部端末でターゲットにヒットしなかった問題が解決する?)
(多分)リーダーボードの機能を修正

ver 1.31
更新時にTarget関連のバグが発生したのを修正

ver 1.3 (提案してくれた方ありがとうございます!)
単射時の射撃タイミングをタップ時から指を話した瞬間に変更
武器とカメラ感度調整の変更をボタンからも行えるように変更
武器とカメラ感度の数値を可視化

ver 1.23
前回の更新以降ゲーム中に射撃ができないバグが発生したため、銃声や当たり判定の順で加えた変更を少し修正
※同時期にGooglePlayGameService関連で手を加えたものがあるため、この修正で治らなければそちら側の変更を検討

ver 1.22 
GooglePlayServiceにログインできなかった問題を修正
プライバシーポリシーの文言を一部変更(4か国語という表記から具体的な言語名の羅列に変更)
【銃声サウンド再生、当たり判定の発生、反動】という順から【当たり判定の発生、銃声サウンドの再生、反動】の順に変更
ゲーム終了時に表示される広告を4回ごとから5回ごとに変更

ver 1.21
プライバシーポリシーを追加
タイトル画像でGODのO部分に銃創を入れていたのが宗教的な配慮に欠けるためAIMのAに銃創を移動

ver 1.2
リリース

【Unity】ゲームの記録を複数保存する

 ゲームの結果や得点を複数記録してスコア履歴やハイスコアランキングのようなものを作る場合は、鍵に整数型を使って記録した番号も保存するか、新しく記録する際に降順でデータを上書きしていく。ここではPlayerPrefsで後者を使ってスコア履歴を実装する方法を紹介する。Jsonやセーブするアセットを使って保存する場合も同じ方法で実装できる。

得点履歴の作成

//This script is released under the MIT License.
using UnityEngine;
using System.Collections;

public class SaveManager : MonoBehaviour
{
    public void SaveScore()
    {
        //1
        OverwriteRecord();
        //4
        int score = GetComponent<Script>().score;
        PlayerPrefs.SetInt("Score1", score);

        PlayerPrefs.Save();
    }

    void OverwriteRecord()
    {
        //2
        int saveNum = 10;
        //3
        while (saveNum >= 1)
        {
            int loadNum = saveNum - 1;
            
            if (PlayerPrefs.HasKey("Score" + loadNum.ToString()))
            {
                int loadScore = PlayerPrefs.GetInt("Score" + loadNum.ToString());

                PlayerPrefs.SetInt("Score" + saveNum, loadScore);

                saveNum -= 1;
            }
            else
            {
                saveNum -= 1;
            }
        }
    }
}
1.データを上書きするメソッドを呼ぶ

 複数の記録を保存する場合は降順でデータを保存しなおさなければならない。もし、先に上書きしなければ、新たに保存したデータが既存のデータを上書きすることになる。そのため、最新のデータを保存する前に一度上書きするメソッドを呼ぶ。

2.保存するデータの数を決める

 保存するデータの数を宣言する。ここで宣言した数分の履歴が生まれる。

3.既存のデータの上書き

 whileを使って降順でデータを上書きしていく。2で決めた数が一番最後のデータであり、そこに1減らした鍵で保存してあるデータを上書きする。通常の記録では昇順で保存していくため、一定の回数保存するまでは後ろの数字にデータは保存されていない。そのため、鍵の有無を確認して、あった場合のみデータの上書きをする。そして鍵があった場合もなかった場合も数字を減らし、これを1になるまで繰り返す。

4.最新のデータを保存する

 保存する変数を宣言する。PlayerPrefsではInt,Float,Stringの三種類が保存できる。ここでは得点のみを保存するため一つのみ宣言しているが、ほかにも保存する場合は保存するものに応じた変数を宣言する。ここではscore1つだけを宣言してるため、ここで参照もしているが、複数記録する場合はあらかじめStart等で取得しておくのがいいだろう。なお、このスクリプトから参照するため、取得先の保存する変数はpublicにする必要がある。もし、同一スクリプト内で記録を実装するならprivateでいい。

使用例

 Scriptという名前のスクリプトとScoreManageを空のオブジェクトにアタッチする。UIのButtonを三つ用意しそれぞれScore、Save、Loadという名前に変更する。各ButtonのOnClickイベントに上記の空のオブジェクトの対応するメソッドを登録する。これでScoreボタンを押した数だけ点数が増え、Saveを押すとデータを保存、Loadを押すとログに保存したデータが表示される。

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

public class Script : MonoBehaviour
{
    public int score;
    SaveManager saveManager;

    void Start()
    {
        saveManager = GetComponent<SaveManager>();
    }

    public void GetScore()
    {
        score += 1;
    }

    public void Save()
    {
        saveManager.SaveScore();
    }

    public void Load()
    {
        int saveNum = 1;

        while (saveNum <= 10)
        {
            if (PlayerPrefs.HasKey("Score" + saveNum.ToString()))
            {

                int loadScore = PlayerPrefs.GetInt("Score" + saveNum.ToString());

                Debug.Log(saveNum + "のデータは" + loadScore);
                saveNum += 1;
            }
            else
            {
                saveNum += 1;
            }
        } 
    }
}

ライセンス

Copyright (c) 2019  Skeyll

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


参考
Unity - Scripting API: PlayerPrefs
https://docs.unity3d.com/ScriptReference/PlayerPrefs.html

【Unity】TouchScriptの使い方

 TouchScriptを導入することで多くのデバイスに対応した複雑なタッチ処理を行える。MITライセンスオープンソース化されており、AseetStoreもしくはGitHubから無料で入手して利用できる。タッチスクリプトではイベントハンドラに独自のイベントを追加し、入力受けたら登録したイベントの処理を行っている。
 なお、以下の説明は多くが公式GitHubの要約である。


導入

1. AssetStoreもしくはGitHubからダウンロード後、インストール。
2. PrefabsフォルダのTouchManagerCursorsをゲームビューに追加。
3. カメラにComponent/TouchScript/Layerを追加。
4. Component/TouchScript/Gestures、もしくは作成したジェスチャースクリプトをオブジェクトに追加。

 以上で入力を扱えるようになる。レイヤーに関してはStandard Layer3D、2D、UIのオブジェクトFullScreenLayerカメラを操作する場合に必要となる。また、テストの実行中にAltを押した後に入力するとダブルタップのシミュレーションが行える。


ジェスチャーの種類

個別的なもの
1.TapGesture
 Events: Tapped
 Messages: OnTap.
2.PressGesture(Friendly)
 Events: Pressed
 Messages: OnPress.
3.ReleaseGesture  (Friendly)
 Events: Released
 Messages: OnRelease.
4.LongPress Gesture
 Events: LongPressed, Messages: OnLongPress.
5.Flick Gesture
 Events: Flicked
 Messages: OnFlick.


連続的なもの
1.Transform Gesture
 Events: TransformStarted, Transformed, TransformCompleted
 Messages: OnTransformStart, OnTransform, OnTransformComplete.
2.Screen Transform Gesture
 Transform Gestureと同じだが、スクリーンの座標を参照。
 Events: TransformStarted, Transformed, TransformCompleted
 Messages: OnTransformStart, OnTransform, OnTransformComplete.
3.Pinned Transform Gesture
 Transform Gestureに似ているが、オブジェクトが中心で固定されて動けない場合は固定された点を軸に回転と大きさの変更が行われる。
 Events: TransformStarted, Transformed, TransformCompleted
 Messages: OnTransformStart, OnTransform, OnTransformComplete.
4.Meta Gesture
 すべてのタッチイベントを個別のイベントに再割り当てする。他のジェスチャーを使うほうが望ましい。
 Events: TouchBegan, TouchMoved, TouchEnded, TouchCancelled
 Messages: OnTouchBegan, OnTouchMoved, OnTouchEnded, OnTouchCancelled.
 ※なお上記の1-3のイベントは基本的には二つ目のタッチ入力まで機能する。

 通常ジェスチャーの入力が行われた際に、そのオブジェクトと親からの入力は一時停止する。つまり、初めの入力が排他的に処理される。しかし、いくつかのジェスチャーは他のジェスチャーと同時に入力することが可能であり、そのジェスチャーはライブラリー内でFriendlyと呼ばれている。
 Friendlyジェスチャーを作る方法は以下の二種類ある。
1. Inspector上でもう一方のFriendly Gesturesリストにドロップ&ドラッグ。
2.gesture1.AddFriendlyGesture(gesture2);を呼ぶ。

イベントを登録

 新たな挙動を実装するためにイベントハンドラにイベントを追加する。追加にはOnEnableOnDisanableメソッドを使い、入力があったときだけイベントの処理を行う。常時イベントを登録しておかないのは、メモリリークの原因となるためである。
 イベントの登録TouchManegerに直接することもできるが、特定のジェスチャーのみを使用する場合は個別のイベントに登録した方が入力の識別が早くなる
 イベントハンドラの利用にはNameSpace Systemを使う。また利用するジェスチャーにもNameSpaceが必要である。必要なNameSpaceは「ジェスチャーの種類」から利用したいジェスチャーの個別ページに飛び、上部のNamespaceに記載のあるものである。また登録するイベントハンドラは「ジェスチャーの種類」、もしくは個別のページのEventsで確認できる。

using System; //イベントハンドラに必要。
using TouchScript.Gestures; //Tap入力に必要。

void OnEnable()
{
 //TappedEventのイベントハンドラに登録している。
 GetComponent<TapGesture>().Tapped += tappedHandler;
}

void OnDisable()
{
 GetComponent<TapGesture>().Tapped += tappedHandler;
}

void tappedHandler(object sender, EventArgs e)
{
 //Tap入力があったときに行う処理。
}


イベントハンドラ

 イベントが発生したときに、その発生したという処理を受けて行う処理のことをイベントハンドラと呼ぶ。void形で引数にEventArgs型を持ち、プロパティとして振る舞うデリゲートのようなものである。
 通常、処理はプログラムによりさまざまに異なる。しかし、「入力を受けた」というイベントの発生を認識する処理自体は汎用的なものである。そのため、イベントの処理を受ける部分と実際の処理を行う部分(イベントハンドラ)を切り分けることができる。こうしたプログラムのことをイベント駆動型プログラムと呼ぶ。


処理を作成する

 TouchScriptにはいくつかの関数が用意されている。例えば、タッチしたスクリーン上の座標の取得や、フレーム間でのスワイプの距離の取得などである。これらはTouchScriptのジェスチャーに対して処理が行われている。また関数を使う場合、追加でNameSpaceが必要になることがある。個別の関数のページに行き、記載していないNameSpaceが必要な場合は追加する。
 以下の例ではTapGestureのScreenPositionを使い、タップした場所のスクリーン上の座標を取得してる。関数の一覧は各ジェスチャーページのPropertiesで確認できる。

using System; //イベントハンドラに必要。
using UnityEngine;
using TouchScript.Gestures; //Tap入力に必要。

public class GetTouchPosition : MonoBehaviour
{
//関数を使うため取得。Startで取得してもいい。
[SerializeField]
TapGesture tapGesture; 

void OnEnable()
{
 //Serializeで取得してるため、ここでGetComponentする必要はない。
 tapGesture.Tapped += OnTapped;
}

void OnDisable()
{
 tapGesture.Tapped += onTapped;
}

void OnTapped(object sender, EventArgs e)
{
 Vector2 tapPosition = tapGesture.ScreenPosition;
 Debug.Log(tapPosition + "をタップした");
}



参考
TouchScript
https://github.com/TouchScript/TouchScript
Writing a Custom Gesture
https://github.com/TouchScript/TouchScript/wiki/Writing-a-Custom-Gesture
イベント - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
https://ufcpp.net/study/csharp/sp_event.html
Unityにおける簡単なジェスチャー取得 - WonderPlanet DEVELOPER BLOG
http://developer.wonderpla.net/entry/blog/engineer/Unity_TouchScript/
【Unity】タッチジェスチャを簡単に実装できる「TouchScript」の基本的な使い方を紹介 - コガネブログ
http://baba-s.hatenablog.com/entry/2018/03/22/085900
TouchScriptアセットのチュートリアルを試した | D.YAMA Blog
http://blog.d-yama7.com/archives/223

【Unity】タッチ入力でカメラを回転させる

 タッチ入力でカメラを操作するには、タッチ入力の移動距離を取ってその値を回転に加える。今回はTouchScriptScreenTransformGestureを使ってこの機能を実装する。


1.FullScreenLayerとScreenTransformGestureをアタッチ

 回転させるオブジェクトにFullScreenLayerScreenTransformGestureをアタッチする。LayerはMainCameraGestureはTranslationにチェックを入れる。これらをつけたオブジェクトが回転するため、カメラにつけた場合は一人称視点プレイヤーやオブジェクトなどにつけた場合は三人称視点になる。

2.スクリプトの作成

 移動距離を取得し、その値をオブジェクトのオイラー角に加えて回転させる。タッチでカメラを操作する場合、画面をスワイプしてその移動量に応じてカメラを回転させると感覚通りの挙動をする。
 そこでタッチの移動距離を取得する関数がScreenTransformGestureのDeltaPositonである。DeltaPositionで前フレームと現在フレームの差分をVector3で取得できる。今回はオイラー角に代入してカメラを回転させるため、この数値をオイラー角に足し続ける必要がある。仮にこの処理を行わない場合は、オイラー角がDelataPositonで取得したVector3の値になるので微小の回転を繰り返すだけになる。また、Transform.eulerangleは360度以上の回転を加えると増加させるのに失敗するため、あらかじめMathf.Clampや回転させる場合の条件をつけて回転の上限を設ける必要がある。
 RotateにDeltaPositonを加えて回転させることも可能である。その場合はDeltaPositionで取得したx,yの値をそのまま使う。
 

//  CameraController.cs
//  https://skeyll.hateblo.jp/entry/camera_rotate_TouchScript
//
//  Created by Skeyll on 2019.06.20.


using System; //EventHandlerに必要
using UnityEngine;
using System.Collections;
using TouchScript.Gestures.TransformGestures; //ScreenTransformGestureに必要
using TouchScript.Gestures.TransformGestures.Base; //DealtaPositionに必要

 

public class CameraController : MonoBehaviour
{
    [SerializeField]
   ScreenTransformGesture transformGesture;
    
 //回転させるオブジェクト。
 [SerializeField]
    Transform controlObject; 
  
  //タッチ入力分だけしか回転させないなら必要ない。
    float rotateSpeed = 20.0f;
   
 //カメラの回転に制限をつけないなら必要がない。
 //この場合は左右110度までしか回転せず、方向転換はできない。
  [SerializeField]
    float limitRotateX = 110.0f, limitRotateY = 90.0f;
    float startRotateX, startRotateY;

    void Start()
    {
        startRotateX = controlObject.transform.rotation.eulerAngles.x; 
        startRotateY = controlObject.transform.rotation.eulerAngles.y;
    }

    void OnEnable()
    {
      transformGesture.Transformed += OnRotating;
    }

    void OnDisable()
    {
       transformGesture.Transformed -= OnRotating;
    }

    void OnRotating(object sender, EventArgs e)
    {
        Vector3 deltaPos = transformGesture.DeltaPosition;
        float rotateX = deltaPos.x * rotateSpeed;
        float rotateY = deltaPos.y * rotateSpeed;

       //transform.eulerAnglesに直接座標を指定してるのでここがなければ常にdeltaの座標を向くようになる。
        startRotateX = startRotateX + rotateY;
        startRotateY = startRotateY + rotateX;
 
       controlObject.transform.eulerAngles = new Vector3(Mathf.Clamp(-startRotateX, -limitRotateX, limitRotateX), Mathf.Clamp(startRotateY, -limitRotateY, limitRotateY), 0);
 }
}



3.回転させるオブジェクトにスクリプトをアタッチ

  LayerとGestureをつけたオブジェクトにCameraControllerをアタッチする。その後、CameraControllerにインスペクタ上からGestueと回転させるオブジェクトを入れる。カメラを回転させる場合は以上で回転させられる。もし回転させる対象をプレイヤーなどのオブジェクトにした場合は、カメラをそのオブジェクトの子に設定し、オブジェクトの回転にカメラを追従させる必要がある。

 もし、移動パネルなどを作りそのパネル上でスライドした移動量でカメラを回転させたい場合はTransformGestureで1ー3と同様のことをする。その場合は新たにFullScreenLayerをアタッチする必要はない。


参考
ScreenTransformGesture Class
http://touchscript.github.io/docs/html/T_TouchScript_Gestures_TransformGestures_ScreenTransformGesture.htm
UnityEngine.Transform - Unity スクリプトリファレンス
https://docs.unity3d.com/ja/2018.2/ScriptReference/Transform.html
C# - Unityで回転制限をつけたいです。|teratail
https://teratail.com/questions/83342

プライバシーポリシー - The GOD AIM

プライバシーポリシー

 私は「The GOD AIM」でいくつかの外部サービスを利用しており、それにともないプライバシー情報を収集しています。私は本アプリご利用になる皆様の情報を以下のように取り扱うものとします。また、これらの情報は法令によって提供を求められた場合、もしくはアプリの運営を委託、譲渡する場合を除いて第三者に提供することはありません。

1.取得情報

外部ストレージ(SDカード)へのアクセス
取得目的:ユーザーの設定(リコイルや感度)を保存

2.お問い合わせに関する情報

 お問い合わせにより知りえたあなたの情報はアプリの改善のためだけに使用します。問い合わせに関して返信することがあるかもしれませんが、改善以外の目的では使用しません。もし、送信したメールの削除依頼があれば速やかに削除します。

3.利用している外部サービス

 私は本アプリの提供や利用に関する動向調査、利用者に適切な広告表示をするために、以下の外部サービスを利用しています。

Unity Analytics
提供者:Unity Technologies
利用目的:アプリのクラッシュ情報の調査、利用状況の確認

AdMob
提供者:Google
利用目的:アプリ内での広告掲載

4.利用者情報の送信停止

 外部サービスはネットワークに繋がった状態で本アプリを遊んでいるときに情報を収集しています。もし、情報の送信を停止したい場合は機内モードにして利用してください。

5.ポリシーの変更

私はプライバシーポリシーの全部または一部を変更することがあります。重要な変更がある場合は告知し、このページに掲載します。

6.お問い合わせ先

 プライバシーポリシーに関するお問い合わせはコンタクトにあるSNSを通じて行うか、アプリ内、アプリ説明欄に記載しているメールアドレスから連絡してください。


制定:2019年8月11日
改定:2019年9月02日

PrivacyPolicy - The GOD AIM

Privacy Policy

I use some external service in "The GOD AIM" and I collect personal infomation. I deal with your infomation as below. I only provide it to a third party when I'm requested to do by law or I transfer my app to them.

1.Getting Permission

Access to external storage(SD)
Purpose:Save user setting ( recoil and sensi...)

2.Contact

I use the Information that I know when you contact me in order to improve my app. I may reply to that email but I only do about your inquiry. When you request me to remove your message, I delete it.

3.External Service

I use follow services in order to improve my app and place ADs.

Unity Analytics
Provider:Unity Technologies
Purpose:Collect crash information of my app, Find out bugs in my app

AdMob
Provider:Google
Purpose:Place ADs in my app

4.Stop Sending Your Information

When you play my app on connecting to the internet, these services collect personal information. If you don't want to do, please you play offline.

5.Revise policy

I may revise all of or a part of this policy. When it have major changes, I announce it and change this policy.

6.Contact Me

If you want to contact to me about this policy, you can contact me with SNS or E-mail.


Establishment : August the 11th, 2019
Revision : September the 2nd, 2019

PrivacyPolicy for “The GOD AIM”


Privacy Policy

 I don't collect personal information in my apps. But I use some external service ( for ADs and LeaderBorad) and these may gather your data. The details are listed below.

External service

https://policies.google.com/technologies/ads?hl=en


Getting permission

  • Using Storage

I just use this for exporting a game record.


 If you contact me with E-mail, I just use your information for app improvement and don't provide to third parties. When you request me to delete, I remove your E-mail.

プライバシーポリシー

 私はアプリ内で個人情報を収集していません。しかし、いくつかの外部サービスを広告やゲーム内のサービスのために利用しており、それらが個人情報を取得している可能性があります。下記よりご確認ください。

外部サービス

https://policies.google.com/technologies/ads?hl=ja


アプリ内権限

  • ストレージの利用

ゲーム結果を画像として保存するために取得しています。


 また、お問い合わせにより得たあなたの個人情報はアプリ、もしくはブログの改善のために利用し、第三者に提供することはありません。削除の要望があった場合、速やかに削除します。

개인 정보 보호 정책

 내 앱에서 개인 정보를 수집하지 않습니다. 그러나 일부 외부 서비스 (AD 및 LeaderBorad)를 사용하면 데이터가 수집 될 수 있습니다. 자세한 내용은 다음과 같습니다.

외부 서비스

https://policies.google.com/technologies/ads?hl=ko


허가 받기

  • 스토리지 사용

나는 이것을 게임 레코드 내보내기에 사용합니다.


 이메일로 저에게 연락하면 앱 개선을 위해 귀하의 정보를 사용하며 제 3 자에게 제공하지 않습니다. 삭제를 요청하면 이메일이 삭제됩니다.

隐私权原则

 我没有收集个人情报在我的手机APP.但是, 我用一些外部服务(为广告和游戏), 还有这些会收集个人情报. 请确认下面的.

外部服务

  • AdMob(Google Inc.) (如果你想看此信息, 我会给你发电子邮件)

https://policies.google.com/technologies/ads?hl=en


APP用权限

  • 使用数据储存

 我用这个权限为保存游戏的结果.

 如果你发电子邮件和我得到你的个人情报, 我用它们为改善我的手机APP和我不提供第三者. 有删除请求,我删除你的电子邮件.

プライバシーポリシー  ©Skeyll 2019- All Rights Reserved.