STYLY 開発者ブログ -STYLY Developer's Blog-

Gameobjectのテクスチャをアスペクト比正しく貼り付ける

Unityで貼り付ける元画像の縦横比と、貼り付け先の縦横比が違った場合、引き伸ばされて画像が表示されてしまいます。

下記のように、アスペクト比が異なる場合は、画像がいっぱいに表示されるように調整して貼り付けます。

NekoImage

        /// <summary>
        /// //指定したウェブ画像を読み込んでゲームオブジェクトのテクスチャとして表示(適切に表示サイズを調整)
        /// 読み込み画像が最大で表示されるように表示部分が自動調整されます
        /// </summary>
        /// <param name="url"></param>
        /// <param name="gObj"></param>
        /// <returns></returns>
        public static IEnumerator<WWW> attacheWebImageToGameobject_appropriately(string url, GameObject gObj)
        {
            WWW texturewww = new WWW(url);
            yield return texturewww;
            gObj.GetComponent<Renderer>().material.mainTexture = texturewww.texture;

            float Obj_x = gObj.transform.lossyScale.x;
            float Obj_y = gObj.transform.lossyScale.y;
            float Img_x = (float)texturewww.texture.width;
            float Img_y = (float)texturewww.texture.height;

            float aspectRatio_Obj = Obj_x / Obj_y;
            float aspectRatio_Img = Img_x/Img_y;

            if (aspectRatio_Img> aspectRatio_Obj)
            {
                //イメージサイズのほうが横に長い場合
                gObj.GetComponent<Renderer>().material.SetTextureScale("_MainTex", new Vector2(aspectRatio_Obj / aspectRatio_Img, 1f));
                gObj.GetComponent<Renderer>().material.SetTextureOffset("_MainTex", new Vector2(   (Img_x-(Obj_x*Img_y/Obj_y))/(2*Img_x)         , 1f));
            }
            else
            {
                //イメージサイズのほうが縦に長い場合
                gObj.GetComponent<Renderer>().material.SetTextureScale("_MainTex", new Vector2(1f,  aspectRatio_Img/ aspectRatio_Obj));
                gObj.GetComponent<Renderer>().material.SetTextureOffset("_MainTex", new Vector2(1f,  (Img_y-Obj_y*Img_x/Obj_x)/(2*Img_y)          ));
            }
        }

 

 

 

カテゴリー: Unity

Unityからc#でAmazon Web ServiceのS3ストレージにアップロードするメモ

Unity5.3からAWSのS3ストレージへファイルをアップロードするメモです。

キーポイント

  • AWSが用意しているAWS Mobile SDK for Unityを利用する
  • S3への認証はCognito Identityを用いる

参考リンク

手順

S3バケットの作成

任意の名前でS3バケットを生成しておきます。Regionはどこでも構いません。今回はTokyoリージョンにtest-bucket-unityとバケット名で作成しました。

s3-1

以下のポリシーは、test-bucket-unity バケット内のすべてのファイルを表示できるアクセス許可をすべての閲覧者に付与します。このポリシーをコピーし、[Bucket Policy Editor] に貼り付けます。

