「Unity」カテゴリーアーカイブ

Maya->Unity2019(2)

スクリプトを作成する

 

  1. キャラクタを操作するスクリプトを作成します
  2. アセット内で右クリック>Create>C# Scriptを選択
  3. ファイル名は chair にする
  4. 作成されたスクリプトを開く(Visual Studioなどが開く)
  5. 全部を以下に入れ替え,保存する
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class chair : MonoBehaviour
{
    CharacterController characterController;

    public float speed = 2f;
    public float jumpSpeed = 3f;
    public float gravity = 9.8f;

    private Vector3 moveDirection = Vector3.zero;

    void Start()
    {
        characterController = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (characterController.isGrounded)
        {
            moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
            moveDirection *= speed;

            if (Input.GetKey(KeyCode.Space))
            {
                moveDirection.y = jumpSpeed;
            }

        }
        moveDirection.y -= gravity * Time.deltaTime;
        characterController.Move(moveDirection * Time.deltaTime);
    }
}
  1. 椅子を選び,Add ComponentからCharacter Controllerを探し出し追加する
  2. Character Controllerの設定項目でCollider(衝突用簡易オブジェクト)の大きさを調整し,床面にめり込まないようにする(緑色のカプセルの大きさを調整する)
  3. 先ほど作成したchairのスクリプトも椅子に追加する

つぎへ

Maya->Unity2019(1)

 

以下も参考に

FBX Exporterが見つからないとき−>ここ

2018バージョン(IKを使用している場合)−>ここ

 

Maya→FBXに出力

Mayaで作成したファイルをUnityに読み込むには,FBXへの出力を選択し、FBX形式のファイルで出力し,それをUnity側で読み込みます.

 

今回はFKで作成したアニメーションを書き出します.IKを使った場合は別の方法となりますので,注意してください

  1. 椅子の最上位の階層を選択します
  2. ファイル>選択項目の書き出しのオプション□を選択します
  3. 選択項目の書き出しオプションが表示されるので,ファイルタイプをFBX exportにし,選択項目の書き出しをクリック
  4. 現在のプリセットがAutodesk Media Entertainment になっていることを確認し,ファイル名をつけて保存する
  5. ファイル拡張子が.fbxになっていることを確認する
  6. 保存したファイルをUnityに読み込む
  7. 読み込んだファイルを選択し,InspectorのModelのタブを選択
  8. Scale Factorを100にし,Applyをクリック
  9. つづいてAnimationのタブを選択し,アニメーションが再生されるか確認する
  10. Loop Timeにチェックを入れ,Applyをクリックしておくこと
  11. Planeなどを作成し,その上に椅子を配置してみる
    椅子の木目が消えていますが,次のステップで読み込みます

 

Mayaのテクスチャを書き出す

  1. Mayaに戻り,椅子の座面オブジェクトと,ハイパーシェードの適用したマテリアル両方を選択する
  2. 編集>ファイルテクスチャに変換□を選択
  3. X,Y解像度を512に,ファイルフォーマットをPNGにし,保存して閉じる
  4. これによって作成されたテクスチャ画像は,MayaプロジェクトフォルダのSourceimageフォルダに入っているので,これをUnityに読みこむ
  5. アセット内で右クリック>Create>Materialで,マテリアルを作成
  6. Albedoの隣に読み込んだテクスチャをドロップする
  7. 作成したマテリアルを椅子の座面にアサインする
  8. 椅子の座面が木目になりました

つぎ

unity->Arduino->Unity開発メモ2019

UnitySerianHandloerのUnity2018で使えたやつ

 

SerialHandler.cs

using UnityEngine;
using System.Collections;
using System.IO.Ports;
using System.Threading;

public class SerialHandler : MonoBehaviour
{
    public delegate void SerialDataReceivedEventHandler(string message);
    public event SerialDataReceivedEventHandler OnDataReceived = delegate { };

    //ポート名
    //例
    //Linuxでは/dev/ttyUSB0
    //windowsではCOM1
    //Macでは/dev/tty.usbmodem1421など
    public string portName = "/dev/cu.usbmodem2101";//mac
    public int baudRate = 9600;

    private SerialPort serialPort_;
    private Thread thread_;
    private bool isRunning_ = false;

    private string message_;
    private bool isNewMessageReceived_ = false;

    void Awake()
    {
        Open();
    }

    void Update()
    {
        if (isNewMessageReceived_)
        {
            OnDataReceived(message_);
        }
        isNewMessageReceived_ = false;
    }

    void OnDestroy()
    {
        Close();
    }

    private void Open()
    {
        serialPort_ = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
        //または
        //serialPort_ = new SerialPort(portName, baudRate);
        serialPort_.ReadTimeout = 20;//Add this 2019
        serialPort_.Open();
        serialPort_.NewLine = "\n";//Add this 2019

        isRunning_ = true;

        thread_ = new Thread(Read);
        thread_.Start();
    }

