「技術メモ」カテゴリーアーカイブ

Dictionaryの使い方(MBAAS関連)

MBAASはJSON互換だけど,JSONは遅れずDictionaryが受けられるらしい.

んで,Dictionaryを真面目に使ったらエラーでるのよ.

 

いける例

using System.Collections.Generic;

public class skillSender : MonoBehaviour {
	
		 static public Dictionary<string,int> skillPDic;//スキルチェックポイント用


	// Use this for initialization
	void Start () {

			skillPDic = new Dictionary<string, int> () {
				};

	}

NGの例

using System.Collections.Generic;

public class skillSender : MonoBehaviour {
	
		 static public Dictionary<string,int> skillPDic;//スキルチェックポイント用


	// Use this for initialization
	void Start () {

			Dictionary<string,int> skillPDic = new Dictionary<string, int> () {
				};

	}

 

 

 

Unity入門-14

 

0秒になったら終了させる

  • まずは時間がゼロ秒になったら終わらせるプログラムを入れる場所を探す
  • 探し方概要
    • 概要:いろいろな場所にDebug.Log(“koko”);を書いて,1秒毎に変化する場所を探す
    • 入力した行が実行された時にコンソールkokoと表示される
    • コンソールのCollapseはオフにする(Collapse同じ内容は1行だけ表示する機能をオフにする)
  • 実際の探し方
    • 各関数{}内の最初か終わり近くにDebug.Log(“koko”);を記入
    • 保存→ゲーム実行→Consoleを確認 を繰り返し,秒変化と同じタイミングで現れる箇所を探す
    • ヒント:秒の変化と音(Tick)の再生は同期しているので,そのあたり,,,?
  • その場所に以下のプログラムを入力する
			if (gameTime < 1) {
				//go end
				StopCoroutine("loop");
				Invoke("goEnd", 2f);
			}

変数 gameTimeが1未満になったら,時間制御をしているコルーチンloopを止めて,goEndの関数を2秒後に実行 の意味

こちらは2秒後に実行されるので,少し余裕が持てます.goEndを実行するタイミング(ここでは2秒)を変えて自分が最も良いと思う時間に変更してみましょう

なお2fのfはfloat(実数)の意味です.Unity上では実数の場合はfとつけるルールがあります

 

これでもいけます

if (gameTime < 1) {
goEnd();
			}

変数gameTimegが1未満になったらgoEnd関数を実行(こっちは2秒待たないのでせわしない)

 

シーンチェンジはどこ?

  • シーン「end」にジャンプする関数 void ○○○(){   } はどこか再度確認すること(上でに書いてありますが)

変数宣言をいろいろ試す

  • 変数宣言をする場所がある
    • グローバル編
      • プログラムのどこでも使えるけど,このプログラム外では使えない
      • publicをつけるとインスペクタで設定できる.インスペクタで設定した値は,プログラムで宣言した値よりも優先される(プログラム側で変更はできる)
      • privateをつけるか何もつけない変数宣言はインスペクタには表示されない
    • ローカル編
      • 関数内で使える(ちょいとメモ代わりや,変数の受け口に使える)
    • 神編
      • staticは神
      • public static int mikeneko; と宣言すると,スクリプト名.mikeneko でゲーム内のどこでも使える
      • ただし関数などによってはstaticを嫌うものがあるので,その際はnamespaceなどを使ってusingする

NCMBでデータストア管理

96時間はまったこと

