月別アーカイブ: 2014年7月

Unity、Tagのついたオブジェクトをスクリプトから取得する際、Cloneオブジェクトを取得してしまう問題

GameObject.FindGameObjectWithTag関数の戻り値にインスタンス化されておらず、HierarchyにもないPrefabを取得してしまう問題。

解決策はそのTagの付加されたすべてを取得して、その中のものがHierarchyに存在するかどうかを調べ、存在していればそれを選択する。

		GameObject gameObject;
		GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("HogeHoge");
		foreach(GameObject temp in gameObjects){
			if(temp.activeInHierarchy){
				gameObject = temp;
				break;
			}
		}

上記のスクリプトのactiveInHierarchyがtrueでもCloneオブジェクトを何故か拾うので、上記のは使えない。かわりにオブジェクトの名前にCloneという文字列を含んでいるか含んでいないかで判断する。すると以下のようになる。

		GameObject gameObject;
		GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("HogeHoge");
		foreach(GameObject temp in gameObjects){
			if(temp.name.IndexOf("Clone") == -1){
				gameObject = temp;
				break;
			}
		}

transform.forwardとtransform.rotation * Vector3.forwardについて

transform.forwardの値はtransform.rotation * Vector3.forwardと等しい。

それならtransform.rotation * Vector3.forwardの使い道は文が長くなるので使わないが、ちょっと式を変更すると使う場面がある。例えばQuaternionの値だけ分かっている時、このローカル座標のz軸をワールド座標に変換したいのなら

Quaternion rotation = Quaternion.Euler(0, 45, 0);
Vector3 position = rotation * Vector3.forward;

と出来る。

transform.InverseTransformPointについて

普通の引き算「target.position – transform.position」と違うのはローカル軸を基準にした位置を返す。
普通の引き算はワールド座標を基準にしている。


using UnityEngine;
using System.Collections;

public class MyMathfAtan2 :
MonoBehaviour {
	public
		Transform target;
	void Update() {

		Vector3 relative = transform.InverseTransformPoint(target.position);

		print ("relative " + relative);
		print (target.position - transform.position);

		float angle =
			Mathf.Atan2(relative.x, relative.z) *
				Mathf.Rad2Deg;
		print (angle);
//		transform.Rotate(0, angle, 0);
	}
}

Unity、自キャラを傾かせずに敵キャラへ向かせるには

transform.LookAt関数を使えば自キャラを敵キャラへ簡単に向かせられるが、敵キャラが自キャラより高い場所にいる時は、自キャラが傾いてしまう。傾かないようにするには以下のようにする


using UnityEngine;
using System.Collections;

public class MyTestLookRotation : MonoBehaviour {

	public Transform target;
	void Update() {

		Vector3 relativePos = target.position - transform.position;

		relativePos.y = 0;

		Quaternion rotation = Quaternion.LookRotation(relativePos);

		transform.rotation = rotation;
	}
}

参考になったUnity公式ページ

Unity、キャラクターに重力を作用させるには

インポートしたキャラクターのFPXファイルをクリックして、インスペクターを表示させる。その中のAnimationタブを開いてRoot Transform Position(Y)のBake Into Poseチェックボックスにマークを付ける。その下のBased Uponはキャラクターが地面と設置する場所を決定するための物。center of massはキャラクターの重心と地面が設置するように設定する物で、通常のHumanoid型のキャラクターにはこれを使わない。使うとキャラクターの重心は腰に設定させるのでキャラクターの下半身が地面に埋まってしまう。なので通常はFeetを選択する。すると足の下が地面との設置面に設定される。これでSceneを再生すると地面に設置するまで落下し続ける。

次にRoot Tranform RotationのBake Into Poseにチェックマークを付ける。するとキャラクターがアニメーション中に横を向いたりしてもRotationは回転されなくなる。

参考になったUnity公式のURL

Unity、MecanimのアニメーションにSub-state machineをスクリプト側から操作するには

通常以下のように書くが

AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.IsName("Base Layer.Idle") {

}

Base Layer上に書かれたSub-State Machineにアクセスするには「Base Layer」文字は削除して

AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.IsName("SubStateMachine.hogehoge") {

}

と書く。

参考になったサイト

Unity、体力ゲージとそのスクリプトの実装について

・プレイヤーの体力システムのコーディングのチュートリアル動画

このチュートリアルのソースコードのダウンロードリンク先はhttp://brackeys.com/preview/create-a-survival-game/

・無料でダウンロード出来る体力システムのスクリプト、Asset Storeからダウンロード

https://www.assetstore.unity3d.com/jp/#!/content/7112

https://www.assetstore.unity3d.com/jp/#!/content/2806

Unity、キャラクターに重力を作用させるには

キャラクターにRigidBodyコンポーネントを追加しても重力が作用しなかったので、調べてみるとCharacterControllerのMove関数にスクリプトから重力を加えないといけない。詳しくは

http://docs-jp.unity3d.com/Documentation/ScriptReference/CharacterController.Move.html

でもジャンプモーションの時に重力を作用させると動きがおかしくなってしまうので、ジャンプモーション中は重力を作用させないようにスクリプトする必要がある

フリーのモーションデータを大量にダウンロード出来るサイト

https://sites.google.com/a/cgspeed.com/cgspeed/motion-capture

http://mocapdata.com/

http://accad.osu.edu/research/mocap/mocap_data.htm

http://mocap.cs.cmu.edu/

http://www.turbosquid.com/search/motion-capture?keyword=&media_typeid=5&sort_column=a5&sort_order=asc

http://www.motioncapturedata.com/2009/04/more-than-4000-free-mocap-data-from.html