    private void Close()
    {
        //isNewMessageReceived_ = false;
        isRunning_ = false;

        if (thread_ != null && thread_.IsAlive)
        {
            thread_.Join();
        }

        if (serialPort_ != null && serialPort_.IsOpen)
        {
            serialPort_.Close();
            serialPort_.Dispose();
        }
    }

    private void Read()
    {
        while (isRunning_ && serialPort_ != null && serialPort_.IsOpen)
        {
            try
            {
                message_ = serialPort_.ReadLine();
                isNewMessageReceived_ = true;
            }
            catch (System.Exception e)
            {
            //    Debug.LogWarning(e.Message);
            }
        }
    }

    public void Write(string message)
    {
        try
        {
            serialPort_.Write(message);
        }
        catch (System.Exception e)
        {
            Debug.LogWarning(e.Message);
        }
    }
}

 

Unityボタン側スクリプト

Btn.cs

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

public class Btn : MonoBehaviour
{
    //先ほど作成したクラス
    public SerialHandler serialHandler;


  void Start()
    {
        //信号を受信したときに、そのメッセージの処理を行う
        serialHandler.OnDataReceived += OnDataReceived;
    }

    void Updata()
    {
        //文字列を送信
       // serialHandler.Write("hogehoge");
    }

    //受信した信号(message)に対する処理
    void OnDataReceived(string message)
    {
        var data = message.Split(
                new string[] { "\t" }, System.StringSplitOptions.None);
        if (data.Length < 2) return;

        try
        {
         
        }
        catch (System.Exception e)
        {
            Debug.LogWarning(e.Message);
        }
    }



    /////ここから追加します
    /// 
    /// 
    /// 
    ///
    public void sendOn()
    {
        //Arduinoに文字列onを送る
        serialHandler.Write("4");
    }

    public void sendOff()
    {
        //
        serialHandler.Write("5");
    }
    public void ledOn()
    {
        //
        serialHandler.Write("6");
    }

    public void ledOff()
    {
        //
        serialHandler.Write("7");
    }

}

 

Arduino側コード

#include <Servo.h>
const int LED_PIN = 13;
int SERVO_SOCKET = 9;
Servo servo;
String InByte_strings;
int InByte;

void setup() {
 Serial.begin(9600);
 pinMode( LED_PIN, OUTPUT );
servo.attach( SERVO_SOCKET );
}

void loop() {
  
  if(Serial.available()>0){
    InByte_strings=Serial.readStringUntil(';');
    InByte=InByte_strings.toInt();
    Serial.println(InByte);

     switch (InByte){
    case 4:
      servo.write( 90 );
      break;
    case 5:
      servo.write( 180 );
      break;
      case 6:
      digitalWrite(LED_PIN,HIGH);
      break;
      case 7:
      digitalWrite(LED_PIN,LOW);
      break;
  }
}
}

 

 

Oculus Quest開発メモ

Oculus Quest 開発メモ

https://qiita.com/pira/items/1c935f30d5ba6c020333

https://framesynthesis.jp/tech/unity/oculusquest/

https://qiita.com/pira/items/1c935f30d5ba6c020333

 

細かい部分はGoの解説でも網羅できる.

MacにOculus接続時=開発者モードをONにするとつながる

つながった後は開発者モードONでいいらしい

OVRPlugin.aar” is denied.

てエラー出る(ビルドはできるけどapk表示されない)

Reveal in FinderでFinderでそのファイルを見つけ,拡張子を.aarから.bakにする

Oculusを接続したまま,Build & Run する

実行される.

 

Unity Timelineを利用したアニメーション

ピタゴラ装置を作る中で,巨大なピタゴラ装置を作りたくても画面からはみ出たりするかもしれません.そこで,次の方法でカメラアニメーションを入れてみましょう.

TimeLineを追加する

  1. Window>Sequencing>Timelineを選択
  2. MainCameraを選択しながら,Timeline画面に表示されるCreateボタンをクリック
  3. MainCameraのTimelineを保存するか訪ねられるので,Saveで保存する
  4. TimelineのMainCameraトラックを選択し,赤丸のRecordingボタンをクリックする
  5. MainCameraを選択し,PositionやRotationなどを変化させる.キーフレームが打たれる.時間を変更しまたキーフレームを打つなどしアニメーションを作成する
  6. Timelineの再生ボタン(下図A)で動きを確認できる(ただしシミュレーションは働かない)
  7. アニメーションの編集などは,下図Bをクリックするとアニメーションカーブで編集できる
  8. 各キーフレームはベジェカーブで編集できる.またキーフレームを右クリックするとカーブの種類を変更できる.上図はキーフレームの左側を直線(Linear)に変更している
  9. 元に戻すには,Compared Autoを選択する

