20191128のUnityに関する記事は11件です。

Unity ARなiphoneアプリで遊んでみた

https://qiita.com/nonkapibara/items/3800d4ff3c56912073df

Fusion360で作ったモデルをfbxファイルにして、unityに取り込む。

で、build and run。

xcodeでprovisoiningのエラー出たら、bulid settingでsignをすべてiOS developperに変更すれば良い。
https://qiita.com/umi_mori/items/1ffe2d56ad97e64cbac0

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity ARなiphoneアプリをつくってみた

https://qiita.com/nonkapibara/items/3800d4ff3c56912073df

Fusion360で作ったモデルをfbxファイルにして、unityに取り込む。

で、build and run。

xcodeでprovisoiningのエラー出たら、bulid settingでsignをすべてiOS developperに変更すれば良い。
https://qiita.com/umi_mori/items/1ffe2d56ad97e64cbac0

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

簡単にイントロ付きループBGMが作れるIntroLoopの紹介

前提

この記事は、Unity アセット冬のアドベントカレンダー 2019 のために書かれた記事です。

Unityアセット冬のアドベントカレンダー 2019 Winter! – Unity公式 Asset Portal

この記事では、簡単にイントロ付きループBGMが作れるアセットIntroLoopをご紹介したいと思います。

Introloop(AssetStoreへのリンク)
Youtubeの解説動画

IntroLoopとは?

UnityのデフォルトのAudio Sourceでは、BGMのループはBGMの最初と最後をループすることしかできません。
IntroLoop1.png
しかしBGMによっては、まずイントロ部分を流しその後のループ部分をループしたいという、イントロ付きループをしたい場合があります。

IntroLoopでは、下図のようにIntro BoundaryとLooping Boundaryを設定することで自由にループ部分を指定することできます。
IntroLoop2.png

このアセットを使う利点を細かく挙げると、

  • イントロ付きループをするために、オーディオファイルをカットしたりする必要はない
  • イントロ付きループをするためのプログラムを書く必要はない。(再生処理などのコントロールはプログラムで実行します)
  • ループ地点の数値指定なので、ループの設定がとても楽
  • オーディオファイルのメモリリリースを適切に行なってくれるのでモバイルでも安心
  • ポーズ、リジューム、フェードイン、フェードアウト、クロスフェードなど多様なコントロールができる
  • オーディオごとにボリューム、ピッチの設定、ループ形式(イントロループ、ループ、ループなし)の設定が可能
  • AudioMixerGroupとの連携も普通にできる
  • フルソースコード、Package Manager対応、コーディングも良い

などがあります。

使い方

使い方はとても簡単です。大体4つの工程に分かれます。

  1. オーディオファイルを用意する
  2. オーディオファイルのループポイントを調べる
  3. IntroloopAudioアセットファイルを作成する
  4. IntroloopPlayerシングルトンを使ってIntroloopAudioを再生する

1. オーディオファイルを用意する

イントロ付きループを行うオーディオファイルを用意します(wav/ogg/mp3など)。
用意したオーディオファイルをUnityにインポートして、AudioClipアセットファイルとしておきます。

2. オーディオファイルのループポイントを調べる

イントロ付きループの2つのループポイント(Intro BoundaryとLooping Boundary)の位置をミリ秒単位で調べます。
IntroLoop2.png

ループポイントのを調べるためには、Audacityなどのオーディオ編集ソフトを利用します。(私はAdobeのAuditionを使っています。こちらも便利です。)今回はIntroLoopの紹介で、オーディオ編集ソフトを用いたループポイントの調べ方は記事の範囲を逸脱しますので省略します。

Audacity ® | Free, open source, cross-platform audio software for multi-track recording and editing.

なお、オーディオ編集ソフトでループポイントを調べるのがベストな方法ですが、
Unity内でループポイントを微調整していくだけでもループポイントを設定できると思います(時間がかかるかもしれません)。

3. IntroloopAudioアセットファイルを作成する

1.で用意したAudioClipアセットファイルを右クリックして出てくるメニューから、Create > Introloop > IntroloopAudioでIntroloopAudioアセットファイルを作成します(下図の1.)。

作成したIntroloopAudioアセットファイルを選択して、設定を行います(下図の2.)。

introloop-asset.png

Audio Clipには対象のオーディオファイルのAudioClipアセットファイルを指定します。

Volume、Pictchを設定します。オーディオファイルの音が大きすぎたり、小さすぎたりする場合にここで調整できます。

LoopモードはIntroloop/Loop/Non Loopingから選べます。イントロ付きループをしたい場合はIntroLoopを選びます。Loopの場合はオーディオファイルの最初と最後をループします。Non Loopingの場合はループしません。IntroLoopでは、これらのモードを同じIntroloopPlayerシングルトンで操作できます。
introloop-audio-set.png

4. IntroloopPlayerシングルトンを使ってIntroloopAudioを再生する

以下のようなコードを書いて3.で用意したIntroloopAudioをコントロールします。
コントロール内容は(再生する/ポーズする/再開する/シークする/停止する)などです。

introloop.cs
using System;
using System.Collections;
using UnityEngine;
using E7.Introloop;

public class MyTest : MonoBehaviour
{
    public IntroloopAudio introloopAudio;

    // 再生する
    public void Play()
    {
        // Introloopならイントロ付きループで、
        // Loopならループで、
        // Non loopingならループなしで再生されます。
        IntroloopPlayer.Instance.Play(introloopAudio);

        // フェードインしながら再生もできる
        // IntroloopPlayer.Instance.Play(introloopAudio, fadetime);
    }

