gologiusの巣

プログラミングなどの技術メモです。誰かの役に立てるとうれしいです。

Akeytsu IKの使用方法メモ

Akeytsuの使用方法メモです.日本語の情報が少ないので参考になれば幸いです. 使い始めてからまだ日が浅いので間違っていたらコメントお願いします.

事前設定

  • 左下が骨のアイコン(rigging mode)になっていること
  • 左上「CharaBank」が「Bind Pose」になっていること

IKの設定

Ctrlキーを押しながら,ボーンを二つ選択.選択すると,下の画像の赤枠内が黄色に光る. f:id:gologius:20170722110151p:plain

光っているボタンを押すと,IKボーンが追加される. f:id:gologius:20170722110300p:plain

モーションを作る

左下のボタンのボタンでモード切り替えができる. f:id:gologius:20170722110349p:plain

ここからがポイントなのですが,IKは元あったモーションには適用することができず,新しく作ったモーションから適用することができるみたいです. 下の画像で説明します. Runというモーションを新しく作ったとします.設定したIKはこのモーションでは使用することができます. しかし,元あったStandなどのモーションでは使用することができませんf:id:gologius:20170722110519p:plain

IK自体が使用できないのではなく,モーションを作成した時点で設定されているIKボーンしか使用できない,ということです. MMD使ったことないのでわかりませんが常識なのかな...?

Androidアプリ開発でToolbar(一番上のバー)の設定

f:id:gologius:20170708075209p:plain

一番上のバー(Toolbar)を編集しようと思って,どこをいじればいいのかわからなかったのでメモ.

開発環境(何を書けば...)

  • min sdk version 21
  • Compile sdk version : API26 : Android8.0
  • build tools version : 26.0
  • ActivityはMainActivity一つ

前提

  • ActivityはMainActivity一つ
  • アプリのテーマをxxxxx.NoActionbarにしている
  • デザイナなりxml直打ちなりでToolbarを挿入している
  • MainActivityのonCreate内に以下のような記述がある
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); //R.id.toolbarは各自で設定したidを入れる
setSupportActionBar(toolbar);

本題

MainActivity内に以下の関数を追加.これによりToolbar内によくみるアイコン付きボタンが表示される準備ができる.

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

次に,xmlファイルを作成する. 先ほどのmenu_mainxmlファイルの名前と(おそらく)同じ

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.gologius.infoclip.MainActivity">
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        android:visible="true"
        app:showAsAction="never"
        tools:title="設定" />
    <item
        android:id="@+id/action_about"
        android:title="このアプリについて"
        android:orderInCategory="200"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="search"
        app:showAsAction="always" />

    <item
        android:id="@+id/action_add"
        android:icon="@android:drawable/ic_menu_add"
        android:title="add"
        app:showAsAction="always" />
</menu>

・・・(縦)のアイコンには,app:showAsAction="never"にしたものが入る. なので,app:showAsAction="never"が一つもなければ・・・(縦)アイコンは表示されない.

たぶんこの解釈であっているはず.

Unity一週間ゲームジャム テーマ「積む」に参加しました

概要

ゲームジャムに参加しました。期間とテーマが決められて、指定の場所にアップロードするだけのお手軽ゲームジャムです。 特に順位付けもありません。

Unity 1週間ゲームジャム | ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

参加理由

