admin のすべての投稿

Unity入門-7 マップビューの作成

シンプルなマップビューの作成

  1. ゲームにはマップビューやナビ画面,飛行機であればレーダーが装備されています.こうしたビューはプレイフィールドを俯瞰で2次元的に見せ,敵やアイテムを記号化して表示させることが常でしょう
  2. ここではカメラを増やすことで,最も簡単なマップビューを装備する
  3. まずはマップビュー用の画面を作成する.そのためにはカメラをもう一つ追加する
  4. GameObject>Camera でヒエラルキーにカメラを追加する
  5. 下図のように設定するmap1
  6. 上図の4はパースペクティブ(透視図法)からオルソ表示(正射投影)に変更している.また7はいわばカメラのレイヤーである.この数字が大きいと手前に表示される.この数値で重なり順を決めることができる.なお後述のレイヤーと混同しないように
  7. 次に自分の目印として以前作成した球を再利用する.球(sphere)を先ほど作成したCameraの子にする.同じ位置の上空に巨大な球を置き、俯瞰で見た際に目印になるようにする
  8. 下図のように設定するmap2
  9. ゲームを再生して確認してみること
  10. ところが,上を見上げると白い球が見えてしまう(下図の上)
    map3

レイヤーの変更

  1. そこで,この白い球を別のレイヤーへと移行する
  2. Sphere(球)を選択しInspectorLayerからAdd Layer… を選択するmap4
  3. 開いたLayer画面の入力できる部分に好きな名称のレイヤー名を設定する,図の例ではmarkerと入れてあるmap5
  4. まだレイヤーが作成されただけなので,再度Sphere>Inspector>Layerからmarkerのレイヤーを選択するmap6

レイヤー別の表示,非表示

  1. 次にメインの画面のカメラにこのmarkerのレイヤーを描画しないように設定する
  2.  FirstPersonCharactorを選択し,CullingMaskのプルダウンからmarkerをクリックしチェックをオフにする.これでレンダリングされなくなるmap7
  3. ゲームを再生して確認してみること
  4. 同様に,他の場所にもCubeなどを配置し,マップ上に目印が表示されるようにする.マップはユーザがゲーム空間内移動したくなるモチベーションとなる
  5. 余談ですが,レイヤーとは別にタグというものがある.こちらは味方,敵,障害物といったゲームに作用する物にそれぞれ共通のタグをつけ,誤って味方を撃っても血が出ないようにする仕組みである.タグについてはこちらを参考に

マテリアルの作成

  1. マーカーの色を変更したい場合は,マテリアルを作成する
  2. Assets>右クリック Create Materialを選択material2
  3. 下図を参考にMaterialを調整し,Sphereにアサインするmaterial1
  4. 今回は発光させることで影のないマーカーを作成した
  5. Mayaと同様にMaterialを作成することで質感を変化させることができるので、いろいろ試してみること
  6. 今回は使用しないが,テクスチャマテリアルにアサインしてから使用すること

つぎへ

Unity入門-6 FPSとTPS

FPSとTPS概要

  1. 前回使用したリグは三人称視点 third person viewなどと呼ばれ,この視点を使用したシューティングゲームをThird Person Shooting(TPS)と呼んだりする
  2. 逆に一人称視点をFirst Person View 、シューティングゲームをFirst Person Shooting(FPS)と呼ぶ

実装

  1. FPSを実装するため準備を行う.ThirdPersonControllerを選択し,Inspector最上段のチェックボックスをオフにします.これでこのキャラクタ以下全てが非表示されこのオブジェクトにアサインされているスクリプトも動作しなくなるgobjoff
  2. これをスクリプトで動作させたい時はこちらを参考にすること
  3. 次に,MultiPuroposeCameraRigも同様にオフにしますgobjoff2
  4. MultiPuroposeCameraRigをオフにするのは,この中に画面表示のためのカメラが入っており,この後追加するFPSのプレファブにもカメラがセットされていて,カメラが2つ存在するのはマズイから(カメラは複数存在してもかまわないが今回は操作系とぶつかるためでもある)
  5. プロジェクトウィンドウの Assets>StandarsAssets>FisrstPersonCharactor >Prefab>FPSControllerを探し,Sceneにドロップしますfpsadd
  6. 緑色の楕円カプセルが全て地面上に現れるように高さを調整する.これはコライダと呼ぶ衝突判定のための形状である

