名古屋でアプリ・VR開発を行っています
ワクワクできるゲームをガンガン開発リリース中!

GameObjectをアニメーションに合わせて動かしてみた

こんにちは。

SAT-BOXカピバラさんです。

今回は、IKシリーズからアニメーションについて書いていきたいと思います。


では、白い人型のモデルに登場してもらいたいと思います。

登場回数も結構な回数になってきたので、

そろそろこのモデルにも名前を付けますか。

命名『SAT-MAN』

f:id:sat-box:20170703185621g:plain

…センスのある、いい名前ですね。

今回も「SAT-MAN」に働いてもらいましょう!

SAT-MANの視線の先にはとてもおいしそうなファーストフード達!

f:id:sat-box:20170703185747p:plain

(体に悪そう)

今回は、このキャラを移動のスクリプトを書かずにアニメーションだけで、アニメーションに合わせてGameObjectを動かしていきたいと思います。

今回のアニメーションはこちらのアセットから拝借いたしました。
https://www.assetstore.unity3d.com/jp/#!/content/15667:AssetStore「Taichi Character Pack」

f:id:sat-box:20170703191031p:plain



今回は前に転がるアニメーションを使いたいと思います。

こんな感じのアニメーションになります。

f:id:sat-box:20170703190827g:plain

まずはスペースキーを押すと転がるように処理を書きます。

※これは「移動のスクリプト」には含みません。

これで見てみましょう。

f:id:sat-box:20170703191232g:plain

このままだと転がるアニメーションをしたあと、元の位置に戻ってしまいますね。。。

f:id:sat-box:20170703191740p:plain

「こんなの、Animatorの [ApplyRootMotion]にチェックを入れればええんちゃうの?」とか思っている、そこのあなた。

「ところがどっこいそれだけじゃ上手くいきません。」

アニメーションデータの、Root Transform Position (XZ)のBake Into Poseにチェックを外してみます。

f:id:sat-box:20170703192610p:plain

するとあら不思議、うまくいきました!

この項目は、チェックを入れると、Transformの値をアニメーションによって変更するかどうかになります。

Transformの座標が変更しているかどうか、シーンビューで見てみるとよくわかると思います。

【チェックを入れた場合】
f:id:sat-box:20170703192848g:plain

【チェック外した場合】
f:id:sat-box:20170703192911g:plain

こんな感じでアニメーションに合わせてTransformの位置を変更することが出来ます!ただ、アニメーションに合わせてTransformの位置を変更するようにすると、入ってはいけない場所に行けるようになってしまったり色んな所にめり込んで行ったりと、デメリットもたくさんあります。

これらのデメリットは、色んな工夫で解決できます。

ですが個人的には今後の拡張性も兼ねてスクリプトで移動の制御をするようにすることをお勧めします。


「Foooooooo!!! I love fast-food!!!」

f:id:sat-box:20170703192542g:plain

「あっ、通り過ぎた」


では(^^)/

Unityのコンポーネント追加方法紹介!

こんにちわ!SAT-BOXのペンギンです。

今日はコンポーネントの追加方法について、1つ紹介したいと思います!

オブジェクトにコンポーネントを追加したい場合、Assetsの中からドラッグアンドドロップで追加することがありますよね。

オブジェクトが1つだけなら全く問題ないのですが、これが複数オブジェクトとなると、ちょっと変わってくるんですよね。

複数オブジェクトを選択してドラッグアンドドロップで追加しようとしても追加されるのはカーソルを合わせたオブジェクトだけ…

なんでやねん!っていつも腑に落ちないです。

選択しているオブジェクト全て追加されればいいのにっ!

f:id:sat-box:20170626201543j:plain

f:id:sat-box:20170626180954p:plain

複数オブジェクトに同時にコンポーネントを追加する方法を複数オブジェクトを選択してAddComponentから毎回スクリプト名を入力する方法しか知らなかったので、いつもいつも入力していました...。

、ついこの間、複数オブジェクトを選択してInspectorにドラッグアンドドロップすると、選択しているオブジェクト全てにコンポーネントが追加されることに気づいたのです!

f:id:sat-box:20170626181337j:plain

f:id:sat-box:20170626181618p:plain

画期的発見でした(笑)

いままで作業効率の悪い面倒な追加方法をしていたんだなって、

ちょっとションボリしました。

みなさんも効率の良い作業方法を見つけていきましょう!

 

以上、ペンギンでした!

PlayerPrefsの謎

こんにちは、SAT-BOXのコアラです。

今日はタイトルの通り、PlayerPrefsの話です。



PlayerPrefsといえば、Unityでセーブ機能を作るときに使うものですよね!

簡単にセーブ、ロードができるので使いやすい反面、欠点があります。

欠点