    // ポーズする
    public void Pause()
    {
        IntroloopPlayer.Instance.Pause();

        // フェードアウトしながらポーズもできる
        // IntroloopPlayer.Instance.Pause(fadetime);
    }

    // 再開する
    public void Resume()
    {
        IntroloopPlayer.Instance.Resume();

        // フェードインしながら再開もできる
        // IntroloopPlayer.Instance.Resume(fadetime);
    }

    // 指定した時間にシークする
    public void Seek(float elapsedTime)
    {
        IntroloopPlayer.Instance.Seek(elapsedTime);
    }

    // 停止する
    public void Stop()
    {
        IntroloopPlayer.Instance.Stop();

        // フェードアウトしながら停止もできる
        // IntroloopPlayer.Instance.Stop(fadetime);
    }
}

上記コードのように、IntroloopAudioの(再生する/ポーズする/再開する/シークする/停止する)はIntroloopPlayerを使って行われます。
IntroloopPlayerはシングルトンとして実装されています。シングルトンについては以下を参照してください。

[Unity]シングルトンを使ってみよう - Qiita

その他、IntroloopPlayerにはAudioMixerの設定項目があります。
ここにAudioMixerを指定することで、AudioMixerの機能を利用できます。
Untitled-2.png

デモでIntroLoopの挙動を確認

デモプログラムはここで確認できます。購入前に確認してみましょう。

Demo | Introloop

サポートは日本語で大丈夫のようです

作者様はタイの方のようですが、Forumを見たところ日本語でのサポート可能なようです。日本人でも安心してアセットを利用できます。

Introloop - Easily play looping music with intro section - Unity Forum

リンク

関連するリンクのまとめです。

Introloop(AssetStoreへのリンク)

Introloop(ホームページ)

Introloop(フォーラム(日本語可能))

最後に

とても便利なので、Unityでお手軽にイントロ付きループをしたい人は是非IntroLoopを使いましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

簡単にイントロ付きループBGMが作れるIntroLoop

前提

この記事は、Unity アセット冬のアドベントカレンダー 2019 のために書かれた記事です。

Unityアセット冬のアドベントカレンダー 2019 Winter! – Unity公式 Asset Portal

この記事では、簡単にイントロ付きループBGMが作れるアセットIntroLoopをご紹介したいと思います。

Introloop(AssetStoreへのリンク)

↓Youtubeの解説動画
Youtubeの解説動画

IntroLoopとは?

UnityのデフォルトのAudio Sourceでは、BGMのループはBGMの最初と最後をループすることしかできません。
IntroLoop1.png
しかしBGMによっては、まずイントロ部分を流しその後のループ部分をループしたいという、イントロ付きループをしたい場合があります。

IntroLoopでは、下図のようにIntro BoundaryとLooping Boundaryを設定することで自由にループ部分を指定することできます。
IntroLoop2.png

このアセットを使う利点を細かく挙げると、

  • イントロ付きループをするために、オーディオファイルをカットしたりする必要はない
  • イントロ付きループをするためのプログラムを書く必要はない。(再生処理などのコントロールはプログラムで実行します)
  • ループ地点の数値指定なので、ループの設定がとても楽
  • オーディオファイルのメモリリリースを適切に行なってくれるのでモバイルでも安心
  • ポーズ、リジューム、フェードイン、フェードアウト、クロスフェードなど多様なコントロールができる
  • オーディオごとにボリューム、ピッチの設定、ループ形式(イントロループ、ループ、ループなし)の設定が可能
  • AudioMixerGroupとの連携も普通にできる
  • フルソースコード、Package Manager対応、コーディングも良い

などがあります。

使い方

使い方はとても簡単です。大体4つの工程に分かれます。

  1. オーディオファイルを用意する
  2. オーディオファイルのループポイントを調べる
  3. IntroloopAudioアセットファイルを作成する
  4. IntroloopPlayerシングルトンを使ってIntroloopAudioを再生する

1. オーディオファイルを用意する

イントロ付きループを行うオーディオファイルを用意します(wav/ogg/mp3など)。
用意したオーディオファイルをUnityにインポートして、AudioClipアセットファイルとしておきます。

2. オーディオファイルのループポイントを調べる

イントロ付きループの2つのループポイント(Intro BoundaryとLooping Boundary)の位置をミリ秒単位で調べます。
IntroLoop2.png

ループポイントのを調べるためには、Audacityなどのオーディオ編集ソフトを利用します。(私はAdobeのAuditionを使っています。こちらも便利です。)今回はIntroLoopの紹介で、オーディオ編集ソフトを用いたループポイントの調べ方は記事の範囲を逸脱しますので省略します。

Audacity ® | Free, open source, cross-platform audio software for multi-track recording and editing.

なお、オーディオ編集ソフトでループポイントを調べるのがベストな方法ですが、
Unity内でループポイントを微調整していくだけでもループポイントを設定できると思います(時間がかかるかもしれません)。

3. IntroloopAudioアセットファイルを作成する

1.で用意したAudioClipアセットファイルを右クリックして出てくるメニューから、Create > Introloop > IntroloopAudioでIntroloopAudioアセットファイルを作成します(下図の1.)。

作成したIntroloopAudioアセットファイルを選択して、設定を行います(下図の2.)。

introloop-asset.png

