Nanashi-soft○プログラマ専用○Unityでゲーム開発○
◇Unityでゲーム開発 -Mecanimを使ってキャラを動かしてみる(12-
実際に実装していってみます
様々な方法が考えられるわけですが,単純な構造で考えてみます
・膝ボーンがスカートボーンに近付いたら浮かす
・離れたら戻す
というものです
本当は脚全体とスカート全体で判定したいところですが,ゲームでそんな事をすると処理が重過ぎます
歩行時に一番上がるのは膝なので,そこをスカートに張り巡らされたボーンの繋ぎ目で検知して動かす事にします
○膝ボーンにコライダを付ける
膝ボーンの位置はメカニムに組み込んだ際に,オートで設定されているはずなので,それを確認すれば良いです
Project上のモデルデータをクリック
Inspectorの Rigタブ→Configure...ボタン
人型が表示されるので,膝の部分をクリックすると,Hierachyにその部分が選択される
両膝のボーンの場所を覚える ←
Inspectorの Doneボタンを押して終了
シーン上に配置したキャラの Hierarchyにはボーン構造も見える状態になっています
先ほど確認した膝のボーンをクリック
メニュー→Component→Physycs→Sphere Collider
Game画面の右上の Gizmosをオンにすると,コライダのサイズがワイヤ表示されます
Inspectorの Shere Collider→Radiusを 0.1に設定(適当に縮めただけです)
○スカートを浮かす
これを適当に実装して,わけのわからない動きになったので,どういう動きをさせるのか? を説明します
Unityを実行中にボーンの Inspector→Transform→Rotaion→Zの数値を変えると,スカートが動きます
Z軸回転の小さくすると広がり,大きくするとすぼみます
回転ですので,ボーンの軸の位置は変わりません
そうすると,膝が近付いて来た際にスカートを広げたとしても,位置は動かないので膝が突き抜けるのを回避できません ←これになかなか気が付かなかった
1つ上の階層のボーンを回転させて,自身が広がるようにする必要があります
コレを踏まえてスクリプトを作成する
Projectの下の Create→C# Script→適当に skirtなどの名前に変える
以下のスクリプトを保存する
using UnityEngine;
using System.Collections;
public class skirt : MonoBehaviour {
float syoki_rotz; //初期位置
float counter; //カウンター
void Start () {
syoki_rotz=this.transform.parent.localEulerAngles.z; //初期位置を保存
counter=0;
}
// Update is called once per frame
void Update () {
float radius=0.1f;
Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, radius); //この範囲内のコライダを抽出
int i = 0;
if(hitColliders.Length == 0){
//周囲にコライダが無くなったら,元の位置に徐々に戻す
if(0 < counter){
this.transform.parent.localRotation=this.transform.parent.localRotation * Quaternion.AngleAxis(5.0f, Vector3.forward);
counter--;
}
}else{
while(i < hitColliders.Length){
if(hitColliders[i].name != "Plane"){ //地面との衝突を除く
//膝が近付いて来たのでスカートを広げる
this.transform.parent.localRotation=this.transform.parent.localRotation * Quaternion.AngleAxis(-5.0f, Vector3.forward);
counter++; //広げた回数をカウント
}
i++;
}
}
}
}
このスクリプトをスカートのボーンに追加する
注意点として,スカートの一番上には設置しないこと。1つ上のボーンを回転させるので,おかしくなる
1つ上のオブジェクトは,transform.parentでわかります(Unity3Dの仕様)
親のオブジェクトの回転角は,localRotationではなぜか正しく取得できませんでしたので,localEulerAnglesを使用して取得しました(なぜかはわかりません)
セットする時は localRotationでうまくいったので,そのままにしています
ちなみに,回転軸に関して,直接値を触ろうとすると,途端に破綻します(汗
回転計算は,基本的に行列を掛けるものだと思っていると幸せになれます
DirectXや OpenGLを直接プログラミングした事がある場合の経験則です('-'*)
なので,親オブジェクトの現在の回転角に,Quaternion.AngleAxisで角度ベクトルを生成して掛けています
これを,transform.rotation.zの値を変えようと考えると非常に難しいです(簡単そうに見えるのですがハマりの原因です)
○TOP○プログラマ専用○Unityでゲーム開発○