1、保存できるものがint型、float型、string型に限られる

2、Windowsだと保存場所がレジストリになる



欠点1の話はしません!一行で完結しました。

欠点2が今日のメインストーリーです。僕がPlayerPrefsを使いたくない最大の理由がここにあります。

レジストリ

PlayerPrefsの保存場所は、OSによって異なります。

それについては、以前のSAT-BOXブログに書いてありました。
ameblo.jp

そして、Windowsだとレジストリに保存され、レジストリにはOSの重要な情報が入っているため、下手にいじるとPCが壊れます。

僕はレジストリいじって壊したことがあります

そんな僕からしたらレジストリに保存されるというのは、トラ、ウマ、コアラです。

なのでPlayerPrefsはあまり使わないのですが、ふと気になったことがありました。

「Windows10だったら保存場所変わってたりしないかな~」って

そんなに期待してませんでしたし、結論から言って変わってなかったです。

ですが、検証しているときに大事件が起こりました。

それは・・・


Unity5.5からレジストリに保存されていない!


6月最大の衝撃でした。

前後のバージョンをいくつか落として試しましたが、5.4.5まではレジストリにあることが確認できました。

しかし、5.5からのバージョンではレジストリの中に保存されていませんでした。

PlayerPrefs.GetString("Koala")などで保存したものは持ってこれたので保存はされているみたいですが・・・(レジストリの中も結構探しました・・・)


つまりどうゆうこと?

予想1 仕様が変わった

これが僕の中では濃厚ですが、Unityの5.5からのドキュメントなどを見ても、PlayerPrefsの保存場所はレジストリの中で変わっていませんでした。

また、調べても保存先が変わったというような情報は見つかりませんでした。

予想2 コアラがなんがミスした

ないと信じたい。

予想3 環境の違いでなんか起きた



結論

わからんけどコアラが怪しい


全く心当たりはないですが、他の事例が見つからなかったので何かやっちゃったかもしれません。

それに、人を疑うくらいなら自分を疑いたかった・・・ かっこいー

最後に、今回の検証で作成したプロジェクトの数とソースコードを載せておきます

f:id:sat-box:20170619192543p:plain
7つ!それぞれUnityのバージョンが違います!(これいらないかも

using UnityEngine;
public class Sample : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
        PlayerPrefs.SetString("Koala", "Koala!");
        PlayerPrefs.Save();
        Debug.Log("SAVE");
    }

}

間違ってないよね!?

是非皆さんも確認してみてください。僕も引き続き検証していきます。

以上、PlayerPrefsの謎でした!


※追記(2017年10月20日)
解決しました!
PlayerPrefsの謎(解決編) - SAT-BOX BLOG
レジストリの別の場所に保存されているようです。

HumanoidのIKを使ってみる3

こんにちは。

SAT-BOXカピバラさんです。

今回も、前回同様、UnityHumanoidIKの機能を紹介したいと思います。

前回の記事はこちらからどうぞ。
sat-box.hatenablog.jp
sat-box.hatenablog.jp


毎度お馴染み、白い人型のモデルに登場してもらいたいと思います。


相変わらず今回も哀愁を漂わせております…ん?
何かを見てますね。
f:id:sat-box:20170612181244g:plain


一体何を見ているんでしょうか。
こ、これは!


f:id:sat-box:20170612181406g:plain

ハ、ハンバーガー…!
と、茶番は置いておいて、今回はこのハンバーガーが足元に移動してきた時に足が上に乗るように設定していきたいと思います。

まずは現状。

f:id:sat-box:20170612181911g:plain

こんな感じで、足元に物を置いても足がハンバーガーの中に埋まって、足を乗せられてないですね。

前回のソースコードを若干修正しつつ、足元のコライダーに合わせて足のポジションをセットする処理を追加して行きたいと思います。

using UnityEngine;
using System.Collections;

public class IKController : MonoBehaviour
{

	[Header("HandIK")]
	[SerializeField]
	public Transform rightHandAnchor = null;
	[SerializeField]
	public Transform leftHandAnchor = null;

	[Header("LookIK")]
	[SerializeField, Range(0.0f, 1.0f)]
	private float lookTotalWeight = 0.0f;
	[SerializeField, Range(0.0f, 1.0f)]
	private float bodyWeight = 0.0f;
	[SerializeField, Range(0.0f, 1.0f)]
	private float headWeight = 0.0f;
	[SerializeField, Range(0.0f, 1.0f)]
	private float eyeWeight = 0.0f;
	[SerializeField]
	private GameObject lookTarget;

	[Header("FootIK")]
	[SerializeField]
	private bool isFootIK;


	private Animator animator;

	void Start()
	{
		animator = GetComponent<Animator>();
	}

