始めに
ADXアンバサダーのこはとです!
CRI ADXを使っていて、音量やAISAC値を一定時間でゆっくり動かしたいな~という時ありませんか?
実はADXには独自のTween機能があり、これらを使うことで値の変化をより滑らかに行うことができます。
今回は、CRI ADXのTween機能の使い方と諸注意について解説します!
この記事は、CRIWAREが提供するサウンドミドルウェア「CRI ADX」の機能についての紹介をします。
本記事では、CRI ADX初心者の方でも触れやすいよう、簡単な内容で解説していきます。
CRI ADXについてはこちら
忙しい人向け
[SerializeField]
CriAtomSourceForAsset source;
void Start()
{
//Tweenの作成
CriAtomExTween tw = new CriAtomExTween( CriAtomExTween.ParameterType.Basic,(uint) CriAtomEx.Parameter.Pitch);
//Tweenの適用
source.player.AttachTween(tw);
//音声の再生
source.Play();
//Tweenを実行
tw.MoveTo(3, 90);
}
この例はピッチの操作ですが、例えば「(uint) CriAtomEx.Parameter.Pitch」の部分を「(uint) CriAtomEx.Parameter.Volume」のように変更すれば、ボリュームの操作ができます。
また、「CriAtomExTween.ParameterType.Basic」の部分を「CriAtomExTween.ParameterType.Aisac」に変えるとAisacの操作もできます。
Tweenとは何か
Tween(トゥイーン)は英語の「between(意味:間の)」に由来する用語で、ゲームエンジンに限らず、動画編集ソフトなどあらゆる分野の技術用語として用いられています。
機能としての具体的な定義はなく、環境によって様々な使用例がありますが、概ね「あるものを、ある場所へ徐々に動かす、またはアニメーションさせる機能」という認識で共通しています。
(例えば、UnityのAsset「DOTween」では、オブジェクトの座標と座標間をアニメーションして動かす、などの機能があります)
物体や値の動きを補完することで、演出や処理を少し凝った、よりリッチなものにすることができます。
CRI ADXにおけるTween
CRI ADXにもこのTweenが実装されており、ここでは音声の各パラメーターを、ある値から別の値に徐々に変更する機能として実装されています。
例えば…
- ゲームのカットシーンに入る際、BGMのボリュームを指定時間で徐々に下げる
- UIなどの演出に合わせて、SEを左右にパンする
- フィールド→洞窟のように、シチュエーションが変化した際、音声のリバーブを徐々に上げる
などの使い方ができます。
AtomCraftで専用にAISACを作らなくとも、コードのみで動的に効果を付与できる、というのも1つの特徴です。
実際に使ってみる
実際に使って機能を見ていきましょう!
今回は「ボタンを押すと、任意のTween効果がBGMに適用される」という機能で作成してみます。
実装へ入る前に、事前にAtomCraftでCueを準備しておきましょう。
今回はAtomCraftの操作は割愛しますが、BGMのような数分のCueが1つがあればOKです。
AtomCraftでのCueの作成方法はこちらからご確認ください。
使用手順と簡単なフローチャート
基本的には
Tweenを作成
↓
TweenをExPlayerにアタッチ
↓
Tweenを実行
の順で使用できます。
簡単にですが、以下が今回の実装のフローチャートです。
UnityProjectの設定
Unity側では、ADX関連の基本オブジェクト、AtomCraftで作成した音声のAtomSourceの他、サンプル用にDropDown、InputField、ButtonとTextを作成しておきましょう。
実装例
using UnityEngine;
using CriWare;
using CriWare.Assets;
using System.Collections.Generic;
using System;
using TMPro;
public class TweenSample : MonoBehaviour
{
//音声Source。~ForAssetと書いてありますが、CriAtomSourceでも可能です
[SerializeField]
CriAtomSourceForAsset source;
//[SerializeField]
//CriAtomSourceForAsset source;
CriAtomExTween tween;
CriAtomExPlayback exPlayback;
//UI関係
//ターゲットのパラメーター選択用ドロップダウン
[SerializeField]
TMP_Dropdown dropdown;
//値が変わるまでの時間
//(※時間はミリ秒なので注意!)
[SerializeField]
TMP_InputField inputField_Duration;
//目標の値
[SerializeField]
TMP_InputField inputField_Value;
//Tweenの現在値
[SerializeField]
TextMeshProUGUI valueText;
private void Awake()
{
//ドロップダウンの初期化
//CriAtomEx.Parameterの内容を表示できるようにする
if (dropdown != null)
{
string[] typeNames = Enum.GetNames(typeof(CriAtomEx.Parameter));
List<string> names = new List<string>(typeNames);
dropdown.ClearOptions();
dropdown.AddOptions(names);
}
}
void Start()
{
//音声の再生。
//Tween実行用にあらかじめexPlaybackを取得しておく
exPlayback = source.Play();
}
// Update is called once per frame
void Update()
{
//Tweenの実行中のみ、現在のTweenの値の動きを表示
if(tween != null)
{
if (tween.IsActive)
{
valueText.text = tween.Value.ToString("N2");
}
}
}
/// <summary>
/// 現在のUIの入力内容を元に、Tweenを実行します。
/// </summary>
public void StartTween()
{
//ドロップダウンの内容を取得し、Parameterの値に変換
CriAtomEx.Parameter param = (CriAtomEx.Parameter)Enum.Parse(typeof(CriAtomEx.Parameter), dropdown.options[dropdown.value].text);
Debug.Log($"param ={param} and get = {dropdown.options[dropdown.value].text}");
//すでに存在する場合、今動作しているものを破棄する
if (tween != null)
{
//実行停止
tween.Stop();
//TweenをDetach
source.player.DetachTween(tween);
//Detach状態を更新
source.player.Update(exPlayback);
////⚠DetachTweenした後、必ずUpdateを挟んでからDisposeさせる
tween.Dispose();
}
//Tweenを作成
tween = new CriAtomExTween(CriAtomExTween.ParameterType.Basic, (uint)param);
//Tweenを適用
source.player.AttachTween(tween);
//ExPlayerは再生中のため、Updateを実行
source.player.Update(exPlayback);
//入力した内容に値を変える(※Durationはミリ秒なので注意!1000→1秒)
if (ushort.TryParse(inputField_Duration.text,out ushort dur) && float.TryParse(inputField_Value.text, out float val))
{
//Tweenの実行
tween.MoveTo(dur, val);
}
}
}
各メソッドについての解説
CriAtomExTween(ParameterType type,uint targetId)
Tweenを作成します。引数に入れる内容によって操作するパラメーターが大きく変わりますのでご注意ください。
基本的にはCriAtomExTween(ParameterType type,uint targetId)の形式で入力するのがオススメです。
第1引数:パラーメーターのタイプ
Basic、またはAisacのどちらかが入力できます。ここに入力した値に応じて、第2引数の意味が変わります。
第2引数:操作するパラメーターの具体的なID
第1引数にBasicを設定した際は、Tweenは指定したIDのCriAtomEx.Parameterを操作対象にします。
また、第1引数にAisacを設定した場合は、AttachしたExPlayerの指定IDのAisac値を操作するようになります。
(↓CriAtomEx.Parameterについてのリファレンス)
CriAtomExTween tw;
tw = new CriAtomExTween( CriAtomExTween.ParameterType.Basic,0);
//→この場合は、CriAtomEx.Parameterの0番のパラメーター(=ボリューム)を操作します。
//tw = new CriAtomExTween( CriAtomExTween.ParameterType.Basic,(uint)CriAtomEx.Parameter.Volume);
//↑これと同義
tw = new CriAtomExTween( CriAtomExTween.ParameterType.Aisac,0);
//→この場合は、Aisacの0番の値を操作します。Aisacの内容はExPlayerに設定された内容に依存します。
なお、引数を入力しない場合は、Tweenはボリュームを操作するようになります。
tw = new CriAtomExTween();
//→何も引数に設定されていない場合、Tweenはボリュームを操作します。
//tw = new CriAtomExTween(CriAtomExTween.ParameterType.Basic, 0);
//↑これと同義
CriAtomExPlayer.AttachTween(Tween)
ExPlayerにTweenをAttachします。この時点ではTweenは再生されません。
ExPlayerの再生後にAttachした場合は、必ずExPlayerのUpdate(CriAtomExPlayer.Update())を行ってください。
CriAtomExPlayer.DetachTween(Tween)
TweenをExPlayerからDetach(切り離し)します。
再生中のExPlayerのTweenを削除したい場合(後述)や、複数のExPlayerを通してTweenを適用している場合の管理などの際にご利用ください。
また、DetachもAttachと同様、実行後に必ずExPlayerのUpdate(CriAtomExPlayer.Update())を行ってください。
CriAtomExTween.MoveTo(ushort durationMs,float value)
これを実行することで、Tweenの動作を実行します。
第1引数に指定した値(ミリ秒)の時間をかけて、対象パラメーターを第2引数の値に変更します。
例えば、対象パラメーターがPitchで、
tween.MoveTo(3500,1200);
と入力した場合、tweenは3.5秒かけてExPlayerのピッチを1200上昇させます。
ここで対象となるパラメーターは、CriAtomExTween()で作成した際に設定したパラメーターが対象となります。
CriAtomExTween.Stop()
Tweenの動作を停止します。
実行時、パラメーターの値はStopが実行されたタイミングの状態でとどまります。
一時停止とは異なるため、StopされたTweenの動きを再開することはできませんのでご注意ください。
同じTweenに再度MoveToを実行することで、停止したパラメーターから再度Tweenを実行することは可能です。
以上が基本的なTweenの使い方になります!
ButtonでStartTween()を実行できるように設定し、各UIをInspecterで参照させ、動作を見てみましょう。
DropDownでパラメーターを選択、InputFieldに秒数を入力、値を入力し、Buttonを押すとパラメーターが動作します。
Tweenを使用する上での注意
ここからは、Tweenを使用する上での注意したい点について解説します。
より複雑な活用ケースでの注意点になりますので、余裕がある方は御覧ください!
DisposeとDetachTweenについて(SDK v3.12.xx以前のみ)
CriAtomExTween.Dispose()では、Tweenそのものを破棄します。
任意のタイミングでTweenの削除を行いたい場合に使用することができますが、一度ExPlayerにAttachした後、ExPlayerの再生中にTweenをDisposeさせるとエラーが出力されます。
(※SDKバージョンがv3.12.xx以下の場合のみ)
必ずDetachTween→ExPlayerのUpdateを行った後にDisposeを行うようにしましょう。
(特にTweenの作成をローカル変数で行った場合は発生しやすいため、Tweenをグローバル変数で取得するのを推奨します)
なお、この不具合はSDKバージョンを3.13.00以降に更新することでも解消します。
更新後はバージョンアップ前のAcbデータは読み込めない場合がありますので、更新後にCueSheetの再ビルドを実行するようにしましょう。
CriAtomExTween tween;
//~~~~~
//NG
if (tween != null)
{
tween.Stop();
tween.Dispose();//TweenをAttachさせた後、ExPlayerからDetachせずにDisposeさせるとエラー
}
//OK
if (tween != null)
{
tween.Stop();
source.player.DetachTween(tween);
//⚠DetachTweenした後は、Disposeする前に必ずUpdateを挟む
source.player.Update(exPlayback);
//Detachが完了してからDispose
tween.Dispose();
}
1つのExPlayerに複数のTweenを使用する際の注意
Tweenは、1つのExPlayerに対して複数のTweenを適用、実行することができます。
ただし、適用するTweenのパラメーターが重複しているか否かで動作が異なります。
パラメーターが重複していない場合
→Tween毎に動作し、それぞれでExPlayerのパラメーターを変化させます。
パラメーターが重複している場合
→パラメーターによって挙動が異なります。詳細は割愛しますが、例えばVolumeの場合は、後入力が先入力の値に乗算されるなど、基本的には効果が同時に実行されるような挙動となります。
なお、複数のTweenを一斉にDetachしたい場合は、CriAtomExPlayer.DetachTweenAll()を実行すると、そのExPlayerのTweenを全てDettachすることができます。
Tweenが操作しているパラメーターの種類は外からは見えない点に注意
ExPlayerに適用したTweenは、ExPlayer側からはどのTweenが適用されているかを確認することはできません。
また、Tween自体も、作成後はそのTweenが何のパラメーターを操作しているかを確認することはできません。
そのため、もし後から「このTweenは何のパラメーターを操作しているのか」を確認するためには、Tweenの状態管理を行うための実装が別途必要です。
以下は、サンプルコードに「Tweenが作成する際、すでに同じターゲットパラメーターのものが適用されている場合は、それを使い回す」という機能を追加したサンプルです。
using UnityEngine;
using CriWare;
using CriWare.Assets;
using UnityEngine.UI;
using System.Collections.Generic;
using System;
using TMPro;
public class TweenSample_Advanced : MonoBehaviour
{
class TweenStruct
{
public CriAtomExTween tween { get; private set; }
public CriAtomExTween.ParameterType parameterType { get; private set; }
public CriAtomEx.Parameter targetParamater { get; set; }
public ushort targetDuration { get; private set; }
public float targetValue { get; private set; }
public TweenStruct(CriAtomExTween.ParameterType type, CriAtomEx.Parameter param)
{
parameterType = type;
targetParamater = param;
tween = new CriAtomExTween(type, (uint)param);
Debug.Log($"type = {type} + param = {param}");
}
public void SetAndPlay_MoveTo(ushort duration, float value)
{
if (tween.IsActive)
{
tween.Stop();
}
targetDuration = duration;
targetValue = value;
tween.MoveTo(targetDuration, targetValue);
}
public void SetAndPlay_MoveFrom(ushort duration, float value)
{
if (tween.IsActive)
{
tween.Stop();
}
targetDuration = duration;
targetValue = value;
tween.MoveFrom(targetDuration, targetValue);
}
}
[SerializeField]
CriAtomSourceForAsset source;
List<TweenStruct> tweenStrList = new List<TweenStruct>();
CriAtomExPlayback exPlayback;
TweenStruct currentStruct;
//UI関係
[SerializeField]
TMP_Dropdown dropdown;
//(※Durationはミリ秒なので注意!)
[SerializeField]
TMP_InputField inputField_Duration;
[SerializeField]
TMP_InputField inputField_Value;
[SerializeField]
TextMeshProUGUI valueText;
private void Awake()
{
//ドロップダウンを初期化→CriAtomEx.Parameterの内容を表示できるようにする
if (dropdown != null)
{
string[] typeNames = Enum.GetNames(typeof(CriAtomEx.Parameter));
List<string> names = new List<string>(typeNames);
dropdown.ClearOptions();
dropdown.AddOptions(names);
}
}
void Start()
{
//音声の再生。
//Tween実行用にあらかじめexPlaybackを取得しておく
exPlayback = source.Play();
////ExPlayerは再生中のため、Updateを実行
//source.player.Update(exPlayback);
}
// Update is called once per frame
void Update()
{
//Tweenの実行中のみ、現在のTweenの値の動きを表示
if (currentStruct != null)
{
if (currentStruct.tween.IsActive)
{
valueText.text = currentStruct.tween.Value.ToString("N2");
}
}
}
public void StartTween()
{
//ドロップダウンの内容を取得し、Parameterの値に変換
if (Enum.TryParse(typeof(CriAtomEx.Parameter), dropdown.options[dropdown.value].text, out var p))
{
CriAtomEx.Parameter param = (CriAtomEx.Parameter)p;
//Debug.Log($"param ={param} and get = {dropdown.options[dropdown.value].text}");
//入力した内容に値を変える(※Durationはミリ秒なので注意!)
if (ushort.TryParse(inputField_Duration.text, out ushort dur) && float.TryParse(inputField_Value.text, out float val))
{
TweenStruct twStr = null;
//Listの中身が存在する場合
if (tweenStrList.Count > 0)
{
//Listの中身を確認
for (int i = 0; i < tweenStrList.Count; i++)
{
//すでに同じターゲットパラメーターのものが存在する場合はそれを更新する
if (tweenStrList[i].targetParamater == param)
{
twStr = tweenStrList[i];
break;
}
}
//探して一致するパラメータータイプのものがない場合は、新しく作成してAdd。
if (twStr == null)
{
twStr = new TweenStruct(CriAtomExTween.ParameterType.Basic, param);
tweenStrList.Add(twStr);
source.player.AttachTween(twStr.tween);
//ExPlayerは再生中のため、Updateを実行
source.player.Update(exPlayback);
}
}
//Listが一個もない場合は新しく作成してAdd
else
{
twStr = new TweenStruct(CriAtomExTween.ParameterType.Basic, param);
tweenStrList.Add(twStr);
source.player.AttachTween(twStr.tween);
//ExPlayerは再生中のため、Updateを実行
source.player.Update(exPlayback);
}
currentStruct = twStr;
//Tweenの実行
twStr.SetAndPlay_MoveTo(dur, val);
}
}
}
}
なお、Tweenの現在のパラメーターは「CriAtomExTween.Value」で見ることができます。
(※Tweenの実行内容はGetParameterFloat32には更新されないためご注意ください)
Tweenの参照エラーの発生に注意!(SDK v3.12.xx以前のみ)

TweenをAttachした後、DetachせずにDisposeしたりするとエラーが出力されます。
この際、次以降に何度実行しても、このようなエラーが出力され続けてしまう場合があります。この場合は、UnityのProjectを閉じて、開き直すことで解決できます。
(※SDKバージョンがv3.12.xx以下の場合のみ)
終わり
以上となります!
最後までお読みいただきありがとうございました!
ややクセがある機能ではありますが、使いこなせると演出面でもグッとクオリティが上がると思います。
今回は説明しませんでしたが、Aisacと合わせることでもより効果がある機能ですので、是非色々試してみてください!
また、CRI ADXでは、公式のDiscordコミュニティも随時公開されています。
「こんなことはできる?」
「不具合が解消しない!」
「他の人がどんな使い方をしているのか知りたい!」
など、気になることや知りたいことを、開発スタッフに直接質問することもできます。
イベント情報等もこちらで告知しておりますので、ご興味のある方はぜひご参加ください!