再生確認

  1. ゲーム再生開始時にカメラが下に落ちるようであれば,コライダが地面にめり込んでいるため(※最近のUnityでは落ちにくいようになっている)
  2. ゲームを再生してみる.歩く音も入っている.またShiftキーを押している間は速く走る.ゲーム再生を止めるときはCtrlキー+Pキーを押す(※ゲームスタート,中止のショートカット)
  3. 自分が作成した地形の中を走り回ってみること

つぎへ

Unity入門-5 親子関係

親子関係2

  1. 先ほどのSphereを選択し,positionに(0,0,0)を入力しますparent1
  2. SphereがCubeの中に隠れます.子オブジェクトであるSphereにとってはCubeが原点(親)になるから
  3. この動作をスクリプトで実施する場合はこちらを参考に

ローカル座標とグローバル座標

  1. このようにオブジェクトが持っている座標と,空間が持っている座標とで表記が異なる
  2. CubeをX軸に30度傾け,移動モードにします(ショートカットW※Mayaと同じ、他も同様)parent2
  3. オブジェクトが持っている軸に沿って移動します.この移動軸をローカル座標と言う
  4. Globalのボタンをクリックすると,空間が持っている軸に沿って=つまり上なら空間のY軸に沿って移動させることができる.こちらをGlobal座標と言うparent5
  5. このように回転させたオブジェクトやその子オブジェクトを移動させる際には注意が必要です

その他のTransform Tools

  1. 移動,回転,スケールなどを使用してみるtools
  2. Inspectorの数値がどう変化するかを確認してみる

つぎへ

 

Unity入門-4 座標系

座標系を理解する

  1. 前回のおさらいです.まずは座標系を理解する.ゲームを再生するとグワーンと動いてキャラクターのところへ移動する.これはMulticamera,,,,が原点(0,0,0)に居てキャラクタの場所へ移動するからである(下図)camrig1
  2. カメラとキャラクタの位置を近づけこの移動を無くす.ThirdPersonControllerを選択し,座標を確認し,その座標を紙などにメモするcamrig2
  3. その座標をMultipuroposeCamera…の座標に入力するrig3
  4. 再生して確認すること

座標系2

  1. 次に球と立方体を作成します.複雑な形状はMayaから読み込むのですが,簡単な形状であればUnity上で作成可能です
  2. GameObject>3D Object>CubeとSphereです
  3. Cubeを選択し,(2,2,2)に移動させます
  4. global
  5. Sphereは原点(0,0,0)に配置しますglobal4
  6. Unity上でも親子付けは重要になります.ヒエラルキー上でSphereを選択し,Cubeにドロップします.SphereがCubeの子になる
  7. このときのSphereの座標がどう変化したかを確認することglobal3

 

つぎへ

Unity入門-3

  1. 次に木を追加してみましょう
  2. (1)Treesモードにし,(2)Edit Trees…からAdd Treeを選択,(3)Broad Leaf_Mobileを選択,(4)Addをクリックして確定し,ブラシで地形上をドラッグすると木が生えます.マシンによっては重い作業となりますので,Density(密度)を下げる
  3. 木が生えてきましたね
  4. 次にキャラクタを追加してみましょう.プロジェクト内のStandardAssets>ThirdPersonCharacotr>Prefab>ThirdPersonControllerを地形の上にドロップしますunity15tps1
  5. 次にカメラを設定します.のStandardAssets>Cameras>Prefabs内のMultipurposeCameraRigHierarchyにドロップします(1)
  6. 次にいまドロップしたMultipurposeCameraRigを選択し,Inspector内のTargetにHierarchyのThirdPersonControllerをドロップし(2),HierarchyのMainCameraを選択しDeleteキーで削除し(3),再生ボタンでゲームモードにします.矢印キーなどでキャラクタを動かしてみましょうunity16tpscam2
  7. 時間のある方は,Standard Assets>Environment>Water>Water>Prefabs>WaterProDaytimeをドロップし,位置やスケールを調整します.映り込みのある水面が作成されますunity18water
  8. ここまで何度かでてきているPrefabとはprefabricatedの略で,パッケージ制作者がすぐにゲーム内で使用できる状態にしたものです.もちろん自分でも作成可能です。また同じキャラクタを複数出現させたい場合なども事前にPrefab化しておくことで簡単に実現可能です

ここまでの状態を保存しておきましょう

