FC2ブログ
    09 «1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.» 11

    ハルシオンシステムの気ままBlog

    株式会社ハルシオンシステムのメンバーが送る、UnityやらJavaやらの技術的話題から、自社開発のアプリの宣伝とかとかのブログです。ほんと気ままにいきたいと思います。更新日は毎週 月 木でっす!

     

    【ハルシオンブログ】Hierarchy内で特定のコンポーネントが付いているものを検索 

    こんにちは。
    大坂です。

    今日からTGSですね。
    行く人は楽しんできてください。行かない人も公式放送とかあったりするのでそちらで楽しんだりできますね。

    Hierarchy内で特定のコンポーネントが付いているものを検索したかった。
    検索のところにコンポーネントの名前入れるだけなんですけどね。

    Audio Source コンポーネントがついたものを検索してみます。


    Audio Source の out put がついてたりついてなかったりして音がおかしくなっていたので使ったのでメモ。
    何かのお役に立てば!

    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】UnityのプロジェクトでATTダイアログを出してみた。え?これでいいの? 

    こんにちは。坂内っす。
    今週は東京ゲームショー2022がありますね。
    色々と気になるブースもありますね!

    今年は特に行く予定もなく、家で大人しくポケガ3開発してます。

    さて、先週はiOSへのビルドで時間食われてました。
    その中で、ATTダイアログを出すところでいい感じにはまったので、まとめておきます。
    色々なサイトのを試したのですが、結局以下に落ち着きました。


    【ATTダイアログ】
    iOS14以降からアプリの新規、アップデート時にATT(App Tracking Transparency)の対応が必須になりました。
    https://developer.apple.com/jp/news/?id=8rm6injj

    こんなの。
    これ入れないとリジェクトされるぽいですよ。

    では行ってみましょう。


    ①Assets/Plugins/iOSの下にATTダイアログを出すネイティブコードを作成する

    今回は「RequestAttDialog.mm」という名前のコードを作成しました。

    [RequestAttDialog.mm]

    #import
    #import
    #import
    #ifdef __cplusplus
    extern "C" {
    #endif
    void requestIDFA() {
    if (@available(iOS 14, *)){
    [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
    // Tracking authorization completed. Start loading ads here.
    // [self loadAd];
    }];
    }
    }
    #ifdef __cplusplus
    }
    #endif



    ②ATTダイアログのネイティブコードを呼び出すクラスを作成する
    これはUnityのプロジェクト内ならどこでもおk。

    [ATTDialog.cs]

    #if UNITY_IOS
    using System.Runtime.InteropServices;
    public class ATTDialog
    {
    [DllImport("__Internal")]
    private static extern int requestIDFA();
    public static void RequestIDFA()
    {
    requestIDFA();
    }
    }
    #endif



    ③上記で作成したRequestIDFAをアプリ開始のシーンで呼ぶ。
    タイトルやスプラッシュのシーンとかあれば、そこのStartなんかで呼んであげればいいです。


    void Start(){
    #if !UNITY_EDITOR && UNITY_IOS
    ATTDialog.RequestIDFA();
    #endif
    }


    ④EditorにFrameworkやInfo.plistで設定する必要のあるものをコードで作っておく
    Assets/Editorに「PostXcodeBuild.cs」を作成する。


    //PostXcodeBuild.cs

    using System.IO;
    using UnityEditor;
    using UnityEditor.Callbacks;
    using System.Collections;
    using System.Collections.Generic;
    #if UNITY_IOS
    using UnityEditor.iOS.Xcode;
    #endif

    public class PostXcodeBuild
    {
    #if UNITY_IOS
    private struct InfoplistInfo
    {
    public string key;
    public string value;
    public InfoplistInfo(string str1, string str2)
    {
    key = str1;
    value = str2;
    }
    };

    private struct LocalizationInfo
    {
    public string lang;
    public bool isdefault;
    public InfoplistInfo[] infoplist;
    public LocalizationInfo(string langstr, bool flg, InfoplistInfo[] info)
    {
    lang = langstr;
    infoplist = info;
    isdefault = flg;
    }
    };
    private struct CommonInfoPlistInfo
    {
    public InfoplistInfo[] infoplist;
    public CommonInfoPlistInfo(InfoplistInfo[] info)
    {
    infoplist = info;
    }
    };

    private static LocalizationInfo[] localizationInfo = {
    new LocalizationInfo("en", false, new InfoplistInfo[]
    {new InfoplistInfo("CFBundleDisplayName", "英語のタイトル"),
    new InfoplistInfo("NSUserTrackingUsageDescription", "Please set to Allow to avoid displaying inappropriate advertisements"),
    }),
    new LocalizationInfo("ja", true, new InfoplistInfo[]
    {new InfoplistInfo("CFBundleDisplayName", "日本語のタイトル"),
    new InfoplistInfo("NSUserTrackingUsageDescription", "不適切な広告の表示を避けるために”トラッキングを許可”に設定してください"),
    })
    };


    private static string[] skadnetworkitems = new string[] { "cstr6suwn9.skadnetwork" };


    static void createInfoPlistString(string pjdirpath, LocalizationInfo localizationinfo)
    {
    string dirpath = Path.Combine(pjdirpath, "Unity-iPhone Tests");

    if (!Directory.Exists(Path.Combine(dirpath, string.Format("{0}.lproj", localizationinfo.lang))))
    {
    Directory.CreateDirectory(Path.Combine(dirpath, string.Format("{0}.lproj", localizationinfo.lang)));
    }
    string plistpath = Path.Combine(dirpath, string.Format("{0}.lproj/InfoPlist.strings", localizationinfo.lang));
    StreamWriter w = new StreamWriter(plistpath, false);
    foreach (InfoplistInfo info in localizationinfo.infoplist)
    {
    string convertedval = System.Text.Encoding.UTF8.GetString(
    System.Text.Encoding.Convert(
    System.Text.Encoding.Unicode,
    System.Text.Encoding.UTF8,
    System.Text.Encoding.Unicode.GetBytes(info.value)
    )
    );
    w.WriteLine(string.Format(info.key + " = \"{0}\";", convertedval));
    }
    w.Close();
    }

    static void addknownRegions(string pjdirpath, LocalizationInfo[] info)
    {
    string strtmp = "";
    string pjpath = PBXProject.GetPBXProjectPath(pjdirpath);

    foreach (LocalizationInfo infotmp in info)
    {
    strtmp += "\t\t" + infotmp.lang + ",\n";
    }
    strtmp += "\t\t);\n";

    StreamReader r = new StreamReader(pjpath);
    string prjstr = "";
    string linetmp = "";
    while (r.Peek() >= 0)
    {
    linetmp = r.ReadLine();
    if (linetmp.IndexOf("knownRegions") != -1)
    {
    prjstr += linetmp + "\n";
    prjstr += strtmp;
    while (true)
    {
    linetmp = r.ReadLine();
    if (linetmp.IndexOf(");") != -1)
    {
    break;
    }
    }
    }
    else
    {
    prjstr += linetmp + "\n";
    }
    }
    r.Close();
    StreamWriter sw = new StreamWriter(pjpath, false);
    sw.Write(prjstr);
    sw.Close();
    }

    static void addLocalizationInfoPlist(string pjdirpath, LocalizationInfo[] info)
    {
    string plistPath = Path.Combine(pjdirpath, "Info.plist");
    PlistDocument plist = new PlistDocument();

    plist.ReadFromFile(plistPath);
    var array = plist.root.CreateArray("CFBundleLocalizations");
    foreach (LocalizationInfo infotmp in info)
    {
    array.AddString(infotmp.lang);
    }
    var rootDict = plist.root;
    foreach (LocalizationInfo infotmp in info)
    {
    if (infotmp.isdefault)
    {
    foreach (InfoplistInfo pinfo in infotmp.infoplist)
    {
    string convertedval = System.Text.Encoding.UTF8.GetString(
    System.Text.Encoding.Convert(
    System.Text.Encoding.Unicode,
    System.Text.Encoding.UTF8,
    System.Text.Encoding.Unicode.GetBytes(pinfo.value)
    ));
    rootDict.SetString(pinfo.key, convertedval);
    }
    }
    }
    plist.WriteToFile(plistPath);
    }

    static void addSkAdNetworkItems(string pjdirpath, string[] skadvallist)
    {
    string plistPath = Path.Combine(pjdirpath, "Info.plist");
    PlistDocument plist = new PlistDocument();
    plist.ReadFromFile(plistPath);

    if (skadvallist != null)
    {
    var array = plist.root.CreateArray("SKAdNetworkItems");
    foreach (string value in skadvallist)
    {
    PlistElementDict dict = array.AddDict();
    dict.SetString("SKAdNetworkIdentifier", value);
    }
    }
    plist.WriteToFile(plistPath);
    }

    static void addAppTrackingTransparency(string pathToBuiltProject)
    {
    string pbxProjectPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
    PBXProject pbxProject = new PBXProject();
    pbxProject.ReadFromFile(pbxProjectPath);
    string targetGuid = pbxProject.GetUnityFrameworkTargetGuid();
    pbxProject.AddFrameworkToProject(targetGuid, "AppTrackingTransparency.framework", true);
    pbxProject.WriteToFile(pbxProjectPath);
    }

    [PostProcessBuild]
    public static void SetXcodePlist(BuildTarget buildTarget, string pathToBuiltProject)
    {
    if (buildTarget != BuildTarget.iOS)
    {
    return;
    }

    foreach (LocalizationInfo entry in localizationInfo)
    {
    /* add infoplist.string */
    createInfoPlistString(pathToBuiltProject, entry);
    }

    /* add knownregions to project */
    addknownRegions(pathToBuiltProject, localizationInfo);

    /* add localization to infoplist */
    addLocalizationInfoPlist(pathToBuiltProject, localizationInfo);

    /* add addSkAdNetworkItems */
    addSkAdNetworkItems(pathToBuiltProject, skadnetworkitems);

    /* add AppTrackingTransparency */
    addAppTrackingTransparency(pathToBuiltProject);
    }
    #endif
    }


    これを作っておけば、XcodeでFrameworkの追加等の手間が省けます。

    ⑤Unityでビルド

    ⑥出来上がったUnity-iPhone.xcworkspaceからXcodeを起動して、ビルド


    最終的にはこちらでATTダイアログが出るようになりました。
    たた、ATTダイアログの戻りを使ったりしてないので、これが正しいのか分からないのが現状…


    こうした方がいいよとかそういうのがあったら是非教えてください!


    ということで、本日はATTダイアログを出してみた。

    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】配列の要素を範囲指定で取得する 

    こんにちは。
    大坂です。

    配列の要素を範囲指定で取得する方法です。
    C# 8.0 以降から使えるみたいですね。

    コード。

    int[] test = new int[] { 0, 1, 2, 3, 4, 5 };

    // 要素[1]から最後まで 1,2,3,4,5
    Debug.Log(string.Join(",", test[1..]));
    // 最初から要素[4]まで 0,1,2,3
    Debug.Log(string.Join(",", test[..4]));
    // 最初から最後の1つ前の要素まで 1,2,3,4
    Debug.Log(string.Join(",", test[1..^1]));


    結果。


    何かの時に使ってみてくださいまし。
    ではまたノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】uGUIのImageをOffsetを使用して無限スクロールする方法。 

    もう気が付けば9月ですね。
    ほんとしらないうちに1年が残り3か月になりました。
    やばばっ!坂内っす。

    ポケガ3今年中に出さないといけないのに…もう時間が…


    さて、Unityのお話。
    横スクロールアクションとか、それ以外でも絵を無限スクロールする場合ってあるじゃないですか。
    もちろん絵自体を動かして端っこまでスクロールしたら元に戻すという方法でできるんですが、絵を動かさないでやる方法もあるぽいです。
    あ、uGUIのImageでの話です。

    やり方は簡単で、Offsetをいじってスクロールさせてるように見せる方法です。

    Image.materialについているOffsetを動かします。

    Dotweenだとこんな感じ


    imgBg.material.DOOffset(new Vector2(3f, 0f), 5f).SetLoops(-1, LoopType.Incremental).SetEase(Ease.Linear);



    DOOffsetで(3.0)まで5秒かけてオフセットを動かします。


    こんな感じで動かすことができます。

    DoTweenを使わない場合でも、UpdateにてOffsetを動かせば動きます。


    private void Update() {
    imgBg.material.mainTextureOffset += new Vector2(Time.deltaTime * 1f, 0f);
    }



    ということで、ImageのスクロールをOffsetを使って行う方法でした。

    では、あでゅ~ノシ

    Category: 開発日記(Unity)

    tb 0 : cm 0   

    【ハルシオンブログ】Unityでクリップボードに文字列を設定する 

    こんにちは。
    大坂です。

    Unityでクリップボードに文字列を設定したかったので、その方法。
    「GUIUtility.systemCopyBuffer」に設定するだけなのですが。

    一応こんな感じ。

    public SuperTextMesh text;

    public void OnClickSetClipboard()
    {
    GUIUtility.systemCopyBuffer = text.text;
    }



    ※画像をクリックすると動きます。

    ちゃんとクリップボードにコピーされて、ペーストも出来てます。
    IDとかをコピーしてあげると入力間違いなどがなくなるかもしれませんね。

    ではまたノシ

    Category: Androidアプリ紹介

    tb 0 : cm 0