Audio Clipには対象のオーディオファイルのAudioClipアセットファイルを指定します。

Volume、Pictchを設定します。オーディオファイルの音が大きすぎたり、小さすぎたりする場合にここで調整できます。

LoopモードはIntroloop/Loop/Non Loopingから選べます。イントロ付きループをしたい場合はIntroLoopを選びます。Loopの場合はオーディオファイルの最初と最後をループします。Non Loopingの場合はループしません。IntroLoopでは、これらのモードを同じIntroloopPlayerシングルトンで操作できます。
introloop-audio-set.png

4. IntroloopPlayerシングルトンを使ってIntroloopAudioを再生する

以下のようなコードを書いて3.で用意したIntroloopAudioをコントロールします。
コントロール内容は(再生する/ポーズする/再開する/シークする/停止する)などです。

MyTest.cs
using System;
using System.Collections;
using UnityEngine;
using E7.Introloop;

public class MyTest : MonoBehaviour
{
    public IntroloopAudio introloopAudio;

    // 再生する
    public void Play()
    {
        // Introloopならイントロ付きループで、
        // Loopならループで、
        // Non loopingならループなしで再生されます。
        IntroloopPlayer.Instance.Play(introloopAudio);

        // フェードインしながら再生もできる
        // IntroloopPlayer.Instance.Play(introloopAudio, fadetime);
    }

    // ポーズする
    public void Pause()
    {
        IntroloopPlayer.Instance.Pause();

        // フェードアウトしながらポーズもできる
        // IntroloopPlayer.Instance.Pause(fadetime);
    }

    // 再開する
    public void Resume()
    {
        IntroloopPlayer.Instance.Resume();

        // フェードインしながら再開もできる
        // IntroloopPlayer.Instance.Resume(fadetime);
    }

    // 指定した時間にシークする
    public void Seek(float elapsedTime)
    {
        IntroloopPlayer.Instance.Seek(elapsedTime);
    }

    // 停止する
    public void Stop()
    {
        IntroloopPlayer.Instance.Stop();

        // フェードアウトしながら停止もできる
        // IntroloopPlayer.Instance.Stop(fadetime);
    }
}

上記コードのように、IntroloopAudioの(再生する/ポーズする/再開する/シークする/停止する)はIntroloopPlayerを使って行われます。
IntroloopPlayerはシングルトンとして実装されています。シングルトンについては以下を参照してください。

[Unity]シングルトンを使ってみよう - Qiita

その他、IntroloopPlayerにはAudioMixerの設定項目があります。
ここにAudioMixerを指定することで、AudioMixerの機能を利用できます。
Untitled-2.png

デモでIntroLoopの挙動を確認

デモプログラムはここで確認できます。購入前に確認してみましょう。

Demo | Introloop

サポートは日本語で大丈夫のようです

作者様はタイの方のようですが、Forumを見たところ日本語でのサポート可能なようです。日本人でも安心してアセットを利用できます。

Introloop - Easily play looping music with intro section - Unity Forum

リンク

関連するリンクのまとめです。

Introloop(AssetStoreへのリンク)

Introloop(ホームページ)

Introloop(フォーラム(日本語可能))

最後に

とても便利なので、Unityでお手軽にイントロ付きループをしたい人は是非IntroLoopを使いましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IntroLoopで簡単にイントロ付きループBGMを作る

前提

この記事は、Unity アセット冬のアドベントカレンダー 2019 のために書かれた記事です。

Unityアセット冬のアドベントカレンダー 2019 Winter! – Unity公式 Asset Portal

この記事では、簡単にイントロ付きループBGMが作れるアセットIntroLoopをご紹介したいと思います。

Introloop(AssetStoreへのリンク)

↓Youtubeの解説動画
Youtubeの解説動画

IntroLoopとは?

UnityのデフォルトのAudio Sourceでは、BGMのループはBGMの最初と最後をループすることしかできません。
IntroLoop1.png
しかしBGMによっては、まずイントロ部分を流しその後のループ部分をループしたいという、イントロ付きループをしたい場合があります。

IntroLoopでは、下図のようにIntro BoundaryとLooping Boundaryを設定することで自由にループ部分を指定することできます。
IntroLoop2.png

このアセットを使う利点を細かく挙げると、

  • イントロ付きループをするために、オーディオファイルをカットしたりする必要はない
  • イントロ付きループをするためのプログラムを書く必要はない。(再生処理などのコントロールはプログラムで実行します)
  • ループ地点の数値指定なので、ループの設定がとても楽
  • オーディオファイルのメモリリリースを適切に行なってくれるのでモバイルでも安心
  • ポーズ、リジューム、フェードイン、フェードアウト、クロスフェードなど多様なコントロールができる
  • オーディオごとにボリューム、ピッチの設定、ループ形式(イントロループ、ループ、ループなし)の設定が可能
  • AudioMixerGroupとの連携も普通にできる
  • フルソースコード、Package Manager対応、コーディングも良い

などがあります。

使い方

使い方はとても簡単です。大体4つの工程に分かれます。

  1. オーディオファイルを用意する
  2. オーディオファイルのループポイントを調べる
  3. IntroloopAudioアセットファイルを作成する
  4. IntroloopPlayerシングルトンを使ってIntroloopAudioを再生する

1. オーディオファイルを用意する

イントロ付きループを行うオーディオファイルを用意します(wav/ogg/mp3など)。
用意したオーディオファイルをUnityにインポートして、AudioClipアセットファイルとしておきます。