	void OnAnimatorIK()
	{
		//アニメーターが無いときは処理しない
		if (!animator)
			return;

		//右手を固定
		if (rightHandAnchor != null)
		{
			SetIkWeight(AvatarIKGoal.RightHand, 1.0f, 1.0f);
			SetIk(AvatarIKGoal.RightHand, rightHandAnchor.position, rightHandAnchor.rotation);
		}

		//右手を固定
		if (leftHandAnchor != null)
		{
			SetIkWeight(AvatarIKGoal.LeftHand, 1.0f, 1.0f);
			SetIk(AvatarIKGoal.LeftHand, leftHandAnchor.position, leftHandAnchor.rotation);
		}

		//ターゲットの方向を向くように
		if (lookTarget != null)
		{
			animator.SetLookAtWeight(lookTotalWeight, bodyWeight, headWeight, eyeWeight);
			animator.SetLookAtPosition(lookTarget.transform.position);
		}

		if (isFootIK)
		{
			Vector3 rightPos = animator.GetIKPosition(AvatarIKGoal.RightFoot);
			Vector3 leftPos = animator.GetIKPosition(AvatarIKGoal.LeftFoot);
			Vector3 diffR = Vector3.zero;
			Vector3 diffL = Vector3.zero;
			RaycastHit ray;

			Debug.DrawLine(rightPos, rightPos  + Vector3.down);

			if (Physics.Raycast(rightPos + Vector3.up * 0.3f, Vector3.down, out ray))
			{
				diffR = (rightPos - ray.point) - Vector3.up * 0.1f;
				SetIkWeight(AvatarIKGoal.RightFoot, 1.0f, 1.0f);
				SetIk(AvatarIKGoal.RightFoot, -diffR, Quaternion.identity, true);
			}
			if (Physics.Raycast(leftPos + Vector3.up * 0.3f, Vector3.down, out ray))
			{
				diffL = (leftPos - ray.point) - Vector3.up * 0.1f;
				SetIkWeight(AvatarIKGoal.LeftFoot, 1.0f, 1.0f);
				SetIk(AvatarIKGoal.LeftFoot, -diffL, Quaternion.identity, true);
			}

			animator.bodyPosition += Mathf.Max(diffR.y, diffL.y) * Vector3.down;
		}
	}

	//IKの重みを設定する
	void SetIkWeight(AvatarIKGoal _goal, float _posWeight, float _rotWeight)
	{
		animator.SetIKPositionWeight(_goal, Mathf.Clamp(_posWeight, 0.0f, 1.0f));
		animator.SetIKRotationWeight(_goal, Mathf.Clamp(_rotWeight, 0.0f, 1.0f));
	}

	//IKを指定して固定させる
	void SetIk(AvatarIKGoal goal, Vector3 _pos, Quaternion _rot, bool isAddIKPosition = false)
	{
		if(isAddIKPosition)
			_pos +=	animator.GetIKPosition(goal);

		animator.SetIKPosition(goal, _pos);
		animator.SetIKRotation(goal, _rot);
	}
}


こんな感じです。
ちょっと段々長くなってきましたね。。。

やっていることとしては左右の足元の少し上辺りからレイを地面に向かって飛ばして、何かコライダーに当たったらそこに足を設定する、という感じです。詳しいことはソースコードを見てください(丸投げ)

無事、ハンバーガーの上に足をのせることに成功しましたね!

f:id:sat-box:20170612182351g:plain

今回は簡単にのせるだけにしましたが、いろんな方が地面の形に合わせて足の角度を変えたりなどソースコードを公開されているので、もっと細かく設定したい人はそちらを参考にどうぞ!

gametukurikata.com

tips.hecomi.com


では(^^)/

鵜飼いを見に行った話

こんにちわ!SAT-BOXのペンギンです。

先週の土曜日、6月3日に愛知県犬山市木曽川鵜飼いを見に行きました!

 

実際には鵜飼いだけではなく、犬山城や城下町も見てきました!

どれも初めての体験でしたが、一番はやはり鵜飼いが感動しました!

 

かがり火とかも幻想的で感動するあまり、

「おおお~!すごいな~!」しか声が出ませんでした(笑)

 

体験していない方は一度は体験しても良いかもしれませんね~!

では失礼します!

 

鵜飼いを見に行く話

こんにちは、SAT-BOXのコアラです。

ブログでペンギンさんが紹介していましたが、先日フットサルがありまして、いやー、体力の衰えを感じてしまいました。

まだ若いんですが。本当に若いんですが。



SAT-BOXではフットサルのような社内イベントが定期的に行われていますが、今週末は鵜飼いを見に行きます。

鵜飼いってなに?って方のために五七五で説明を考えたので聞いてください。

鵜飼いとは 鵜でアユをとる 漁法だよ