  • NCMBデータストアはJSON互換だけどJSONは保存できない
  • NCMBデータストア一回のセッションに複数のログ(今回はスキルチェックの結果)を保存する場合は,Dictionaryで保存する
  • UnityのC#でDictionaryを使うには最初に「using System.Collections.Generic;」って言っておく
  • アクセス権を設定する場合,新規オブジェクトの場合は「NCMBACL acl = new NCMBACL ();」でいいが,既存の場合は一旦アクセス権を読み込んでから書き換える(参考サイト
  • データストアはACL設定しないと公開になる仕様らしい(ランキングとか用なので)
  • ACLのスクリプトでユーザ名の使い方その1
    NCMBUser user = NCMBUser.CurrentUser;
    string userName = user.UserName;
    			NCMBACL acl = new NCMBACL ();//今回のログは新規作成なのでnewでよい
    			acl.SetWriteAccess (userName, true);
    			acl.SetReadAccess (userName, true);

     

 

Unity入門-13 スクリプトmyQuestをざっくり対訳してみる

対訳してみました.

元のスクリプトは

using UnityEngine;
using System.Collections;
using UnityEngine.UI;//UIを使用するのに必要
using UnityEngine.SceneManagement;//シーン遷移をするのに必要

public class myQuest : MonoBehaviour {

	[SerializeField, HeaderAttribute ("経由地の数")]
	public int points;

	//sound
	[SerializeField, HeaderAttribute ("効果音をドロップ")]
	public AudioClip getSound;
	public AudioClip tickSE;


	//default time
	[SerializeField, HeaderAttribute ("カウントダウンの初期時間")]
	public int gameTime;
	[SerializeField, HeaderAttribute ("残時間のUItextをドロップ")]
	public Text timeText;
	[SerializeField, HeaderAttribute ("残りの経由地数表示UIをドロップ")]
	public Text nokoriText;

	[SerializeField, HeaderAttribute ("エンディングのシーン名を入力")]
	public string endSceneName;

	//audio source get from this script attached
	AudioSource myaudio;


	// Use this for initialization
	void Start () {

		myaudio =	GetComponent<AudioSource>();
		timeText.text = "残り時間" + gameTime.ToString () + "秒";
		nokoriText.text = "のこり" + points.ToString () + "個";
		//start after nSec
		Invoke("timeCount", 3.5f);
	}
		
	void Update () {
	
	}


	//if hit destroy obj
	void RedirectedOnTriggerEnter(Collider mycollider) {
		//Debug.Log (mycollider.gameObject.tag);
		if (mycollider.gameObject.tag == "pointObj") {
			points--;
			nokoriText.text = "のこり" + points.ToString () + "個";
			myaudio.PlayOneShot (getSound, 0.7F);
			Destroy (mycollider.gameObject);

			if (points < 1) {
				//go end
				StopCoroutine("loop");
				Invoke("goEnd", 2f);
			}
		}
	}

	void timeCount(){
		StartCoroutine("loop");
	}

 

対訳はこちら(画像:クリックで拡大)

%e5%af%be%e8%a8%b3%e3%81%97%e3%81%a6%e3%81%bf%e3%82%88%e3%81%86

次へ

game managerシステムみたいなの

 

よくつかう関数をいれとくのを作ります

using UnityEngine;
using System.Collections;

namespace globalManager{//名前空間

public class myManager : MonoBehaviour {//クラス名はmyManager


		public static void mytest2(){
			Debug.Log ("test");
		}

		public static void mytest3(int cat){
			Debug.Log (cat);
		}


}

}

 

このnamespaseでusingすると呼び出せます

using UnityEngine;
using System.Collections;
using globalManager;//必要

public class slaveScript : MonoBehaviour {

	void Start () {
		myManager.mytest2 ();
		myManager.mytest3 (5);
	}
	

}

これで,コンソールには

「test」「5」と表示されます

 

入力された数値をならす

.lerpがうまく使えなかったので,速度をならしたやつ

月のジャンプ力をこれに入れるとならせますが,配列は3くらいがいいかも

 

	//変数作成
	float[] spArr = new float[5];//spArrというフロートの長さ5の配列を作成
	float avrKmspeed;//平均速度格納用
	
	//初期化
	float sum = 0f;//初期化(てきとうなとこに入れてね)
	
	
		//データ格納

		if (i < 5) {//iが5未満なら
			spArr [i] = myspeed;//配列のi番目に速度を格納して
			i++;//iを1つ増やす
		}
		if (i > 4) {//iが4よりでかければ
			i = 0;//iはゼロね(先頭にもどる)
		}
		

		for (int j = 0; j < spArr.Length; j++) {//配列の長さだけ繰り返すよ
			sum += spArr [j];//sumに配列の中身全部足す
		}
		
		avrKmspeed = sum / spArr.Length;//配列の中身総計を配列の長さで割る

 

キャラクタをジャンプさせる

スクリプトのみです

_jumpPowerの値を他のプログラムや装置で変化させると,動的にジャンプ力が変わります

using UnityEngine;
using System.Collections;

public class jump : MonoBehaviour {

	// 変数一覧
	public GameObject _myobj;//ここにRigidbodyのついてるゲームオブジェクト
	Rigidbody _myrigid;//リジッドボディ用変数
	public float _jumpPower;//ジャンプ力



	void Start() {
		_myrigid = _myobj.GetComponent<Rigidbody>();//ゲーム開始時にゲームオブジェクトからリジッドボディのコンポーネントを取得する
	}


	void FixedUpdate() {//fixed updateはリジッドボディの時に使う
		if (Input.GetKeyDown("space"))//キー入力でスペースキー
			_myrigid.velocity = new Vector3(0, _jumpPower, 0);//y方向にジャンプ力を加える

	}
}

 

実行の様子

空のゲームオブジェクトにスクリプトをアサインして,リジッドボディのついたcubeオブジェクトをスクリプトにアサインして,スペースキーでジャンプさせています

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

シリアル通信時に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);
			}
		}


	}
		


}

 

実行動画