見出し画像

ダンスゲーを作りたい#39 【試作】プレイシステムの基盤その1(アニメーションとtweenの移動の共存)

前回ある程度なに作ればいいかまとめたので今回は以下を作ります。

・Loadしたオブジェクトを初期位置に配置するスクリプトを書く
DJモデルのアニメーションを叩いて動かす
・カメラを取得し、tweenで適正位置に動かす
・ボタンでキャラのアニメーションのトリガを叩き設定済みの技で動く

Loadしたオブジェクトを初期位置に配置するスクリプトを書く

オブジェクトは最終的にはサーバから配信する形式がいいので、初期位置を設定済みにしとくとかいうわけにもいかないので、スクリプトで位置調整をさせます。

void setObject(){
    //オブジェクトを配置してまとめとく用のオブジェクト
    GameObject PlayObjects = GameObject.Find("PlayObjects");
    
    //GameObjectを取得して↑内に配置 仮でローカル読み出し
    GameObject __prefab_f = (GameObject)Resources.Load("フロアモデルのプレハブのパス");
    GameObject floor =Instantiate(__prefab_f) as GameObject;
    floor.transform.SetParent(PlayObjects.transform, false);
    GameObject __prefab_c = (GameObject)Resources.Load("キャラクターモデルのプレハブのパス");
    GameObject chara =Instantiate(__prefab_c) as GameObject;
    chara.transform.SetParent(PlayObjects.transform, false);
    chara.transform.Rotate(new Vector3(0,180,0));
    GameObject __prefab_dj = (GameObject)Resources.Load("DJキャラモデルのプレハブのパス");
    GameObject DJ =Instantiate(__prefab_dj) as GameObject;
    DJ.transform.SetParent(PlayObjects.transform, false);
    
    DJ.transform.Rotate(new Vector3(0,180,0));
    //DJの位置はフロアごとに違う可能性があるためフロアごとの情報として配信する必要有り
    DJ.transform.localPosition =(new Vector3(0,1,5));
    
    //それぞれのオブジェクトはプレイ管理用のマネージャに渡す
    Manager.PlayingManager.Chara = chara;
    Manager.PlayingManager.Floor = floor;
    Manager.PlayingManager.DJ    = DJ;
    Manager.PlayingManager.PlayCamera = GameObject.Find("PlayCam");
    
    //マネージャをスタート
    Manager.PlayingManager.OnStart();
}

こんな感じ?

Managerの内容は後程紹介しますが、ここで書いてるManagerは独自実装なのでそのままやっても動きません。詳しくは過去記事に書いた気がしますのでそちらを。

この処理はプレイ時に表示するUI要素のプレハブにくっついていて、3Dオブジェクトを扱うものの、呼び出しはUI要素を呼び出す流れでやらせます。

画像1

これでいい感じに初期位置配置がされるようになりました。

モデル類はfbxのモデルを配置してからResourceに置き直してプレハブ化したものを使っています。

キャラモデルの中身はさておき、フロアのモデル内には任意の名前(ここではPlayCam)と名付けて、DJブースを映す初期位置に設定したカメラを内包させます。

画像2

名付けとくとカメラのオブジェクト取得するの楽だからね。

なんかよくわかんないですが、キャラモデル全部後ろ向いてるんで180度回します。

DJモデルのアニメーションを叩いて動かす

まずDJモデルのプレハブにAnimatorを設定します。

画像3

定常状態と規定トリガで発動するアニメーションを設定し、AnyStateからトリガscratchでscratchアニメーションに移行する形です。

プレイマネージャでは先ほどのスタートが呼ばれた際に

DJのAnimator.SetTrigger("scratch")でトリガを発動させアニメーションを開始できます。

カメラを取得し、tweenで適正位置に動かす

カメラの取得は名付けることで既に出来ちゃってます。

動かすこと自体はDotweenのDOLocalMoveとかで簡単にできます。

ここで問題なのは、Animationの終了をきっかけに関数を走らせる点。

これは経験則よりアニメーションイベントで解消できます。

画像4

青いやつがアニメーションイベント。鉛筆+みたいなアイコンで追加できます。

アニメーションイベントはanimatorがついているオブジェクトに同時にアタッチしているスクリプトの関数が呼べるので、それ用にスクリプトを作成します。

画像5

このスクリプト内の関数をアニメーションイベントから呼ぶように設定します。

画像6

呼ばれる関数内ではManagerにアクセスして次の処理を呼び出します。

ここでカメラが移動する処理が入る感じですかね。