Unity入門-1_3

Physic Materialを設定します

  1. Assets>Create>Physic Materialを選択
  2. Assetsフォルダ内にPhysic Materialが作成されるので,名称をBounceに変更(名称は何でもいい)
  3. Bounceを選択し,InspectorのBouncinessを0.5に変更
  4. Cubeを選択し,BoxColliderコンポーネントのMaterialに作成したBounceをドロップする
  5. 再生し変化を確認する

Unity入門-1_2

(2019追加)

Rigid Bodyを使ってオブジェクトに重さを与える

 

  1. GameObject>3D Object>Plane で平面を取り出す
  2. GameObject>3D Object>Cube で立方体を取り出す
  3. Cubeを適当な位置に置く
  4. 再生ボタンを押す(変化なし)
  5. Cubeを選択し Component>Physics>Rigid Bodyを選択する
  6. CubeのInspectorを見るとRigid Bodyコンポーネントがアサインされていることがわかる
  7. 再生ボタンを押し変化を確認する
  8. Rigid BodyコンポーネントのMass(重量)の値を変化させ,挙動がどう変わるか確認すること

つづく

 

サンタゲーム用スクリプト

サンタゲームのメインスクリプト.単眼VRで照準に入ったら色を変えたり,スコアを表示したり,残時間を表示するなど.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;


public class scope: MonoBehaviour {

    [Header("クロスヘア(照準)の画像をつけたUIを入れる")]
    public Image aimPointImage;
    [Header("スライダー(補足時間目安)のUIを入れる")]
    public Slider myslider;//UIのスライダー
    float slideValue = 0f;//スライダーの値用の変数
    bool soundBool = false;//音を連続再生されるのを防止するBool
    [Header("何点ゲットしたかを表示する画像用のUI")]
    public Image pointImage;//何点ゲットしたかを表示する画像用のUI
    [Header("上のImageが入っているGameObject")]
    public GameObject imageObj;//上のImageが入っているGameObject

    [Header("10点用画像")]
    public Sprite point10;//Imageに割り当てる画像(スプライト10点用以下同じ)
    [Header("20点用画像")]
    public Sprite point20;
    [Header("50点用画像")]
    public Sprite point50;

    [Header("クロスヘアにロックした時の音")]
    public AudioClip scopesound;//クロスヘアにロックした時の音
    [Header("プレゼントをゲットした音")]
    public AudioClip getsound;//プレゼントをゲットした音
    AudioSource audio;//オーディオソース用
    AudioSource audio2;

    [Header("ポイント表示用UI")]
    public Text pointTxt;//文字変数ポイント用
    [Header("時間表示用UI")]
    public Text timeText;//時間表示用文字
    int mypoint;//ポイント用Int
    [Header("初期残時間")]
    public int mytime;//時間用


    private void Start()
    {
        AudioSource[] audioSources = gameObject.GetComponents<AudioSource>();//Maincameraにアサインされている複数のAudioSourceを取得し配列に入れる

        audio = audioSources[0];//一つ目のオーディオソースの名前をaudioに
        audio2 = audioSources[1];
        imageObj.SetActive(false);//ポイント取得画像パネルを隠す

        mypoint = 0;
        pointTxt.text = mypoint.ToString();//UIの文字を初期化する
        timeText.text = mytime.ToString();//上と同じ
        Invoke("startTimer", 3f);//3秒後にタイマースタート
    }


    void FixedUpdate()
    {

        // Rayを飛ばす
        Ray ray = new Ray(transform.position, transform.forward);

        // outパラメータ用に、Rayのヒット情報を取得するための変数を用意
        RaycastHit hit;


        // Rayのhit情報を取得する

        if (Physics.SphereCast(ray, 0.5f, out hit, 80.0f)){//Rayで球を飛ばす

            // Rayがhitしたオブジェクトのタグ名を取得
            string hitTag = hit.collider.tag;

            // タグの名前がpresentだったら、照準の色が変わる
            if ((hitTag.Equals("present"))){
                //照準を赤に変える
                aimPointImage.color = new Color(1.0f, 0.0f, 0.0f, 1.0f);

                slideValue += 1.5f;//スライドバー用の値をアップさせる
                myslider.value = slideValue;//スライドバーの値をセットする

                if(!soundBool){//連打再生されないようにBoolで飛ばす
                    soundBool = true;
                    audio.PlayOneShot(scopesound, 0.2f);//スコープ用の音を再生する
                }


                //99越えたら消す
                if(slideValue > 99){
                    pointget(hit.collider.gameObject);
                    Destroy(hit.collider.gameObject);
                    soundBool = false;//再び再生できるようにする


                }

            }else{
                // present以外では水色に
                aimPointImage.color = new Color(0.0f, 1.0f, 1.0f, 1.0f);
                slideValue = 0f;//スライド値を0にする
                myslider.value = slideValue;//その値をスライドにセットする
                audio.Stop();//音再生停止
                soundBool = false;
            }

        }else{
            // Rayがヒットしていない場合は水色に
            aimPointImage.color = new Color(0.0f, 1.0f, 1.0f, 1.0f);
            slideValue = 0f;
            myslider.value = slideValue;
            audio.Stop();
            soundBool = false;
        }
    }