2. オーディオファイルのループポイントを調べる

イントロ付きループの2つのループポイント(Intro BoundaryとLooping Boundary)の位置をミリ秒単位で調べます。
IntroLoop2.png

ループポイントのを調べるためには、Audacityなどのオーディオ編集ソフトを利用します。(私はAdobeのAuditionを使っています。こちらも便利です。)今回はIntroLoopの紹介で、オーディオ編集ソフトを用いたループポイントの調べ方は記事の範囲を逸脱しますので省略します。

Audacity ® | Free, open source, cross-platform audio software for multi-track recording and editing.

なお、オーディオ編集ソフトでループポイントを調べるのがベストな方法ですが、
Unity内でループポイントを微調整していくだけでもループポイントを設定できると思います(時間がかかるかもしれません)。

3. IntroloopAudioアセットファイルを作成する

1.で用意したAudioClipアセットファイルを右クリックして出てくるメニューから、Create > Introloop > IntroloopAudioでIntroloopAudioアセットファイルを作成します(下図の1.)。

作成したIntroloopAudioアセットファイルを選択して、設定を行います(下図の2.)。

introloop-asset.png

Audio Clipには対象のオーディオファイルのAudioClipアセットファイルを指定します。

Volume、Pictchを設定します。オーディオファイルの音が大きすぎたり、小さすぎたりする場合にここで調整できます。

LoopモードはIntroloop/Loop/Non Loopingから選べます。イントロ付きループをしたい場合はIntroLoopを選びます。Loopの場合はオーディオファイルの最初と最後をループします。Non Loopingの場合はループしません。IntroLoopでは、これらのモードを同じIntroloopPlayerシングルトンで操作できます。
introloop-audio-set.png

4. IntroloopPlayerシングルトンを使ってIntroloopAudioを再生する

以下のようなコードを書いて3.で用意したIntroloopAudioをコントロールします。
コントロール内容は(再生する/ポーズする/再開する/シークする/停止する)などです。

MyTest.cs
using System;
using System.Collections;
using UnityEngine;
using E7.Introloop;

public class MyTest : MonoBehaviour
{
    public IntroloopAudio introloopAudio;

    // 再生する
    public void Play()
    {
        // Introloopならイントロ付きループで、
        // Loopならループで、
        // Non loopingならループなしで再生されます。
        IntroloopPlayer.Instance.Play(introloopAudio);

        // フェードインしながら再生もできる
        // IntroloopPlayer.Instance.Play(introloopAudio, fadetime);
    }

    // ポーズする
    public void Pause()
    {
        IntroloopPlayer.Instance.Pause();

        // フェードアウトしながらポーズもできる
        // IntroloopPlayer.Instance.Pause(fadetime);
    }

    // 再開する
    public void Resume()
    {
        IntroloopPlayer.Instance.Resume();

        // フェードインしながら再開もできる
        // IntroloopPlayer.Instance.Resume(fadetime);
    }

    // 指定した時間にシークする
    public void Seek(float elapsedTime)
    {
        IntroloopPlayer.Instance.Seek(elapsedTime);
    }

    // 停止する
    public void Stop()
    {
        IntroloopPlayer.Instance.Stop();

        // フェードアウトしながら停止もできる
        // IntroloopPlayer.Instance.Stop(fadetime);
    }
}

上記コードのように、IntroloopAudioの(再生する/ポーズする/再開する/シークする/停止する)はIntroloopPlayerを使って行われます。
IntroloopPlayerはシングルトンとして実装されています。シングルトンについては以下を参照してください。

[Unity]シングルトンを使ってみよう - Qiita

その他、IntroloopPlayerにはAudioMixerの設定項目があります。
ここにAudioMixerを指定することで、AudioMixerの機能を利用できます。
Untitled-2.png

デモでIntroLoopの挙動を確認

デモプログラムはここで確認できます。購入前に確認してみましょう。

Demo | Introloop

サポートは日本語で大丈夫のようです

作者様はタイの方のようですが、Forumを見たところ日本語でのサポート可能なようです。日本人でも安心してアセットを利用できます。

Introloop - Easily play looping music with intro section - Unity Forum

リンク

関連するリンクのまとめです。

Introloop(AssetStoreへのリンク)

Introloop(ホームページ)

Introloop(フォーラム(日本語可能))

最後に

とても便利なので、Unityでお手軽にイントロ付きループをしたい人は是非IntroLoopを使いましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

toio と Unity の連携

はじめに

これは「toio™(ロボットトイ | toio(トイオ)) Advent Calendar 2019」の1日目の記事になります。

この記事ではUnityとtoioの連携方法を記します。
以下の記事・サイトを参考にしました。

toio.js とは

toio.js は Node.js を用いたtoio公式のライブラリです。
パソコン側からcoreCubeを動かしたり、マット上の位置を取得したり出来ます。
今回はこれを使ってマット上のcoreCubeにUnity上のCubeを連動させたいと思います。

環境

OS : MacOS High Sierra 10.13.6

下準備

Unity

Unity Hub のインストール

Unity Hub を入れます。
こちらUnityHubをダウンロードからインストーラをダウンロードできます。

unity hubを起動してインストールで最新バージョンのUnityを入れます。
このとき、Visual Studioも一緒にインストールします。
スクリーンショット 2019-11-26 15.04.54.png

UniRx