{
  "Version":"2012-10-17",
  "Statement": [{
    "Sid": "Allow Public Access to All Objects",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::test-bucket-unity/*"
  }
 ]
}

 

Permissionの追加でAny Authenticated AWS UserにListとUpload/Delete権限を付与します。

aws

Identify Pool Idの取得

AWSログイン後、Amazon Cognito管理ページに移動します。 Cogniteは2016年6月現在US-EASTリージョンでしか提供されていません。

s3-2

Manage Federated Identitiesに進みます。

s3-3

Identify pool nameを名づけて、Enable access to unauthenticated identitiesをチェックしてCreate PoolをクリックしてIdentify Poolを作成します。

s3-4

アクセス権限設定のためのIAMロールを新規に作成します。特に規定の値から何も変更せずに「許可」をクリックします。

次に進むと、UnityからAWSへCognito Identify pool IDを用いたアクセスコードのサンプルが表示されます。

s3-5

IAMロール変更(S3アクセス権限付与)

次に作成したIdentify poolでS3へアクセスできるようにしておきましょう。IAMコンソールに移動して、ロールを見ると先ほど生成したIAMロール(今回の場合Cognito_test_pool_nameAuth_Role)がありますので設定を変更します。

s3-6

S3へのフルアクセスポリシーをアタッチします。

s3-7

これで、S3へのアクセス権限は完了。

Unity上でAWS利用

What is the AWS Mobile SDK for Unity? ページからAWS Mobile SDK for Unityをダウンロードします。

解凍したフォルダから下記2つのパッケージをインポートします。

  • AWSSDK.S3.3.1.7.2.unitypackage
  • AWSSDK.IdentityManagement.3.1.4.3.unitypackage

S3ExampleデモシーンでS3にアクセスできることを確認しましょう。

s3-8

S3にファイルをアップロードするクラスを作ったのでシェアしておきます。

using UnityEngine;
using Amazon.S3;
using Amazon.S3.Model;
using System.IO;
using Amazon.CognitoIdentity;
using Amazon;


public class s3upload {

    private CognitoAWSCredentials credentials;
    private string backetNameString;
    private RegionEndpoint regionVal;

    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="IdentityPoolId">CognitoのIdentify Pool ID</param>
    /// <param name="backetName">バケット名</param>
    /// <param name="region">Region未指定の場合はUSEast1</param>
    public s3upload(string IdentityPoolId, string backetName, RegionEndpoint region=null)
    {
        if (region == null) { regionVal = RegionEndpoint.USEast1; }    //Region未指定の場合はUSEast1を設定
        credentials = new CognitoAWSCredentials(IdentityPoolId, regionVal);
        backetNameString = backetName;
    }


    /// <summary>
    /// 指定ファイルをS3バケットにアップロードします
    /// </summary>
    /// <param name="inputFileFullPath">アップロードするローカルファイルパス</param>
    /// <param name="uploadS3path">S3パス。fol/filenameと指定するとfolフォルダ以下にアップロードする</param>
    public void uploadFileToS3(string inputFileFullPath, string uploadS3path)
    {
        AmazonS3Client S3Client = new AmazonS3Client(credentials, regionVal);

        //ファイル読み込み
        var stream = new FileStream(inputFileFullPath,
            FileMode.Open, FileAccess.Read, FileShare.Read);

        //リクエスト作成
        var request = new PostObjectRequest()
        {
            Bucket = backetNameString,
            Key = uploadS3path,
            InputStream = stream,
            CannedACL = S3CannedACL.Private
        };

        //アップロード
        S3Client.PostObjectAsync(request, (responseObj) =>
        {
            if (responseObj.Exception == null){
                //Success
                Debug.Log(uploadS3path + "   :Upload successed");
            }
            else{Debug.LogError(string.Format("\n receieved error {0}", responseObj.Response.HttpStatusCode.ToString()));}
        });
    }
}

利用するには下記のようにする

using UnityEngine;
using System.Collections;
using Amazon;

public class test : MonoBehaviour {

	// Use this for initialization
	void Start () {
        UnityInitializer.AttachToGameObject(this.gameObject);
        string IdentityPoolId = "us-east-1:6f62b9a3-8bbc-xxxx-xxxx-xxxxxxxxxx";
        string backetName = "test-bucket-unity";
        string inputFileFullPath = @"C:\temp\zipicon.png";
        string uploadS3path = "fol1/zipicon.png";

        s3upload s3 = new s3upload(IdentityPoolId, backetName);
        s3.uploadFileToS3(inputFileFullPath, uploadS3path);
    }
	
	// Update is called once per frame
	void Update () {
	
	}
}

メモ

Exception: Main thread has not been set, is the AWSPrefab on the scene?エラーは
UnityInitializer.AttachToGameObject(this.gameObject);
で対処

Editorモードでは動かない?。。。。->動かないようです。。

 

追記(2016/09/04)

エディタモードでは上記方法でS3へのアップロードができないのでc#でコマンドライン上で動くコンソールアプリを開発しUnityから呼び出すことにした。コンソールアプリでは若干実装の方法が異なる
https://github.com/from2001/S3Uploader

1, Visual Studioでコンソールアプリケーションプロジェクトを作成

2,必要ライブラリをNugetでインストール

Install-Package AWSSDK.S3
Install-Package AWSSDK.CognitoIdentity

3,s3upload.cs(コンソールアプリ用)を作成

using System;
using Amazon.S3;
using Amazon.CognitoIdentity;
using Amazon;
using Amazon.S3.Transfer;

public class s3upload
{
    private CognitoAWSCredentials credentials;
    private string g_backetNameString;
    private string g_RegionSystemName_backet;

    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="IdentityPoolId">CognitoのIdentify Pool ID</param>
    /// <param name="backetName">バケット名</param>
    /// <param name="RegionSystemName"> us-west-1, ap-northeast-1, ap-south-1 etc..</param>
    public s3upload(string IdentityPoolId, string RegionSystemName_backet, string backetName, string RegionSystemName_IdentityPoolId)
    {
        RegionEndpoint regionVal = RegionEndpoint.GetBySystemName(RegionSystemName_IdentityPoolId);
        credentials = new CognitoAWSCredentials(IdentityPoolId, regionVal);
        g_backetNameString = backetName;
        g_RegionSystemName_backet = RegionSystemName_backet;
    }

    /// <summary>
    /// 指定ファイルをS3バケットにアップロードします
    /// </summary>
    /// <param name="inputFileFullPath">アップロードするローカルファイルパス</param>
    /// <param name="uploadS3path">S3パス。fol/filenameと指定するとfolフォルダ以下にアップロードする</param>
    public void uploadFileToS3(string inputFileFullPath, string uploadS3path)
    {
        RegionEndpoint Region_backet = RegionEndpoint.GetBySystemName(g_RegionSystemName_backet);
        AmazonS3Client S3Client = new AmazonS3Client(credentials, Region_backet);
        TransferUtility fileTransferUtility = new TransferUtility(S3Client);

        //ファイル転送
        fileTransferUtility.Upload(inputFileFullPath, g_backetNameString, uploadS3path);
        Console.WriteLine("Uploaded: " + uploadS3path);

    }

    /// <summary>
    /// 指定フォルダをS3バケットにアップロードします
    /// </summary>
    /// <param name="inputFileFullPath">アップロードするローカルフォルダパス</param>
    /// <param name="uploadS3dir">S3パス。fol/と指定するとfolフォルダ以下にアップロードする</param>
    public void uploadFolderToS3(string inputFolderFullPath, string uploadS3dir)
    {
        //uploadS3pathの末尾が/でない場合は/を付加
        if (uploadS3dir.EndsWith("/")==false) { uploadS3dir = uploadS3dir + "/"; }
        //inputFolderFullPathの末尾が\でない場合は\を付加
        if (inputFolderFullPath.EndsWith("\\") == false) { inputFolderFullPath = inputFolderFullPath + "\\"; }

        //ファイル一覧取得
        System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(inputFolderFullPath);
        System.IO.FileInfo[] files =
            di.GetFiles("*", System.IO.SearchOption.AllDirectories);

        //1ファイルずつアップロード
        foreach (System.IO.FileInfo f in files)
        {
            string uploadS3path;
            uploadS3path = uploadS3dir + f.FullName.Replace(inputFolderFullPath, "");
            uploadS3path = uploadS3path.Replace(@"\", "/");
            uploadFileToS3(f.FullName, uploadS3path);
        }


    }



}

4,呼び出し方は同じ

S3アップロード用のコマンドラインツールはこちらにアップしました。
S3Uploader

 

カテゴリー: Unity

Asset Bundle利用メモ

Unityのアセットバンドルの利用方法をメモ

アセットストアよりAssetBundle Manager & Example Scenesをダウンロードしてインポート。

ab1

Asset Bundle Managerに関してはまず下記を読んでおく。

ここが変わる!Unity 5のスマホ開発 ~アセットバンドル、ビルド、プラグイン~

 

メモ

  • Local Asset Bundle Serverを実行時に
    Win32Exception: ApplicationName='”C:/Program Files/Unity5.3.5p2/Editor\Data\MonoBleedingEdge\bin\mono.exe”‘エラー
    が出る。=>一度Build AssetBundleを実行するとエラーが発生しなくなる
  • Local Asset Bundle Serverは内部でAssetBundleServer.exeが実行されPort7888のウェブサーバーとして機能する。プロジェクトフォルダ内の\AssetBundlesはhttp://localhost:7888/に対応。他のプロジェクトでビルドしたアセットをテストで利用したい場合はSimulationモードではなく、AssetBundleServerを利用すること。
  • Asset Bundle Managerは二重ロードや依存解決してくれるコードが含まれていて便利なラッパー。
  • アセットバンドルにはスクリプトを含めることができない

 

Asset Bundleを体験して理解するために、一連の流れを試してみる

ABProject1で作成したPrefabアセットを、ABProject2で読み込んでみる

ABProject1にて(アセットバンドル作成)

  1. Asset StoreからAssetBundle Manager & Example Scenesをインポート
    1. オブジェクトを作成(CylinderとCubeを組み合わせた)
    2. ProjectビューにドラッグしてPrefab化(Prefab名:asset_prefab1)
    3. ProjectビューのPrefabにInspectorビューでAssetBundle名をつける(AssetBundle名:ab1)ab2
  2. アセットをビルド(Assets – AssetBundles – BuildAssetbundles)ab3
  3. Windowsの場合は\ABProject1\AssetBundles\Windows以下にビルドされたアセットが作成される。

ABProject2にて(アセットバンドル読み込み)

  1. Asset StoreからAssetBundle Manager & Example Scenesをインポート
  2. アセットをビルド(Assets – AssetBundles – BuildAssetbundles)をダミー実行する。これを初回行わないとLocalAssetBundleServerがエラーを吐く
  3. ABProject1で作成したアセットファイルをABProject2フォルダにコピーする
    コピーファイル:ab1、ab1.manifest
    コピー元:\ABProject1\AssetBundles\Windows
    コピー先:\ABProject2\AssetBundles\Windows
  4. LocalAssetBundleServerを起動
    ab5
  5. アセットロード用のスクリプトを設定
    LoadAssetsスクリプトを任意のオブジェクト(今回はLoaderと名付けた空オブジェクト)に貼り付ける
    Asset Bundle Name:ビルドするときに名付けたアセット名
    Asset Name:復元するアセット化したPrefabの名前ab6
  6. 実行すると、アセットバンドル化したPrefabが読み込まれますab7

 

動作を含むオブジェクトをアセットバンドル化して配信したい

アセットバンドルには通常の方法ではスクリプトを含めることができません。アセットバンド化する際にはスクリプトの参照情報のみビルドされます。つまり、スクリプトファイルは、アセット読み込み側プロジェクトにも予め用意しておかなくてはいけません。

特殊な方法としてスクリプトをDLL化して配信するという方法がありますが今回は扱いません。下記のサイトに方法がありますので、参考に。
ゲームをビルドした後でもスクリプト(機能)を追加する(テラシュールブログ)
How to compile script to include it to AssetBundle?(Unity Forum)

動きを含むアセットを配信する一番簡単な方法はPlaymakerなどビジュアルスクリプティングソリューションを用いることのように思います。Playmakerで設定したオブジェクトの挙動はビルド時にアセットバンドル化されるため配信可能です。読み込み側プロジェクトにもPlaymakerをインストールしておけば、配信先でも動作します。ものすごく簡単で便利。

ab8

アセットバンドルのキャッシュに関して

AssetBundle Manager & Example ScenesのLoadAssets.csスクリプトは内部でLoadFromCacheOrDownload関数をもちいてアセットをダウンロードしています。既に読み込んだことのあるAssetbundle名のアセットは、LoadAssets.csスクリプトもLoadFromCacheOrDownload関数もキャッシュから読み込みます。つまり、普通にビルドするアセットバンドルを更新して配信するだけでは、そのアセットが新しいものなのかどうか判断してくれません。

キャッシュをクリアするには

  • LoadFromCacheOrDownloadの引数でバージョンを指定する。(キャッシュした時より大きい番号を指定すると再読込する)
  • Caching.CleanCache();関数でキャッシュをクリアする

アップロードされているmanifestファイル更新されている時だけアセット本体ダウンロードしなおしてくれればいいのに。。。自作するかな。

スクリプト経由でAssetBundleNameを付加する方法


 

とりあえず、ここまで。後々追記予定。

 

 

カテゴリー: Unity

Unityでビデオストリーミングをテクスチャとして表示する(アセットなしでOK)

テクスチャ上でビデオを再生するにはAVProアセットEasy Movie Texture (Video Texture)などを使う方法がありますがUnityのMovieテクスチャを使えば追加アセット無しでも実現することが可能です。

ウェブサーバーからストリーミングされる動画をテクスチャに貼るにはどうしたらいいものかと調べていたらUnity標準のMovieテクスチャでも実現できることがわかった。ただし、動画ファイル形式はogg形式でないとダメなようだ。

ウェブサーバー上のoggビデオファイルをストリーミング再生する

下記コードをOggVideoStreamingTexture.csとして保存する。

using UnityEngine;
using System.Collections;
using System;

public class OggVideoStreamingTexture : MonoBehaviour {

    public string OggVideoURL;
    public GameObject GameobjectForVideoTexture;

    void Start () {
        StreamPlayVideoAsTexture();
    }

    public void StreamPlayVideoAsTexture()
    {
        if (this.OggVideoURL!="") {
            StartCoroutine(StartStream(this.OggVideoURL));
        }
    }

    protected IEnumerator StartStream(String url)
    {
         MovieTexture movieTexture;

        //エラー2つ出るが無視してOK
        //https://issuetracker.unity3d.com/issues/movietexture-fmod-error-when-trying-to-play-video-using-www-class
        Debug.Log("Ignore following two errors");
        WWW videoStreamer = new WWW(url);
        movieTexture = videoStreamer.movie;
        while (!movieTexture.isReadyToPlay)
        {
            yield return 0;
        }
        GameobjectForVideoTexture.GetComponent<Renderer>().material.mainTexture = movieTexture;
        AudioSource audioSource = GameobjectForVideoTexture.AddComponent<AudioSource>();
        audioSource.clip = movieTexture.audioClip;
        movieTexture.Play();
        audioSource.Play();
    }

}

任意のGameobjectに貼り付けます。

OggVideoURL:ストリーム再生するoggビデオのURL
サンプルで http://www.unity3d.com/webplayers/Movie/sample.ogg を利用して試そう

GameobjectForVideoTexture:ビデオを表示するオブジェクト。未指定の場合はスクリプトをアタッチしたオブジェクトに動画が表示されます。

ogg1

実行すると動画が表示されます。サーバーからダウンロード途中でも再生がスタートします。エラーが2つ出ますが無視してOKです。海外のフォーラムでも話題にでていましたがUnityのバグっぽい。

ogg2

 

ogg形式へビデオファイルのコンバート方法

上記スクリプトでの動画ストリーミング再生には、動画のファイル形式がogg形式である必要があります。各種ビデオファイルをogg形式へ変換するスクリプトを作成したので紹介しておく。スクリプトはVBScriptで記述したWidnows Scripting Hostです。(VBScriptを拡張子.vbsで保存すればそのままWindowsで実行できて便利)

  1. ffmpegのダウンロード
    ffmpeg公式サイトからWindows用バイナリをダウンロード
    zipファイルを解凍する
  2. 下記スクリプトをConvert_video_to_ogg.vbsとして保存。1で解凍したffmpegフォルダに設置する
    '==============================================
    'Video file to ogg video convert script with ffmpeg
    '	2016-06-13 @from2001vr
    '==============================================
    OggQuality_video = 5	'0 to 10
    OggQuality_audio = 5	'0 to 10
    
    ffmpegPath = "bin\ffmpeg.exe"
    
    MsgBox "Ogg video file will be created at the same folder.",0,"Choose video file to convert"
    'ファイル選択
    InputVideoFilePath = FileDialog()
    
    '変換処理コマンド生成
    commandString = ffmpegPath + " -i " + InputVideoFilePath + "  -codec:v libtheora -qscale:v " + cstr(OggQuality_video) + " -codec:a libvorbis -qscale:a " + cstr(OggQuality_audio) + " " + Left(InputVideoFilePath, Len(InputVideoFilePath) - 4) + ".ogg"
    
    
    '処理実行
    dim objWShell
    Set objShell = WScript.CreateObject("WScript.Shell")
    objShell.Run commandString, 1, true
    Set objShell = Nothing
    
    '保存フォルダを開く
    Set objShell = WScript.CreateObject("Shell.Application")
    objShell.Explore Left(InputVideoFilePath, InStrRev(InputVideoFilePath, "\"))
    
    'ファイル選択ダイアログ
    function FileDialog()
    	Set wShell=CreateObject("WScript.Shell")
    	Set oExec=wShell.Exec("mshta.exe ""about:<input type=file id=FILE><script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);</script>""")
    	FileDialog = oExec.StdOut.ReadLine
    End Function
    
  3. Convert_video_to_ogg.vbs をダブルクリックして実行

説明文書が表示されるのでOKを押す

ogg3

ビデオファイルを選択する

ogg4

後は、変換されるのを待つ。oggファイルは元ビデオと同じフォルダに生成されます。

ogg5

ffmpegとogg変換スクリプトのセットをこちらに置いておきます( GPL 3.0ライセンスによる再配布)

zipiconffmpeg-20160610-git-0a9e781-win32-static_with_ogg_video_convert_script.zip

 

 

カテゴリー: Unity

UnityでC#を用いてInstagram APIを利用するメモ

Instagram API利用時のメモです。
今回は、Instagramの任意のユーザーの新着を取得するのに必要な手順で、それ以外の利用方法は今回のメモの対象外です。

まず、事前知識として知っておくと理解が早い情報

  • 一般公開されている写真の情報を取得するだけでもAPIを用いる必要がある。
  • APIは審査基準が厳しい
  • 審査通るまではSANDBOXモードで動作し、10ユーザーの新着20件までの情報しか取得できない
  • SANDBOXモードで取得するユーザーは個別に許可をもらう必要がある
  • APIの利用はURL ENDPOINTにアクセスすることでJSON形式でデータを取得することができるREST APIなので実装は難しくない
  • usernameとuseridはことなり、APIで利用するのはuserid。(APIを用いてusernameからuseridを取得する必要あり。ここを理解していなくてハマった。)
  • APIの利用にはアクセストークンが必要。これは、管理画面で発行されるClient IDともClient Secretとも違い、Client IDを用いて別途取得する必要がある。(セッションごとに必要なものではなく、一度取得すればリセットしないかぎり使える)
  • 2015年10月17日からAPIの審査が必要になったらしい。なので、この日付より古いネットの情報は注意が必要

事前準備

  1. Developer登録
    https://www.instagram.com/developer/
    から開発者情報を入力
  2. Applicationの登録
    Detailsタブ
    Valid redirect URIs:
    アクセストークンを取得するのに利用。今回の用途では実在するURLであればひとまずなんでも良いSecurityタブ
    Disable implicit OAuth:チェックを外す
    Enforce signed requests:チェックを外す
  3. ApplicationごとのClient IDが発行されるのでメモします
  4. Sandboxユーザーの追加
    Manage Clients – EDIT – Sandbox
    で写真を取得したいユーザーを追加します。
    追加したユーザーには個別に承認を貰う必要があります。
  5. アクセストークンの取得
    APIを利用する際に必要なAccess Tokenを取得します。
    ・Application登録時に設定したRedirect URL
    ・取得したClient ID
    を下記URLに含めてブラウザからアクセスします。

    https://www.instagram.com/oauth/authorize/?response_type=token&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URL}

    insta1
    認証を求められるのでAuthorizeをクリック
    ブラウザのページがリダイレクトで指定したサイトにジャンプします。
    insta2
    その際、ブラウザのアドレスバーのURLに表示されるaccess_token以降の文字列がアクセストークンになります。

  6. 情報を取得したいユーザーのuseridを取得
    繰り返しになりますが、SANDBOXモードでは写真や情報を取得するユーザーには個別に許可を貰う必要があります。またAPIではusernameではなくuseridを利用する必要があるため、対象ユーザーのuseridを取得します。
    usernameとはhttps://www.instagram.com/kyarykyary0129/ のkyarykyary0129の部分です。
    下記URLでUSERNAMEとACCESS_TOKENを指定してブラウザでアクセス

    https://api.instagram.com/v1/users/search?q={USERNAME}&access_token={ACCESS_TOKEN}

    ブラウザにUSERNAMEで指定したユーザーの情報が表示されます。(見やすく整形しています)

    {
        "data": [
            {
                "bio": "", 
                "full_name": "jun kawasaki", 
                "id": "4159593", 
                "profile_picture": "https://scontent.cdninstagram.com/t51.2885-19/s150x150/12816775_1001839336556997_1168307022_a.jpg", 
                "username": "jun784", 
                "website": "http://junkawasaki.me"
            }
        ], 
        "meta": {
            "code": 200
        }
    }

    上記の場合、useridは4159593になります。

 

写真投稿の取得

API ENDPOINTのドキュメントはこちら

ここまでの事前準備で取得した
・アクセストークン
・取得対象ユーザーのuserid
をAPIで利用して情報をとります

指定ユーザーの新着情報取得

https://api.instagram.com/v1/users/{user-id}/media/recent/?access_token={ACCESS-TOKEN}

 

Instagramの投稿写真を取得するためのコードを作成したので公開しておきます。写真一覧取るだけのシンプルなものです。今後これをベースに機能追加予定。

MiniJSON及びJsonNodeをダウンロードしておくこと。

using UnityEngine;
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Generic;
using System.Linq;

//Unity C#でJSONの扱い方
//http://qiita.com/phi/items/914bc839b543988fc0ec
//http://qiita.com/asus4/items/bac121c34cd3169116c0
using MiniJSON;
//Also Download JsonNode


public class InstagramApi : MonoBehaviour
{
        public string access_token;
        public string username;
        public GameObject[] PhotoFrames;

        public InstagramApi(string access_token)
        {
            this.access_token = access_token;
        }

    void Start()
    {
        StartCoroutine("MainRoutine");
    }


    /// <summary>
    /// 設定された情報を元にインスタグラムにアクセスしてフォトフレームを書き換えます
    /// </summary>
    private IEnumerator<bool> MainRoutine()
    {
        //未設定チェック
        if (username == "") { Debug.Log("username is not set");return null; }
        if (access_token == "") { Debug.Log("access token is not set"); return null; }
        if (PhotoFrames.Length==0) { Debug.Log("PhotoFrames is not set"); return null; }

        //メイン処理
        var userid = getUseridFomUsername(username);
        var photoURLs = getRecentPhotos(userid);
        for (int i = 0; i < PhotoFrames.Length; i++)
        {
            if (i >= photoURLs.Length) { break; }
            StartCoroutine(attacheWebImageToGameobject(photoURLs[i], PhotoFrames[i]));
        }
        return null;
    }



    /// <summary>
    /// InstagramユーザーネームからユーザーIDを取得する関数
    /// </summary>
    /// <param name="username">ユーザーネーム</param>
    /// <returns></returns>
    public string getUseridFomUsername(string username)
        {
            string API_URI = "https://api.instagram.com/v1/users/search?q={USERNAME}&access_token={ACCESS_TOKEN}";
            API_URI = API_URI.Replace("{USERNAME}", username);
            API_URI = API_URI.Replace("{ACCESS_TOKEN}", this.access_token);
            var jsonText = getHtml(API_URI);
            var json = JsonNode.Parse(jsonText);
            var id = json["data"][0]["id"].Get<string>();
            return (id);
        }


        /// <summary>
        /// 指定のユーザーの最新投稿写真のURLを配列で取得します。動画の場合はサムネイル画像になります。
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public string[] getRecentPhotos(string userid, int count = 20)
        {
            List<string>PhotoURLs= new List<string>();

            string API_URI = "https://api.instagram.com/v1/users/{USERID}/media/recent/?access_token={ACCESS_TOKEN}&count={COUNT}";
            API_URI = API_URI.Replace("{USERID}", userid);
            API_URI = API_URI.Replace("{ACCESS_TOKEN}", this.access_token);
            API_URI = API_URI.Replace("{COUNT}", count.ToString());
            var jsonText = getHtml(API_URI);
            var json = JsonNode.Parse(jsonText);
            var data = json["data"];
            foreach(var d in data)
            {
                var PhotoURL = d["images"]["standard_resolution"]["url"].Get<string>();
                PhotoURLs.Add(PhotoURL);
            }
            return (PhotoURLs.ToArray());
        }

    /// <summary>
    /// //指定したウェブ画像を読み込んでゲームオブジェクトのテクスチャとして表示
    /// 呼び出し方:StartCoroutine(attacheWebImageToGameobject(PhotoURL, Gameobject));
    /// </summary>
    /// <param name="url"></param>
    /// <param name="gObj"></param>
    /// <returns></returns>
    private IEnumerator<WWW> attacheWebImageToGameobject(string url, GameObject gObj)
        {
        WWW texturewww = new WWW(url);
        yield return texturewww;
        gObj.GetComponent<Renderer>().material.mainTexture = texturewww.texture;
        }





        /// <summary>
        /// HTMLの取得関数(SSLエラー対処済み)
        /// </summary>
        /// <param name="URL"></param>
        /// <returns></returns>
        private string getHtml(string URL)
        {
            SSLValidator.OverrideValidation();//Avoid SSL error
            WebClient wc = new WebClient();
            Stream st = wc.OpenRead(URL);
            Encoding enc = Encoding.GetEncoding("utf-8");
            StreamReader sr = new StreamReader(st, enc);
            string html = sr.ReadToEnd();
            sr.Close();
            st.Close();
            return (html);
        }

    }

    //Avoid SSL error
    //http://stackoverflow.com/questions/18454292/system-net-certificatepolicy-to-servercertificatevalidationcallback-accept-all-c
    public static class SSLValidator
    {
        private static bool OnValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
        public static void OverrideValidation()
        {
            ServicePointManager.ServerCertificateValidationCallback = OnValidateCertificate;
            ServicePointManager.Expect100Continue = true;
        }
    }


    //【Unity】指定したゲームオブジェクトから名前で子オブジェクトを検索する拡張メソッド
    //http://baba-s.hatenablog.com/entry/2014/08/01/101104
    public static class GameObjectExtensions
    {
        /// <summary>
        /// 深い階層まで子オブジェクトを名前で検索して GameObject 型で取得します
        /// </summary>
        /// <param name="self">GameObject 型のインスタンス</param>
        /// <param name="name">検索するオブジェクトの名前</param>
        /// <param name="includeInactive">非アクティブなオブジェクトも検索する場合 true</param>
        /// <returns>子オブジェクト</returns>
        public static GameObject FindDeep(
            this GameObject self,
            string name,
            bool includeInactive = false)
        {
            var children = self.GetComponentsInChildren<Transform>(includeInactive);
            foreach (var transform in children)
            {
                if (transform.name == name)
                {
                    return transform.gameObject;
                }
            }
            return null;
        }
    }

 

 

カテゴリー: Unity

HOME / Coporate Site/ Careers

© Copyright 2018 STYLY..