らしいです。調べたので間違いないです。

アユ料理も食べれるので、個人的にすごく楽しみにしています。



何を隠そう、コアラはアユが好物なのです。(本当のコアラって魚食べれるのでしょうか、気になります)

好きな魚ランキングでは1位かもしれません。ウナギがライバルですね。

好きな食べ物ランキングだと圏外ですね。ウナギは35位です。



話がそれましたが、コアラはウナギが好きだということを最後にお伝えします。おいしいからね!

では、行ってきます!

HumanoidのIKを使ってみる2

こんにちは。

SAT-BOXカピバラさんです。

前回はHumanoidのIKの機能を使ってHumanoidのモデルの手を左右の棒に固定しました。今回はその続きです。

今回は、Humanoidモデルが何か物を『見る』という処理を作ってみたいと思います。という事で今回も前回と同様白い人型のモデルに登場してもらいたいと思います。

はい。
相変わらず今回も哀愁を漂わせております。

f:id:sat-box:20170424191056g:plain

IKの設定については前回のIKの記事を参考に設定してください。
sat-box.hatenablog.jp


まず、見る対象のオブジェクトを作成します。
今回は、このアセットを拝借。

f:id:sat-box:20170522171003j:plain
http://u3d.as/Mh3:FREE Food Pack

…おいしそう。

この中から、おにぎりを頂戴してとりあえず配置。
今回はこのおにぎりを人型モデルが見るように設定していきます。
その後、この人型モデルの目の前に持ってきます。

ほら、おにぎりだよー!
f:id:sat-box:20170522171331g:plain

このままだと、勿論見ないですよね。

前回のソースコードに追加して、見る処理も書いていきます。

using UnityEngine;
using System.Collections;

public class IKController : MonoBehaviour {

	[Header("HandAnchors")]
	[SerializeField]
	public Transform rightHandAnchor = null;
	[SerializeField]
	public Transform leftHandAnchor = null;

	[Header("LookWeight")]
	[SerializeField, Range(0.0f, 1.0f)]
	private float lookTotalWeight = 0.0f;
	[SerializeField, Range(0.0f, 1.0f)]
	private float bodyWeight = 0.0f;
	[SerializeField, Range(0.0f, 1.0f)]
	private float headWeight = 0.0f;
	[SerializeField, Range(0.0f, 1.0f)]
	private float eyeWeight = 0.0f;
	[SerializeField]
	private GameObject lookTarget;

	private Animator animator;

	void Start()
	{
		animator = GetComponent<Animator>();
	}

	void OnAnimatorIK()
	{
		//アニメーターが無いときは処理しない
		if (!animator)
			return;

		//右手を固定
		if (rightHandAnchor != null)
		{
			animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
			animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
			animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandAnchor.position);
			animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandAnchor.rotation);
		}

		//右手を固定
		if (leftHandAnchor != null)
		{
			animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
			animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
			animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHandAnchor.position);
			animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHandAnchor.rotation);
		}


		//敵が自分の方向を向くようにする
		if (lookTarget != null)
		{
			animator.SetLookAtWeight(lookTotalWeight, bodyWeight, headWeight, eyeWeight);
			animator.SetLookAtPosition(lookTarget.transform.position);
		}
	}
}


こんな感じです。
前回に比べて調整する項目が増えました。

f:id:sat-box:20170522172248p:plain

上から説明していくと

LookTotalWeight…全体の重み。
BodyWeight…体の重み
HeadWeight…頭の重み
EyeWeight…目の重み
LookTarget…見る対象

で、重みと表現しているのはどれだけ見る対象に向けるか、のような意味です。1を100%、0を0%と考えてもらい、何パーセントくらい見る対象に向けるか、という感じです。

とりあえず実際にやってみるのが分かりやすいと思うので、ちょっとやってみましょう。

全て1にした状態
f:id:sat-box:20170522173336g:plain

BodyWeight だけ1にした状態
f:id:sat-box:20170522174739g:plain

HeadWeight だけ1にした状態
f:id:sat-box:20170522174837g:plain

EyeWeight だけ1にした状態
f:id:sat-box:20170522174937g:plain

あっ
この人型のモデル、目が無い…。
目だけ動く感じは分からなかったと思いますが、BodyWeightだけ1の時は、体で見る方向を向く感じで、HeadWeightだけ1の時は頭だけ、その方向を向く感じだったと思います。


こんな感じで調整できるようになるので、「人の感じ」を出すときは見るという調整がいると思うので、ぜひ使ってみてください!

では(^^)/

次の記事
HumanoidのIKを使ってみる3 - SAT-BOX BLOG


前回の記事
UnityでHumanoidのIKを使ってみる1 - SAT-BOX BLOG