Uncaught translation error: java.lang.IllegalArgumentException: already added: Lcom/google/android/gms/internal/zzut; などと言われてエラー

Firebaseの指定しているプラグインバージョンとAdMobの指定しているプラグインバージョンが違うから起きてるっぽい。

参考
github.com


Assets/GoogleMoblieAds/Editor
にあるGoogleMobileAdsDependencies.xml

Assets/Firebase/Editor
においてある〜Dependencies.xmlで中に書いてあるバージョンを揃えてあげたら解消した。

UnityでAndroid版をビルド時にmanifestファイルのマージに失敗する

Users/wakepon/projects/2357/Temp/StagingArea/AndroidManifest-main.xml:6:16-49 Error:
	Attribute application@icon value=(@drawable/app_icon) from AndroidManifest-main.xml:6:16-49
	is also present at AndroidManifest.xml:13:9-45 value=(@drawable/ic_launcher).
	Suggestion: add 'tools:replace="android:icon"' to <application> element at AndroidManifest-main.xml:6:3-22:17 to override.

こんな感じのエラーが出て困ってた。

ここに、ワークアラウンドが載ってました。
issuetracker.unity3d.com

先のリンク先の記事にも乗っているけど、

Windows:
https://dl-ssl.google.com/android/repository/tools_r25.2.5-windows.zip

Mac OSX:
https://dl-ssl.google.com/android/repository/tools_r25.2.5-macosx.zip

をダウンロードし、SDKのtoolフォルダ(/Users/ユーザー名/Library/Android/sdk/tool)を退避し、代わりにダウンロードしてきたフォルダを使うようにしたところ、エラーを回避できました。

どうもSDKを26にしたタイミングから発生してたらしい。気づかんかった。

UnityでFirebaseプラグインを新しくしたら、XCodeのビルドでエラーが出た件

_objc_class_$_firanalytics", referenced from unity

というようなリンカエラー

Unity-iPhone.xcodeprojの方でビルドしようとしたいたんですが、pod installしてUnity-iPhone.xcworkspaceを生成して、そっちでビルドすればOKというとこまではわかった。

しかし、pod installをしようとすると、

Firebase pod install - pod 'Firebase/Analytics' - Required a higher minimum deployment target
Specs satisfying the `Firebase/Analytics (= 4.1.0)` dependency were found, but they required a higher minimum deployment target.

というエラーがでる。

Podfileの

platform :ios, '6.0'

platform :ios, '7.0'

にすることで解決した。が、何で解決したのか、よくわかっていない。

Unityで作ったアプリでExperiaでのみAdMobのバナーがちょっと上に出る問題

ExperiaでのみAdMobのバナーがちょっと上に出るという問題が以前からちょこちょこと報告が上がっていたんですが、一体どうしてExperiaでのみそんなことになるのか分からず途方にくれていました。

こんなふうに表示されてしまう↓
f:id:wkpn:20170630173252j:plain

ただしくはこう↓
f:id:wkpn:20170630173207j:plain

場合によってはゲームのUIとも被ってしまって困っていたんですが、ふとしたことで直りました。

それは、AndroidManifest.xmlのapplicationタグ部分が

<application android:icon="@drawable/app_icon"
    android:label="@string/app_name"
    android:debuggable="false">

だったのをandroid:theme="@android:style/Theme.NoTitleBar"を追加して、

<application android:icon="@drawable/app_icon"
    android:label="@string/app_name"
    android:debuggable="false"
    android:theme="@android:style/Theme.NoTitleBar" >

こうしたら直りました。

Androidの仕様に疎く、なぜこれで直ったのか分からないのですが、とりあえず直ったので共有しておきます。

UnityでiOSとかでよくあるトグルスイッチを作りたい。

iOSとかである、こーいうトグルスイッチを作りたい!っと思って作ってみました。

まず画から。

こーいう緑色で楕円のONの画像に、
f:id:wkpn:20170623213239p:plain

こーいう灰色で楕円のOFFの画像を被せ、
f:id:wkpn:20170623213254p:plain

さらに白い丸いボタン画像を載せます。
f:id:wkpn:20170623213258p:plain

Scriptで、タッチするとボタンが右に行って、OFF画像が縮小して消え、もう一回押すとボタンが左に行ってOFF画像が拡大して現れるようにします。

ソースはだいたいこんな感じ↓(Tweenアニメするためにオレオレライブラリが入ってますが、そこはDoTweenとかのメジャーなやつに置き換えてもらえばうまく動くかと思います。)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using WK.Tween;

public class ToggleSwitchController : MonoBehaviour, IPointerClickHandler {
    [SerializeField]
    Transform button;

    [SerializeField]
    Transform inactiveBackground;

    [SerializeField]
    float duration = 0.1f;

    [SerializeField]
    UnityEvent onEvent;

    [SerializeField]
    UnityEvent offEvent;