Unity入門-2

  1. 次に地形を作成します
  2. Sceneビューに戻り,GameObject>3D Object>Terrain を選択unity5
  3. 作成されたTerrainを選択し,右のInspectorのTerrainを確認する
  4. デフォルトで500×500(m)のTerrainとなっているので,原点を中心にする
  5. ブラシのアイコンを選択し,Raise or Lower Terrainを選択.Brushesでブラシの種類やBrush Sizeを変更しTerrinを編集する
  6. 山が作成される.ブラシの大きさやボケ具合を変えて適当な山を作成する.Shiftキーを押している間は山が沈む(盛り下げ).
  7. ただし最初の平面よりは下がらない
  8. デフォルトでLightmapをベイクするモードになっており毎回計算時間がかかるので,TerainStaticをオフにする
  9. 高さを指定することもできます.Set Heightモードにし,Heightの値に適当な数値を入力して,ドラッグします.
  10. 地形が盛り上がり,一定の高さで停止します.
  11. (余談)Unityの地形はゼロより下がらないので,下がり勾配の川や道路を作成する場合,最初に地形全体を一定の高さに上げておくことが必要になる場合もあります.その場合はHeightの横にあるFlattenをクリックします.
  12. 余談2:国土交通省にデータを使うことで,リアルな地形を作成することもできます
  13. Smooth Heightモードは高さをぼかしますunity8
  14. Paint Textureモードにし,Edit Terrain Layersボタンをプレスするとコンテクストメニューが表示されるので,Add Layer…を選択します
  15. ウィンドウのGrassHillAlbedoを選択しますunity10
  16. 次に,Grass Rocky Albedo,Sand Albedo,CriffSpecularAlbedoなどを追加し,テクスチャを編集してみるunity11tikei

つぎへ

Unity入門-1

  1. Unityが起動するとプロジェクト設定画面が表示されますので,Newをクリックしますice_screenshot_20161003-145126
  2. Project nameを好きなものに設定し,3D モード,Add Assets Packageをクリック(バージョンによってはこの表示位置が異なります)ice_screenshot_20161003-145406
  3. Asset packagesのCharactorsと,Environmentにチェックを入れDoneをクリック(バージョンによって見つからない場合はスキップします)ice_screenshot_20161003-145613
  4. Create projectをクリック
  5. Unityがスタートします
  6. (※Asset Packagesを読み込めなかったり飛ばした場合は,Assets>Import Packages> でそれぞれ読み込んでください)※バージョンによってはStandard  Packagesを読み込みます
  7. Window>Layouts>Default を選択し同じレイアウトにしますunityscreen
  8. ライトの向きを変えてみましょう.Directional Lightを選択します.結果が分かりやすいよにGame画面にしますunity2
  9. 右側に選択した物のInspectorが表示されます.rotationx値を変ささせますunity3
  10. 次にSceneのビューに変更し,Directional Lightがどう変化してるか回転させながら確認しますunity4

次へ   ここから先はLMSをご覧ください.

 

某アクチュエーターコントロールスクリプト

シリアル通信時にCR,LFが入るとおかしくなる現象がおき,それの対策版です

Arduinoのシリアルモニタは改行無しで使用していれば特に問題はおきませんが,うっかり改行つきでテストしてた時に起こる問題を回避しています

寝不足だと改行モードが変わったことに気づかないのよ,,,

 

#include <Servo.h>

unsigned long mytime = 0;
unsigned long hittime;
unsigned long duration;
boolean sensorBool = false;//センサ計測制御用
boolean sensorWorking = false;//
boolean servoUp = false;//servo上下のBool
boolean serialFilter = true;//servo上下のBool
int input_value;//A1入力値
Servo myservo;//サーボ設定
int kaisu = 0;  // 角度のカウンタ max10で使うのは8がいい
int power;//サーボ動作速度
unsigned long startTime;//タイマー用
int servoTime;
int myvar;

void stageReset() {
  myservo.write(0);//最大斜度にする(リセット)
  delay(5000);//最大斜度になるのを待つ
  
  //約4度傾けて水平にする
  servoUp = true;
  power = 200;
  startTime = millis();
  servoTime = 3000;

  kaisu = 4;//4度にセット
}


void setup() {
  Serial.begin(9600);
  myservo.attach(9, 1000, 2000);
  mytime = millis();
  stageReset();//ステージ水平にする
  sensorWorking = false;
}

void mysend() {
  Serial.println(duration);//シリアルに計測時間送る
}


void loop() {
  //回転間隔計測
  input_value = analogRead(1);
  if (sensorBool) {
    if (input_value < 130) {//3.3V is under 130 is read sw ON Long cable version
      sensorBool = false;
      hittime = millis();
      duration = hittime - mytime;
      mysend();
      mytime = hittime;
    }
  } else if (!sensorBool) {
    if (input_value > 300) {
      sensorBool = true;
    }
  }

  //サーボ動作
  if (servoUp) {
    sensorWorking = true;
    if (millis() > startTime + servoTime) {
      servoUp = false;
      serialFilter = true;
      sensorWorking = false;
    }
    myservo.writeMicroseconds(map(power, 0, 255, 1500, 2000));
    Serial.flush();
  } else if (!servoUp) {
    myservo.writeMicroseconds(map(0, 0, 255, 1500, 2000));
   Serial.flush();
  }
}