就職したところで、思いのほか情報系の技術に触れない、情報系の同期もいなくて・・・みたいな理由(説明難しい)。 単純に研修の時期なので仕方ない面はありますが・・・(けどPCすら触れないのはどうなの

とりあえずメインで使うものを決める

テーマ「積む」から連想するものを探します。

・・・土のうが思い浮かびました。 最初の印象を大事にしたいのでこれでいくことに。

土のうの3Dモデルなんかないし作るか~とか思いつつ一応探したらあった。 で、とりあえず位置決めと設置を実装したのが以下の動画

ゲームとして成り立たせる

土のうといえば水などの浸水を防ぐものです。 「防く」ものです。 水を防ぐ、のはビジュアル的にどうやるのがいいか思い浮かばなかったので、弾を防ぐことにしました。

これブロックくずしじゃ( ^ω^)・・・

防ぐだけでは微妙な気がしたので、敵と弾を増やして、エフェクトもつけて綺麗な感じになるようにしました。

で、あとはTopとかゲームクリア画面とか作って完成。

www.youtube.com

技術的な話

正直特に難しいことはしてません。ソースも公開したいと思ってる(思ってるだけでGithubにUPし忘れる) ので、見たら大したことしてないなーとしか思わないかと。 ただ、WebGL用にビルドするのも初めてだったので、日本語が表示されない問題で躓きました。

qiita.com

弾の反射はスクリプト書くよりも、Physical Material割り当てる方が楽だし確実っぽい。

あと、シーン切り替え時に画面が暗くなる問題が発生した。 古いバーションの解決策はあったけど、新しいバージョンはあんまりなかった。 結果的に以下の赤枠のAuto Generationのチェックを外してGenerate Lightingボタンを押して事前にデータを作っておくことで対応した。 .sceneと同じ場所にフォルダが出力されるけど、消したらダメ

f:id:gologius:20170625091236p:plain

反省と今後に向けて

  • 毎回同じ機能実装、作業をしている気がするので、テンプレートを作っときたい
    • 次回にも生かせる
  • クリア画面でスコアを出力していない
    • ごめんなさい。そのうち直すか
  • AIがバカ
    • 自分の陣地内に留まってない。
  • ゲームとして面白いかが微妙
    • 運ゲー化してる。敵を倒す爽快感みたいなのはない
  • ロゴ、サムネがダサい
    • デザイン力の問題
  • 素材の問題
    • 拾ってくるとどうしてもかぶってしまう(オリジナリティの低下)
    • 実際BGMがかぶっていた
    • 凄そうに見せるにはビジュアルけっこう大事。自分で絵かける人とか強い
  • UI
    • 動かしたりとかしたい。ゲームジャムでそこに力をいれるのは時間的にきついかもしれないが
    • 要勉強

感想

Twitter上だけですが、みんながいろいろ作ってて、一体感みたいなのが楽しかったです。 発想力がすごい人がいっぱいいました。すごい

Unityでオブジェクトのマテリアルを変更する話

Unityで動的にマテリアルを変更したい、的なことがしたい場合

GameObject obj = xxxxxx; //適当な読み込み
Material mtl = yyyy; //適当な読み込み

obj.GetComponent<Renderer>().material = mtl;

のようにするのですが、僕は勝手に

obj.GetComponent<Renderer>().material = mtl;

obj.GetComponent<Renderer>().materials[0] = mtl;

が同じ振る舞いをするものだと思っていました。

どうも違うみたいで、前者だと意図したふるまいになるのですが、後者の場合、以下の画像のようにDefault Materialが割り当てられてしまうみたいです。

f:id:gologius:20170527183941p:plain (MeshRendererの部分です)

どう違うのかはまた調査します

メタセコイア ロボットのようなものにボーンを入れる

メタセコイアでボーンを入れてモデルを動かす際に,人なら不自然にならないように変形してほしい場合がほとんどです.

しかし,ロボットや機械などの無機物の場合には,変形してほしくない場合はどうすればよいのでしょうか.

つまり,一つのオブジェクトに一つのボーンを適用したい,一つのオブジェクトに二つ以上のボーンの影響を与えたくない場合です.

需要は非常に多いはずなのに,Webに全然それらしきことが書いていない(調べ不足かもしれませんが...)

というわけで,自分がやった方法をまとめてみました

今回使用するモデル

f:id:kamiwo_koete:20170321095623p:plain

分り易いように色を変えました.以下の説明はウェイトの色とごっちゃになってわかりづらいので,白で着色してます.

ボーンを入れる

左のコマンドパネルにボーンから.リギングタブでボーンの追加ができます.これは直観的にできるのではないでしょうか.

f:id:kamiwo_koete:20170321101649p:plain

スキン設定

動かしたいすべてのオブジェクトを選択します.

f:id:kamiwo_koete:20170321101754p:plain

スキニング,ボーン影響,正規化はどうでもいいです.変形させる際の設定なので.

スキニング

オブジェクトに各ボーンの影響度(=ウェイト)を設定していきます.肩を例に説明します.

  1. 動かしたいオブジェクトの頂点を選択
    • 例:オブジェクトshoulderの頂点をCtrl+Aなどですべて選択します
  2. 対応するボーンをボーンリストから選択
    • 例:bone1をクリック
  3. スキニング->ペイント->頂点で,全ボーンからのウェイトをクリアをクリック
    • 正規化していたり,余計な操作が入っていると,ウェイトが設定されている場合があるため
  4. スキニング->ペイント->頂点100の部分をクリック f:id:kamiwo_koete:20170321104017p:plain

これらの処理をすべての動かしたいオブジェクト,ボーンに適用します.

例の場合は,選択された頂点(=shoulder)へのbone1の影響度を100%にした,ということです.つまりbone1のみにshoulderは従う,ということです. (ここらへんの説明間違っていたら指摘お願いします.

説明動画と結果

www.youtube.com

もっといい方法あったら教えてください

参考

Metasequoia BBS

Unity ドーナツ(donuts) 描画

kamiwo-koete.hatenablog.jp

前の記事を応用して,ドーナツ型を描画します

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

[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class Sector : MonoBehaviour
{

    public float radius = 10.0f;
    public float holeRadius = 5.0f;
    public float startDegree = 10.0f;
    public float endDegree = 170.0f;
    public int split = 5;

  
    void Start()
    {
        MeshFilter m = this.GetComponent<MeshFilter>();
        m.mesh = createMesh();
    }

    void Update()
    {

    }

    Mesh createMesh()
    {
        if(Mathf.Approximately(holeRadius , 0.0f)){
            return createSector();
        }

        return createDonuts();
    }

    Mesh createSector()
    {
        Mesh mesh = new Mesh();

        //頂点座標計算
        Vector3[] vertices = new Vector3[2 + split];
        Vector2[] uv = new Vector2[2 + split];

        vertices[0] = new Vector3(0f, 0f, 0f);
        uv[0] = new Vector2(0.5f, 0.5f);

        float deltaRad = Mathf.Deg2Rad * ((endDegree - startDegree) / (float)split);
        for (int i = 1; i < 2 + split; i++)
        {
            float x = Mathf.Cos(deltaRad * (i - 1) + (Mathf.Deg2Rad * startDegree));
            float y = Mathf.Sin(deltaRad * (i - 1) + (Mathf.Deg2Rad * startDegree));
            vertices[i] = new Vector3(
                x * radius,
                y * radius,
                0.0f);

            uv[i] = new Vector2(x * 0.5f + 0.5f, y * 0.5f + 0.5f);
        }
        mesh.vertices = vertices;
        mesh.uv = uv;

        //三角形を構成する頂点のindexを,順に設定していく
        int[] triangles = new int[3 * split];
        for (int i = 0; i < split; i++)
        {
            triangles[(i * 3)] = 0;
            triangles[(i * 3) + 1] = i + 1;
            triangles[(i * 3) + 2] = i + 2;
        }
        mesh.triangles = triangles;

        return mesh;
    }

    Mesh createDonuts()
    {
        Mesh mesh = new Mesh();

        Vector3[] vertices = new Vector3[2 + 2 * split];
        Vector2[] uv = new Vector2[2 + 2 * split];


        //頂点座標計算
        float deltaRad = Mathf.Deg2Rad * ((endDegree - startDegree) / (float)split);
        int indexOffset = vertices.Length / 2;
        for (int i = 0; i <vertices.Length/2; i++)
        {
            float x = Mathf.Cos(deltaRad * (i - 1) + (Mathf.Deg2Rad * startDegree));
            float y = Mathf.Sin(deltaRad * (i - 1) + (Mathf.Deg2Rad * startDegree));
            //外側
            vertices[i] = new Vector3(
                x * radius,
                y * radius,
                0.0f);
            //内側
            vertices[i + indexOffset] = new Vector3(
                x * holeRadius,
                y * holeRadius,
                0.0f);


            uv[i] = new Vector2(x * 0.5f + 0.5f, y * 0.5f + 0.5f);
            uv[i + indexOffset] = new Vector2(x * 0.5f * (holeRadius / radius) + 0.5f, y * 0.5f * (holeRadius / radius) + 0.5f);
        }
        mesh.vertices = vertices;
        mesh.uv = uv;

        //三角形を構成する頂点のindexを,順に設定していく
        int[] triangles = new int[6 * split];
        for (int i = 0; i < split; i++)
        {
            triangles[(i * 6) + 0] = i;
            triangles[(i * 6) + 1] = i + 1;
            triangles[(i * 6) + 2] = (i + indexOffset) + 1;

            triangles[(i * 6) + 3] = i;
            triangles[(i * 6) + 4] = (i + indexOffset) + 1;
            triangles[(i * 6) + 5] = (i + indexOffset);

        }
        mesh.triangles = triangles;

        return mesh;
    }
}

メインはcreateDonuts()のほうです. createSector()の方は前回と変わりません.

内径holeRadiusを0にすると,通常の扇形を描画します. 別に描画結果は変わりませんが,頂点数と面数が変わるので,計算コストが軽くなります.

結果

f:id:kamiwo_koete:20170319102524p:plain

Unity 扇型 描画

扇形を描画します.

ちなみにUIのゲージ等に利用したい場合は,UIのImageコンポーネント

  • ImageType -> Filled
  • Fill Meshod -> Radial 360

を利用したほうが楽です.

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

[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class Sector : MonoBehaviour
{

    public float radius = 10.0f;
    public float startDegree = 10.0f;
    public float endDegree = 170.0f;
    public int triangleNum = 5;

    void Start()
    {
        MeshFilter m = this.GetComponent<MeshFilter>();
        m.mesh = createMesh();
    }

    void Update()
    {

    }

    Mesh createMesh()
    {
        Mesh mesh = new Mesh();

        //頂点座標計算
        Vector3[] vertices = new Vector3[2 + triangleNum];
        Vector2[] uv = new Vector2[2 + triangleNum];

        vertices[0] = new Vector3(0f, 0f, 0f);
        uv[0] = new Vector2(0.5f, 0.5f);

        float deltaRad = Mathf.Deg2Rad * ((endDegree - startDegree) / (float)triangleNum);
        for (int i = 1; i < 2 + triangleNum; i++)
        {
            float x = Mathf.Cos(deltaRad * (i - 1) + (Mathf.Deg2Rad * startDegree));
            float y = Mathf.Sin(deltaRad * (i - 1) + (Mathf.Deg2Rad * startDegree));
            vertices[i] = new Vector3(
                x * radius,
                y * radius,
                0.0f);

            uv[i] = new Vector2(x * 0.5f + 0.5f, y * 0.5f + 0.5f);
        }
        mesh.vertices = vertices;
        mesh.uv = uv;

        //三角形を構成する頂点のindexを,順に設定していく
        int[] triangles = new int[3 * triangleNum];
        for (int i = 0; i < triangleNum; i++)
        {
            triangles[(i * 3)] = 0;
            triangles[(i * 3) + 1] = i + 1;
            triangles[(i * 3) + 2] = i + 2;
        }
        mesh.triangles = triangles;

        return mesh;
    }
}

UVの設定までしないとテクスチャが表示されません.

使い方は適当な空のGameObjectにこのスクリプトを追加するだけです.

実行結果は以下の通り. あと,マテリアルのシェーダーをSprites/Defaultにしておかないとテクスチャが表示されなかったので注意. f:id:kamiwo_koete:20170313004403p:plain

参考

http://www.itdadao.com/articles/c15a1049295p0.html

nanmo.hateblo.jp