Unity Hub で新規プロジェクトを作成します。
スクリーンショット 2019-11-26 14.48.17.png

プロジェクトが開いたらAssetストアで UniRx をダウンロード、インポートします。
すると、Assetsフォルダ下にPluginsフォルダができ、その中にUniRxが入ります。
スクリーンショット 2019-11-26 15.31.22.png

C# websocketライブラリ

こちらからライブラリをダウンロードして解凍します。
スクリーンショット 2019-11-28 21.31.12.png

中にある websocket-sharp.csproj をVisualStudioで開きビルドすると bin/Debug 下に websocket-sharp.dll が出来ます。
スクリーンショット 2019-11-28 21.30.09.png

この websocket-sharp.dll を先ほど作成したプロジェクトの Assets/Plugins に入れます。
スクリーンショット 2019-11-26 15.51.16のコピー.png

これでUnity側の下準備は完了です。

toio.js

brew install yarn

yarn に関しては公式では npm で入れていますが、

npm install -g yarn

私は以下のように brew を使いました。

brew install yarn 

権限が必要だったり入れ難かった覚えがありましたが、なんかと入れたようです。
良くないことをしたかも知れません。

toio.js

次に toio の github から toio.js を clone します。
公式曰く、以下のコマンドでパッケージのbuildまで済みます。
yarn example:hogehoge でサンプルプログラムが動きます。

git clone https://github.com/toio/toio.js.git
cd toio.js
yarn install
yarn build
yarn example:keyboard-control

coreCubeの電源を入れて接続され方向キーで動いたらオッケーです。
僕は接続されなかったのでパソコンを再起動したら動きました。

実装

Unity側

SceneにCreateから3D Object/Cubeを置きます。
またCreateからUI/Buttonを置いておきます。

GameViewでみるとこんな感じになると思います。
スクリーンショット 2019-11-28 21.10.24.png

Cube に Add Component/NewScript でPositionSyncというスクリプトをつけます。
以下、@nmxi さんの記事*から拝借したコードを改変して書いた中身です。

PositionSync.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using WebSocketSharp;
using UniRx;

public class PositionSync : MonoBehaviour
{

    [SerializeField] private string _serverAddress;
    [SerializeField] private int _port;

    [SerializeField] private SyncPhase _nowPhase;

    private GameObject tA;
    private WebSocket ws;
    string message = "";
    string messageA = "";

    public float span = 0.5f;

    public enum SyncPhase
    {
        Idling,
        Syncing
    }

    private void Awake()
    {
        tA = GameObject.Find("Cube");
        _nowPhase = SyncPhase.Idling;

    }

    void Update()
    {
        string[] m = message.Split(',');

        switch (m[0])
        {
            case "A":

                if (message != messageA)
                {
                    ////サイズの変更
                    //マット
                    //559mm 410points 
                    //toioコアキューブ
                    //31.8mm about 23.3point

                    tA.transform.position = new Vector3(-(float.Parse(m[2]) - 250.0f) / 10.0f, tA.transform.position.y, -(float.Parse(m[1]) - 250.0f) / 10.0f);
                    tA.transform.rotation = Quaternion.Euler(0, float.Parse(m[3]), 0);
                }
                messageA = message;
                //Debug.Log(m);
                break;
        }


    }
    /// <summary>
    /// Get Down Start Sync Button
    /// </summary>
    public void OnSyncStartButtonDown()
    {
        var ca = "ws://" + _serverAddress + ":" + _port.ToString();
        Debug.Log("Connect to " + ca);
        ws = new WebSocket(ca);

        //Add Events
        //On catch message event
        ws.OnMessage += (object sender, MessageEventArgs e) => {
            message = e.Data;

        };

        //On error event
        ws.OnError += (sender, e) => {
            Debug.Log("WebSocket Error Message: " + e.Message);
            _nowPhase = SyncPhase.Idling;
        };

        //On WebSocket close event
        ws.OnClose += (sender, e) => {
            Debug.Log("Disconnected Server");
        };

        ws.Connect();

        _nowPhase = SyncPhase.Syncing;
    }

    public void OnChangedTargetTransformValue(Vector3 pos)
    {
        if (_nowPhase == SyncPhase.Syncing)
        {
            //ws.Send(pos.ToString());
            //ws.Send("1");
        }
    }
}

Cube にある PositionSync (Script)の欄に
Server Address には "localhost"、Port には "8080"を入れて置きます。
スクリーンショット 2019-11-28 21.05.17.png

先ほど置いたButtonのOn Click()に Cube/PositionSync/OnSyncStartButtonDown() を追加します。
スクリーンショット 2019-11-28 21.12.27.png

toio.js側

toio.js/projectsフォルダを作成し、その中にスクリプトを置きます。
今回はtoio公式のサンプルと@nmxi さんの記事*から拝借したコードを悪魔合体して以下のスクリプトを生成しました。

マット上におけるcoreCubeの絶対位置をUnityに送るプログラムです。

toio_node.js
const { NearestScanner } = require('@toio/scanner')

var WebSocketServer = require('ws').Server

var wss = new WebSocketServer({
    port: 8080
});

var cube;

async function main() {
  // start a scanner to find nearest cube
  cube = await new NearestScanner().start()

  // connect to the cube
  await cube.connect()
}

main()

wss.on('connection', function(ws) {

    //position-idに変化があった時
    //移動、回転
    //toioPositionを更新する
    cube.on('id:position-id', data => {
        ws.send("A,"+data.x+","+data.y+","+data.angle)

    })
    //マットから離れた時
    cube.on('id:position-id-missed', () => {
      // ws.send('Position Miss!');
    })
});