void serialEvent() {
 // Serial.println("SERIALIN");

 //if(var == 0x0D){
 // return;
 //}else if(var == 0x0A){
 // return;
// }

 
  if (Serial.available()>0) { 
    byte var = Serial.read();

 if(var == 0x0D){
  return;
 }else if(var == 0x0A){
  return;
}else{

    
 if(serialFilter){
    serialFilter = false;
    //byte var = Serial.read();
    myvar = var - 0x30;//16進数でくるので16進数のゼロひく
   //int myvar = int(var);
   // switch (var) {
    //  case 1://stage UP
    servoUp = true;
    
   if(myvar  == 9){
      stageReset();
    return;
    }else if(myvar > 8){
      myvar = 8;
    }else if (myvar < 0){
      myvar = 0;
    }
    
   
if(kaisu > -1 && kaisu < 9 && !sensorWorking){  //ex2 var0

       // int sabun = myvar - kaisu;
       //   Serial.println(myvar);
  //Serial.println(sabun);
   //     servoUp = true;
   int sabun = myvar - kaisu;
   //Serial.println(sabun);
        if(sabun > 0 && !sensorWorking){
         // Serial.println("UP");
        power = 255;
        }else if (sabun < 0 && !sensorWorking){
         // Serial.println("down");
          power = -230;//down
        }

        startTime = millis();
        servoTime = 350 * abs(sabun);
        //if(kaisu > -1 && kaisu < 9){
          if(myvar < 0){
            kaisu = 0;
          }else if (myvar > 8){
            kaisu = 8;
          }else{
          kaisu = myvar;
          }
         
        //}
        //kaisu--;
      }
    //    break;
     // case 2://stage Down
      //else if(kaisu < 9){
       // power = -180;
       // servoUp = true;
       // servoTime = 700;
       // startTime = millis();
       // kaisu++;
      //}
       // break;
    }//end of serial filter
  }// end delte CRLF
  }
  
}
  

 

RigidBody.Velocityを使わない加速減速

マウスの横移動だけで加速減速します.マウスを戻しても逆走はしません.brakeの係数を変えることで減速率が変わりますが,単なる引き算なのであまりきれいではありません.

可能であれば加速に使用しているべき乗

Mathf.Pow(計算したい数値, 乗数);

のような関数を使うか,二次元関数や三角関数を使って減算してみるのもいいかもしれませんね.

 

スクリプト

using UnityEngine;
using System.Collections;

public class mousei : MonoBehaviour {

	public GameObject boatObj;
	public float sensitivity = 0.1f;
	public float brake = 0.05f;
	float firstPos;


	// Use this for initialization
	void Start () {
		firstPos = 0f;
	
	}
	
	// Update is called once per frame
	void Update () {

		float mouse_move_x = Input.GetAxis("Mouse X") * sensitivity;

		if (mouse_move_x > 0.1) {
			Mathf.Pow(mouse_move_x, 2);
			boatObj.transform.position += new Vector3 (mouse_move_x, 0f, 0f);
			firstPos += mouse_move_x;
		} else {
			if(firstPos > 0){
				firstPos -= brake;
			boatObj.transform.position += new Vector3 (firstPos, 0f, 0f);
			}
		}


	}
		


}

 

実行動画

特定のオブジェクトをON/OFFする

まずはスクリプトのみですが

 

using UnityEngine;
using System.Collections;

public class detachchild : MonoBehaviour {

	public GameObject RootObject;

	public GameObject RootObject2;
	// Use this for initialization
	void Awake(){


	}


	void Start () {


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



	public void hanasu(){
		RootObject.SetActive (false);
		RootObject2.SetActive (true);
	}

	public void hanasu2(){
		RootObject.SetActive (true);
		RootObject2.SetActive (false);
	}
}

 

public void クラス名(){

}

をつけたスクリプトは,ボタンのonClickにアサインしてそのクラスを選ぶとボタンから実行できます

 

ゲームオブジェクト変数名.SetActive(false); で見えなくなり

ゲームオブジェクト変数名.SetActive(true); で見えるようになります

そのゲームオブジェクトにアタッチしているスクリプトも無効になりますので注意.