    void pointget(GameObject go){
        //音再生
        audio2.PlayOneShot(getsound);
        //ポイント表示
        //InstatiateしたPrefab名で足す点数を変えている
        //と同時にポイント用画像を選定してセットする
  
        if (go.name.Contains("PresentYel"))
        {
            pointImage.sprite = point10;
            mypoint += 10;
        }
        else if (go.name.Contains("PresentBlue"))
        {
            pointImage.sprite = point20;
            mypoint += 20;
        }
        else if (go.name.Contains("PresentRed"))
        {
            pointImage.sprite = point50;
            mypoint += 50;
        }

        PlayerPrefs.SetInt("score", mypoint);//End画面用にPlayerPrefsに得点をセットする
        imageObj.SetActive(true);//得点画面を出す
        Invoke("hidePoint", 1f);//1秒後にポイント画面を隠す
        pointTxt.text = mypoint.ToString();//ポイントを文字列に変更して表示
    }

    void hidePoint(){
        imageObj.SetActive(false);//ポイント画面を隠す
    }


    void startTimer(){
        
        StartCoroutine ("myTimer"); //コルーチンをスタートする
    }


    IEnumerator myTimer()
    {
        while (true)
        {
            mytime--;//初期設定の120秒を減らす

            if(mytime < 10){//10秒未満になったら残り時間を変える
                timeText.color = new Color(1.0f, 0.0f, 0.0f, 1.0f);//文字を赤色に
            }else{
                timeText.color = new Color(1.0f, 1.0f, 1.0f, 1.0f);//文字を白色に
            }

            timeText.text = mytime.ToString();

            yield return new WaitForSeconds(1.0f);//1秒間待つ


            //終了処理
            if(mytime < 1){
                Invoke("showScore", 2f);
                yield break;
                //終了処理へ

            }


        }
    }

    //やめるボタン用
    public void goHomeBtn(){
        SceneManager.LoadScene("op");
    }

    //タイムアップ処理
    void showScore(){
        //スコア表示画面へ
        SceneManager.LoadScene("end");
    }
}

スクリプトの使い方です.説明文を入れていますので参考に.

スクリプトに説明文を入れています

単眼VR用スクリプト

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

public class gyroCam : MonoBehaviour {

	// Use this for initialization
	void Start () {
		Input.gyro.enabled = true;
	}
	
	// 横位置用
	void Update () {
		transform.rotation = Quaternion.AngleAxis(90.0f,Vector3.right)*Input.gyro.attitude*Quaternion.AngleAxis(180.0f,Vector3.forward);
	}
}

スマートホンのジャイロに応じてカメラが移動します.Androidはジャイロが搭載されていない機種も多いので使えないこともあります.

動作例

ゲームオブジェクトを巡回させる(AI無し)

スクリプトがアサインされたゲームオブジェクトを毎回決まったルートを巡回させます.

下のスクリプトをPatrol.csとして保存しUnityに読み込みます.

using UnityEngine;
using System.Collections;

public class Patrol : MonoBehaviour
{

    [SerializeField, TooltipAttribute("経由地点の数を入力し,シーン上に配置した空のオブジェクトをアサインします")]
    public Transform[] wayPoints;

    public Transform target;
    public float speed;

    public int currentRoot;


    void Update()
    {

        //配列に入れたTransformを順に巡る.AIを使っていればスムーズに曲がるがこれは鋭角に曲がる

        float step = speed * Time.deltaTime;
        transform.position = Vector3.MoveTowards(transform.position, wayPoints[currentRoot].position, step);


        Vector3 pos = wayPoints[currentRoot].position;

        float test = Vector3.Distance(target.position, pos);
        transform.LookAt(pos);
                    
        if(Vector3.Distance(transform.position, pos) < 0.5f)
        {
          currentRoot = (currentRoot < wayPoints.Length - 1) ? currentRoot + 1 : 0;
        }

    }
}

シーン内に巡回するGameObjectを配置します.

図ではCubeを選択しています

このGameObjectにPatrol.csをアサインします.

Sizeは巡回箇所の数で,ここに数字を入れると下に入力フィールドが現れます.Speedには適当な数字を入れておきます.

Elementには GameObject>CreateEmptyで作成した空のオブジェクト(位置情報のみ)を配置いれます.

これで再生すると,Patrol.csをアサインしたGameObjectがWayPointsを巡回するようになります.