前回の更新で追加された機能の、読み込み時にランダムでポーズ(アニメーション)が変わるアセットバンドルの作成方法です。
事前準備
こちらの記事の事前準備をしておいてください。
ランダム要素があるアニメーションコントローラー作成
プロジェクトビュー上で右クリックして、作成→アニメーターコントローラーを選択し、アニメーターコントローラーを作成します。 アニメーションクリップをセットします。下のサンプル画像の場合、アニメーション数は3つなので、パラメーターに int 値の random3 を作成します。
移管は random3 の値が 0, 1, 2 で各アニメーションに移管するようにします。
(VR Dance Viewer は アニメーター再生時に int値の random(数字) のパラメーターがある場合、 0 から (数字)-1 の値の乱数を生成します)
あとは MakeABTool の .ab(AnimatorController) に作成したアニメーションコントローラーをセットして start を押せば完成です。
移管作成スクリプト
アニメーションクリップが多いと移管作成が面倒なので、移管と randomXX を自動生成するスクリプトを作りました。Editor フォルダの中にこのコードを放り込むと uniharu → VRDanceViewer → AnimTool → RandomAnimatorControllerTool の項目が出現します。
アニメーションクリップを配置したアニメーションコントローラー を選択した状態で、このスクリプトを実行すると移管とrandomXX が生成されます。
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
public class AnyStateRandomTransitions : MonoBehaviour
{
[MenuItem("uniharu/VRDanceViewer/AnimTool/RandomAnimatorControllerTool")]
public static void AddAnyStateTransitionsWithConditions()
{
var controller = Selection.activeObject as AnimatorController;
if (controller == null)
{
EditorUtility.DisplayDialog("Error", "AnimatorController が選択されていません", "OK");
return;
}
if (controller != null)
{
bool result = EditorUtility.DisplayDialog("Confirmation", "選択されている AnimatorController を書き換えます", "Yes","Cancel" );
if (!result)
{
return;
}
}
if (!HasParameter(controller, "random", AnimatorControllerParameterType.Int))
{
controller.AddParameter("random", AnimatorControllerParameterType.Int);
}
int rndno = 0;
foreach (var layer in controller.layers)
{
var stateMachine = layer.stateMachine;
int index = 0;
foreach (var child in stateMachine.states)
{
var state = child.state;
if (state == stateMachine.defaultState)
{
continue;
}
bool exists = false;
foreach (var transition in stateMachine.anyStateTransitions)
{
if (transition.destinationState == state)
{
exists = true;
break;
}
}
if (!exists)
{
var transition = stateMachine.AddAnyStateTransition(state);
transition.hasExitTime = false;
transition.hasFixedDuration = true;
transition.exitTime = 0f;
transition.duration = 0f;
transition.canTransitionToSelf = false;
transition.AddCondition(AnimatorConditionMode.Equals, index, "random");
}
index++;
rndno = index;
}
}
string newName = $"random{rndno}";
RenameParameter(controller , "random" , newName);
AssetDatabase.SaveAssets();
}
private static bool HasParameter(AnimatorController controller, string name, AnimatorControllerParameterType type)
{
foreach (var param in controller.parameters)
{
if (param.name == name && param.type == type)
return true;
}
return false;
}
public static void RenameParameter(AnimatorController controller, string oldName, string newName)
{
AnimatorControllerParameter oldParam = null;
foreach (var param in controller.parameters)
{
if (param.name == oldName)
{
oldParam = param;
break;
}
}
var newParam = new AnimatorControllerParameter
{
name = newName,
type = oldParam.type,
defaultInt = oldParam.defaultInt,
};
controller.AddParameter(newParam);
foreach (var layer in controller.layers)
{
foreach (var transition in layer.stateMachine.anyStateTransitions)
{
var conditions = transition.conditions;
for (int i = 0; i < conditions.Length; i++)
{
if (conditions[i].parameter == oldName)
{
var newCondition = conditions[i];
newCondition.parameter = newName;
conditions[i] = newCondition;
}
}
transition.conditions = conditions;
}
foreach (var state in layer.stateMachine.states)
{
foreach (var transition in state.state.transitions)
{
var conditions = transition.conditions;
for (int i = 0; i < conditions.Length; i++)
{
if (conditions[i].parameter == oldName)
{
var newCondition = conditions[i];
newCondition.parameter = newName;
conditions[i] = newCondition;
}
}
transition.conditions = conditions;
}
}
}
controller.RemoveParameter(oldParam);
}
}

0 件のコメント:
コメントを投稿