    bool currToggle = false;
    public bool CurrToggle { get { return currToggle; } }

    private enum EState {
          idle
        , gotoOn
        , gotoOff
    }

    private EState currState    = 0;
    private EState nextState    = 0;
    private int    stateCounter = 0;

    static readonly Vector3 cOnPos  = new Vector3(  100.0f, 0.0f, 0.0f );
    static readonly Vector3 cOffPos = new Vector3( -100.0f, 0.0f, 0.0f );

    //------------------------------------------------------------------------------
    void Awake()
    {
        stateCounter = 0;
        currState    = EState.idle;
        nextState    = EState.idle;
    }

    //------------------------------------------------------------------------------
    void Update()
    {
        ++stateCounter; 
        if( currState != nextState )
        {
            currState    = nextState;
            stateCounter = 0;
        }

        switch( currState )
        {
            case EState.gotoOn:
                updateGoToOn();
                break;
            case EState.gotoOff:
                updateGoToOff();
                break;
        }
    }

    //------------------------------------------------------------------------------
    private void changeState( EState next_state )
    {
        nextState = next_state;
    }

    //------------------------------------------------------------------------------
    private void updateGoToOn()
    {
        if( stateCounter == 0 )
        {
            inactiveBackground.TwScale( Vector3.zero, duration );
            button.TwMove( cOnPos, duration ).OnComplete( 
                    () => {
                            changeState( EState.idle );
                            onEvent.Invoke();
                        }
                    );
        }
    }

    //------------------------------------------------------------------------------
    private void updateGoToOff()
    {
        if( stateCounter == 0 )
        {
            inactiveBackground.TwScale( Vector3.one, duration );
            button.TwMove( cOffPos, duration ).OnComplete( () => {
                            changeState( EState.idle );
                            offEvent.Invoke();
                        }
                    );
        }
    }

    //------------------------------------------------------------------------------
    public bool GoToOnImmediately()
    {
        if( currState == EState.idle || nextState == EState.idle )
        {
            inactiveBackground.localScale = Vector3.zero;
            button.localPosition = cOnPos;
            currToggle = true;
            changeState( EState.idle );
            return true;
        }
        return false;
    }

    //------------------------------------------------------------------------------
    public bool GoToOffImmediately()
    {
        if( currState == EState.idle || nextState == EState.idle )
        {
            inactiveBackground.localScale = Vector3.one;
            button.localPosition = cOffPos;
            currToggle = false;
            changeState( EState.idle );
            return true;
        }
        return false;
    }

    //------------------------------------------------------------------------------
    public bool GoToOn()
    {
        if( currState == EState.idle )
        {
            changeState( EState.gotoOn );
            return true;
        }
        return false;
    }

    //------------------------------------------------------------------------------
    public bool GoToOff()
    {
        if( currState == EState.idle )
        {
            changeState( EState.gotoOff );
            return true;
        }
        return false;
    }

    //------------------------------------------------------------------------------
    public virtual void OnPointerClick( PointerEventData event_data )
    {
        if( currState == EState.idle )
        {
            currToggle ^= true;
            if( currToggle )
            {
                GoToOn();
            }
            else
            {
                GoToOff();
            }
        }
    }
}

こちらにソース一式があります。
github.com

UnityでBGMのイントロ付きループに挑戦

最初に試したのはループ終端まで来たのを確認してAudioSource.timeをループ開始地点に飛ばす方法
www.shibuya24.info


次に試したのが、イントロ用とループ用でAudioSourceを2つ用意してループ用のAudioSourceをPlayScheduledでイントロ長分ずらして再生する方法。
qiita.com

自分の実装が良くなかったのかもしれないのですが、どちらの方法でもstreaming再生した時に音がプツッと途切れる事案が発生して断念。

結局Assetを購入して解決。

https://www.assetstore.unity3d.com/en/#!/content/51095

$21.6しましたが、今のところ途切れることはなく順調に動いているので満足してます。

UnityでビルドしたiOS版アプリがcompute_class_bitmap: Invalid type 13 for fieldと言われて落ちる

UnityでビルドしたiOS版アプリでcompute_class_bitmap: Invalid type 13 for fieldと言われて落ちる事案が発生しました。

IL2CPPでビルドすれば大丈夫。けどMonoだとアウト。Monoのほうがビルドが爆速なので、私、実機で動作確認する際は結構Monoでビルドするのです。

調べていくとどうも自作のTreeコンテナクラスが悪いようでした。

public class TreeContainer<T>
{
    private List<TreeContainer<T>> children;

    ...

childrenのとこの括弧が二重になっているGenericが駄目みたいです。

https://forum.unity3d.com/threads/new-running-fine-in-mac-windows-player-but-crashes-in-iphone-player.111056/

こちらの記事によると、generic of genericはAOTコンパイルではうまくいかないんだそうです。なのでiOS以外では問題なく動いていたと。

waken.hatenablog.com

悩ましい。