実行

1.coreCube の電源を入れます。

2.toio_node.js を実行します。(少しして coreCube から音がします。)

 cd projects
 node toio_node.js

3.Unity のプロジェクトを Run します。

4.GameView 上で Button をクリックします。

この状態でマットに置いた coreCube の位置が Unity の Cube に反映されれば成功です。

こんな感じ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity]冬のアドカレ2019 破壊系アセットGO Shatter Toolkitについて

この記事はUnityアセット冬のアドベントカレンダー 2019 Winter!の12月21日の記事になります。

GO Shatter Toolkitとは?

オブジェクトの破壊表現を簡単にしてくれアセットです。
最終リリースは2015年ですがUnity2019.2.3でも問題なく動作しました。

できること

qiita1.gif
オブジェクトをぶつけてオブジェクトを破壊。
破壊された破片オブジェクト同士がぶつかり、破壊されることもあります。

qiita2.gif
切断面のテクスチャをしているすことも可能。

基本的な使い方

キャプチャ.PNG

破壊したいオブジェクトにRigidbody、MeshCollider(Convexにチェック)、ShatterTool、WorldUvMapper、ShatterOnCollisionをアタッチする。

それぞれの機能は以下の通り(書いてないのは分からなかったやつです)

ShatterTool

破壊を制御するメインのスクリプト。

GenerationLimit

破壊された破片がさらに破壊される回数を指定できます。

Cuts

破壊された破片数を指定できます。

FillCut

切断面にメッシュを張るか指定できます。基本オンにしておいていいと思います。

WorldUvMapper

切断面にテクスチャを張るスクリプト。

Scale

テクスチャの大きさを指定します。

ShatterOnCollision

何かがぶつかったときに破壊するためのスクリプト。

RequiredVelocity

どれくらいの勢いでぶつかったら破壊するか。

CooldownTime

破壊した後何秒間、破壊を待機するか。

切断面のテクスチャを変える

11.PNG
先ほどのWorldUvMapperをTargetUvMapperに変更し、スタート位置と大きさを設定します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityからkintoneアプリのレコードを承認する方法

はじめに

この記事では、kintoneアプリ内で設定したプロセス管理をUnity内から操作する方法を案内します。実現方法に注力したいため、『Unityのプレイヤーがスペースキーを押したら、特定のレコードが承認される』というシンプルなシナリオにします。
shounin.png

なお、例ではJSONの作成をしやすくするためにSimpleJSONを使用しています。プロジェクト内で利用する方法は下記の記事を参考にしてください:
- UnityからkintoneのREST APIを叩く方法

kintoneアプリの準備

プロセス管理を設定したアプリを作りましょう。
kintone環境を持っていない方はcybozu developer networkのこのページから1年間無料で使用できる開発者ライセンスのkintone環境を手に入れてください。

フィールドの設定

好みのフィールドを設定してください

プロセス管理の設定

アプリの設定画面から、設定タブ→プロセス管理 に遷移するとプロセス管理の設定を有効に出来ます。
この記事の例では『《特定のユーザ》が作業者として設定されたレコードを《承認》というアクションでプロセス管理のステータスを《承認済》に進める』というのをREST APIで実行します。REST APIを実行する際に、この《特定のユーザ》でパスワード認証を行います。
下記のようにプロセス管理の設定をしましょう。
Screen Shot 2019-11-27 at 21.41.30.png

設定が終わったら保存をし、アプリを公開/更新しましょう。

スクリプトの準備

サンプルコードとしてシンプルに見せたいため、特定のアプリの特定のレコードに対してプロセスを進めるような内容にします。
下記のサンプルコードの{サブドメイン名}{Base64エンコードされた『ユーザ名:パスワード』}{アプリID}{レコードID}は適宜自分の環境に合うように変更してください。kintoneのREST APIの認証についてはcybozu developer network のこちらのページから詳細を確認することが出来ます。

testAPI.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using SimpleJSON;
using System.Text;

public class testAPI : MonoBehaviour
{
    const string domain = "{サブドメイン名}.cybozu.com";
    const string passwordauth = "{Base64エンコードされた『ユーザ名:パスワード』}";

    void Start()
    {

    }

    void Update()
    {
        if (Input.GetKeyDown("space"))
        {
            print("space key was pressed");
            int WorkflowappID = {アプリID};
            int workflowRecordID = {レコードID};
            StartCoroutine(updateRecordStatus(WorkflowappID, workflowRecordID, "承認"));
        }
    }

    private IEnumerator updateRecordStatus(int appID, int recordID, string action)
    {
        //APIエンドポイントの作成
        string RequestURL = "https://" + domain + "/k/v1/record/status.json";

        //ボディで送るJSONを作る → {"action":"承認","app":15,"id":1}
        JSONObject APIrequestBody = new JSONObject();
        APIrequestBody.Add("action", action);
        APIrequestBody.Add("app", appID);
        APIrequestBody.Add("id", recordID);

        //APIの実行前の準備
        UnityWebRequest request = new UnityWebRequest(RequestURL, "PUT");
        byte[] putData = Encoding.UTF8.GetBytes(APIrequestBody.ToString());
        request.uploadHandler = (UploadHandler)new UploadHandlerRaw(putData);
        request.SetRequestHeader("X-Cybozu-Authorization", passwordauth);
        request.SetRequestHeader("Content-Type", "application/json");

        //APIを実行
        yield return request.SendWebRequest();
    }
}