プレイマネージャはこんな感じ。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
//プレイ系のイベント管理専用マネージャ
public class PlayManager : MonoBehaviour{
    //これは外からセットされてる 
    public GameObject Floor;
    public GameObject Chara;
    public GameObject DJ; 
    public GameObject PlayCamera ;
    //アニメーションが終わったら呼ばれるkeyで分類して処理を流す
    public void  OnAnimationEnd(string key){
       switch (key){
           case "DJ_scratch":
               Playstart_Move();
           break;
       }
    }
    //開始時の処理
    public void OnStart(){
       //DJのアニメーションにトリガをセットしてアニメーションを開始
       DJ.GetComponent<Animator>().SetTrigger("scrach");
    }
    
    //DJのスタートアニメーションが終わったら呼ばれる処理
    public void Playstart_Move(){
       //カメラをtweenで移動
       PlayCamera.transform.DOLocalMove(new Vector3(0f,1.9f,-13f),2.0f);
       PlayCamera.transform.DORotate(new Vector3(8f,0f,0f),2.0f);
    }
}

画像7

アニメーションの長さとかその辺はさておき、やりたいこと自体はできるようになりました。

ボタンでキャラのアニメーションのトリガを叩き設定済みの技で動く

では本プロジェクトのアニメーションの根幹たる仕組みを実装します。

基本的には以前軽く試作したものをベースにやり方をまとめていきます。

まずボーンが通ってHumanoidアバターを適用可能なキャラモデルのFBXを用意します。今回はUnityちゃんでいきますが、blenderで作れるところまで確認済みです。

画像8

画像9

これを一瞬ヒエラルキーに配置し、配置したものをResourceフォルダに持ってきてプレハブ化してしまいます。なんか二種類やり方が出てきますがoriginみたいのでいいんじゃないでしょうか?よくわからんけど。

ここでは読み出しの都合上Characterってファイル名にする必要があります。

画像10

そしたらこれにアニメーションの設定をします。

注意ですが、書き出したりしてFBXと一緒に出力させたアニメーションクリップは、おそらくreadonlyで編集できないので、ctr+Dで複製したものを編集して使います。controller設定時は複製したものを使いましょう。二度手間なので。

画像11

基本は全キャラ共通controllerを使う予定なので、Humanoidにして共通アニメーションを使ってますが、キャラごとにアニメーションも個別にするなら一体ずつcontrollerとクリップを作ればHumanoidにするくだりは不要です。

そしたらキャラプレハブにムーブの終了を検知するためのスクリプトを作成しアタッチします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character_script : MonoBehaviour{
   Manager Manager{
       get{return GameObject.Find("Manager").GetComponent<Manager>();}
   }
   public void OnMoveEnd(){
       Manager.PlayingManager.OnMoveEnd();
   }
}

アニメーションクリップの各ムーブの終わりにこの関数を呼び出すよう上記同様にアニメーションイベントを設定します。これの辺のくだりは終了検知しないなら不要です。

最後にUI要素のボタン側ですね。

各ボタンは自分が何番ボタンなのかをOnclickでUI要素についているスクリプトに通知します。

スクリプトでは何番ボタンがどの技なのかのリストをもっているので、それを元にマネージャに通知します。ここは別に番号通知だけしてマネージャでリスト照合してもいいとは思います。

マネージャはキャラモデルのアニメーションに対してトリガーをセットしてアニメーションを発動させます。

アニメーションが終わる際は、最後のところに設定したアニメーションイベントからモデルにアタッチしたスクリプトが呼ばれ、

スクリプトはマネージャに終了を通知します。

これで一連の流れの好きなところを関数取得できるとこまでできたんじゃないでしょうか?

一旦適当に技リストを設定して動かしてみましょう。

画像12

DJをHarukoに、ダンスモデルをUnityちゃんに変更してみました。

ボタンを押すと設定してあるwalkとjumpをしてくれました。ちなみにこれはHarukoに入ってるMotionなので、キャラ共通でモーションが使えることも確認できました。

ここまでやったことの構成をざっくりまとめるとこうです。

画像13

ユーザの入力を受け付けるUIとモデルの挙動をスクリプトでつなぐようなイメージでしょうか。

あとはモーションがダンスのモーションになって、バックで曲が流れれば、好きなボタンで好きなムーブをするダンスゲーの完成ですね。

残る鬼門はscoreですが、例えばアニメーションに対して適当な位置でムーブ特性情報をまとめておけば、イベント経由でスコアに反映とかもできそうかなって思ったり?

まぁそれはまた今度ででいいでしょう。今回はこれまで。

この記事が気に入ったらサポートをしてみませんか?