使用したkintone REST APIのドキュメントはこちらから確認出来ます:
- レコードのステータスの更新

実行結果

kintoneアプリに新しいレコードを追加して、手動でステータスを《承認待ち》進めます。
作業者として選択するのは、Unityのスクリプト内からパスワード認証を行うユーザです。
proceedstatus.gif

Unityのゲーム内でスペースキーを押します。
unityscreenshot.png

kintoneアプリのレコードの最新情報を見るために、ブラウザをリフレッシュしましょう。
ステータスが《承認済》になっているはずです。履歴タブをクリックすれば、どのユーザがいつステータスを進めたかがわかります。
approve_success.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#),Python】API通信勉強メモ③簡易版ログイン機能の実装

今回やること

Unity側から入力した情報を登録 & ログインする機能を作ります。
前回同様、Flaskでローカルにアプリケーションサーバーを立てて利用します。

【前回】:【Unity(C#),Python】API通信勉強メモ②Flaskでローカルサーバー立ち上げ

なんもわからんなりの解釈が山盛りなのでマサカリ、オールオッケーです。
特にセキュリティ面に関してはエンジニアと名乗るのが恥ずかしいくらい疎いので
超巨大マサカリで一刀両断してもらってもしっかりと受け止めます。

実際に作成したもの

GetHIKAKIN.gif

ID、パスワードを入力してのアカウント登録が行えて、
ログイン画面で実際にログインっぽいことが可能です。

行っていることのイメージです。

ログインイメージ.PNG

DBに情報が保存されているので、Editorを閉じてもアカウント情報は消えません。(たぶん)

Unity側

Unity側が行う処理としては入力した情報をローカルサーバーに送って、
レスポンスに応じてテキストを表示するだけです。

登録ボタンに関する処理
using System.Collections;
using UnityEngine.Networking;
using UnityEngine;
using System.Text;
using UnityEngine.UI;

public class RegistraionHTTPPost : MonoBehaviour {

    [SerializeField, Header("LogText")]
    Text m_logText;

    [SerializeField, Header("IDInputField")]
    InputField m_idInputField;

    [SerializeField, Header("PassInputField")]
    InputField m_passInputField;

    //接続するURL
    private const string RegistrationURL = "http://localhost:5000/registration";

    //ゲームオブジェクトUI > ButtonのInspector > On Click()から呼び出すメソッド
    public void Registration()
    {
        StartCoroutine(RegistrationCoroutine(RegistrationURL));
    }

    IEnumerator RegistrationCoroutine(string url)
    {
        //POSTする情報
        WWWForm form = new WWWForm();
        form.AddField("user_id", m_idInputField.text, Encoding.UTF8);
        form.AddField("password", m_passInputField.text, Encoding.UTF8);

        //URLをPOSTで用意
        UnityWebRequest webRequest = UnityWebRequest.Post(url, form);
        //UnityWebRequestにバッファをセット
        webRequest.downloadHandler = new DownloadHandlerBuffer();
        //URLに接続して結果が戻ってくるまで待機
        yield return webRequest.SendWebRequest();

        //エラーが出ていないかチェック
        if (webRequest.isNetworkError)
        {
            //通信失敗
            Debug.Log(webRequest.error);
            m_logText.text = "通信エラー";
        }
        else
        {
            //通信成功
            Debug.Log("Post"+" : "+webRequest.downloadHandler.text);
            m_logText.text = webRequest.downloadHandler.text;
        }
    }
}

ローカルサーバーに対して情報を送る処理は下記箇所が担っています。
ローカルサーバー側が受け取る情報として
formuser_idpasswordなどをリクエスト情報として追加しています。

リクエスト時に送る情報
    //POSTする情報
    WWWForm form = new WWWForm();
    form.AddField("user_id", m_idInputField.text, Encoding.UTF8);
    form.AddField("password", m_passInputField.text, Encoding.UTF8);

詳細に理解できてはいませんが、
formというのはリクエストの種類(POST,GETなど)に加えて、何かしらの情報を渡せるもののようです。
WWWFormはPOST専用のクラスです。

ローカルのアプリケーションサーバー(Flask)

こっちは本当に難しくて、
そもそも私は何をやればいいんだろうという状態が長く続いてしんどかったです。

まずはアカウント情報を登録する上でDB(データベース)というものを利用する必要があるとわかりました。

DBって何?

データベース(英: database, DB)とは、検索や蓄積が容易にできるよう整理された情報の集まり。 通常はコンピュータによって実現されたものを指すが、紙の住所録などをデータベースと呼ぶ場合もある。コンピュータを使用したデータベース・システムでは、データベース管理用のソフトウェアであるデータベース管理システムを使用する場合も多い。

【引用元】:ウィキペディア(Wikipedia)

データベースってのはソフトウェアのことらしいです。
そのデータはどこにあってどういう仕組みで成り立っているのか完全に理解するために深堀りすると、
帰ってこられなくなるって偉い人が言ってたので深くは考えません。
【参考リンク】:そもそもデータベースって何で出来ていて、どこの何にどう保存されるのでしょうか。。

DBにもいろいろと種類があって、今回利用するのはRDB(リレーショナルデータベース)っぽいです。

SQLAlchemy

データベースを実際に操作するにはSQLという言語を用いるのですが、それをPython内からやってくれる、というライブラリ

【引用元】:はじめての Flask #4 ~データベースをSQLAlchemyでいじってみよう~

だそうです。便利ですね~。今回はこちらを使います。

実装

いよいよFlask及びDBの実装です。

import hashlib

from flask import *

from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session

app = Flask(__name__)

engine = create_engine('sqlite:///user.db')
Base = declarative_base()


# DBの設定
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True, unique=True)
    user_id = Column(String)
    password = Column(String)


Base.metadata.create_all(engine)
SessionMaker = sessionmaker(bind=engine)
session = scoped_session(SessionMaker)


# DBにIDとパスワード登録する
@app.route("/registration", methods=["POST"])
def registration():

    user = request.form["user_id"].strip()
    check_users = session.query(User).filter(User.user_id == user).all()

    if check_users:
        return "そのユーザー名は使用済みです"
    else:
        user = User(user_id=request.form["user_id"], password=str(hashlib.sha256(
            request.form["password"].strip().encode("utf-8")).digest()))
        session.add(user)
        session.commit()
        return str(user.user_id.strip() + "様\nご登録ありがとうございます")

# ログインできるID、パスワードの組合わせかどうかDBを見て照合
@app.route("/login", methods=["POST"])
def login_check():

    user = request.form["user_id"].strip()
    check_users = session.query(User).filter(User.user_id == user).all()

    try:
        for login_user in check_users:
            login_user_pass = login_user.password

        if login_user_pass == str(hashlib.sha256(
                request.form["password"].strip().encode("utf-8")).digest()):
            return "ログイン完了です"
        else:
            return "パスワードが異なります"
    except:
        return "登録情報が異なります"


if __name__ == "__main__":
    app.run(debug=True)
    # User.__table__.drop(engine)  # テーブル削除用

テーブルの消し方

下記箇所のコメントアウトを解除して動かせば消えます。

  User.__table__.drop(engine)  # テーブル削除用

Pylintと仲良くする

VSCでpyhtonを書いているのですが、FlaskがPylintと仲良くしてくれませんでした。

そのため、Setting.jsonを開いて下記設定を追記しました。

"python.linting.pylintArgs": [
        "--load-plugins",
        "pylint_flask"
    ],

ハッシュ化

今回、ハッシュ化してセキュリティ対策もばっちりだぜ!ってのをやってみたかったんですが、
現状、②の箇所しかできていないので全く意味がないような気がしてます。
POSTを使うだけではセキュリティ不十分だよ~って記事がいっぱい出てくるので
やりとりする情報は全てハッシュ化しないとダメなのかな~と勝手に思ってます。
この辺り、詳しく知ってる方いたら教えてください。

ログインイメージ.PNG

Basic認証とDigest認証

セキュリティうんぬんを調べている際に知りました。
認証にも種類があるそうです。

Digest認証はセキュリティの観点でBasic認証より優れています。しかし、すべての環境に対応しているわけではありません。ページを利用するユーザーの環境がある程度分かっていて、対応しているブラウザを使っている場合には問題はありません。しかし、不特定多数のユーザーに向けたページで設定をする場合、Digest認証は向いていません。

一方Basic認証はセキュリティ面でDigest認証に劣っています。しかし、あらかじめセキュリティ対策が行われている環境下、例えばSSLやローカルネットワーク内などで利用する分には特に問題はないでしょう。ユーザーの環境にも左右されません。

このように、不特定多数のユーザーが使うページにユーザー認証を設定する場合はSSLと合わせたBasic認証、管理者など接続する環境が特定されている場合にはDigest認証、と状況によって使い分けるのが一般的です。

【引用元】:Basic認証(基本認証)とDigest認証、それぞれの役割と違いについて

今回実装したものはBasic認証と呼ばれるものに該当するのでしょうか。
よくわかりませんので、"お前が作ったのはどちらでもない"とかでいいので知りたいです。

参考リンク

【PythonのORM】SQLAlchemyで基本的なSQLクエリまとめ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Commonクラスを自動で生成する仕組みを作ると人生が楽になる【Unity】

UnityでC#スクリプトを生成した後毎回デフォルトで書かれているコードを決まったネームスペースやregionなど、チームのルールに沿って書き直す経験はありませんか。毎回同じコードを書くのは手間ですし、うっかりルールを守れていない状態で処理を書いていたなんてこともありますよね。

この問題は自分でテンプレートをカスタマイズする事で解決する事ができます。

1. UnityEditorをダウンロードしたパスからScriptTemplatesを探す

キャプチャ.PNG

2. 81-C# Script-NewBehaviourScript.cs.txt を好みで書き換える

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

public class #SCRIPTNAME# : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #NOTRIM#
    }

    // Update is called once per frame
    void Update()
    {
        #NOTRIM#
    }
}

あとはUnityでスクリプト生成すると
上記で書き換えた通りにコードが書き換えられていると思います。

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

namespace Common
{
    /// <summary>
    /// 
    /// </summary>
    public class NewBehaviourScript : MonoBehaviour
    {
        #region 定数

        #endregion

        #region 変数

        #endregion

        #region プロパティ

        #endregion

        #region ライフサイクル

        void Awake()
        {

        }

        void Start()
        {

        }

        void Update()
        {

        }

        void LateUpdate()
        {

        }

        #endregion

    }
}

おわりに

書き換えるだけでなくテンプレートを追加することもできます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

unityで物を投げる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む