2013年10月28日月曜日

Blender:オブジェクト原点の移動と回転

MayaだとInsertキーを押してやるアレ。
Maxだと右のタブから選んでやるアレ。

Pivotと呼ばれる、オブジェクト自身の原点の変更方法。

・移動
3DViewのメニューから
Object>Transform
のOrigin to というところを使う
BlenderではOriginと言うみたいね。

・回転
これはかなり無理矢理
正式なやり方はわからない
現状はEdit Modeに切り替えてオブジェクト自身を回転させてOriginとずらしている

本当のやり方はどうなんだろう
Posted on 8:41 | Categories:

2013年9月20日金曜日

2013年9月16日月曜日

BlenderからUnityにオブジェクトを持ってくるとSmooth Shadeになってしまう問題

http://answers.unity3d.com/questions/294558/blender-normal-smoothing-import-problem.html

ここに回答があった。

モディファイアにエッジスプリットを入れる

以前から調べていてスプリットしちゃうと後々オブジェクトの編集が難しくなるんじゃないかと思ってたんだけど、モディファイアを使うなら問題なし。

めでたしめでたし。

2013年8月24日土曜日

回転の経験則

結局、回転について全然わからないので、
一度総当してみることにした。

プログラマが見たら大笑いだと思うが、仕方ない。
これがUnityプログラミング・ストロングスタイルだ。

やりたいことは。
1フレームにつき1度回して、90フレーム後に90度回転していること。

試した内容の詳細は後回しにして、結果を先に。
結局ちゃんと90度回転したのは以下。
obj.transform.rotation *=Quaternion.Euler(0, 1, 0);
obj.transform.rotation *=Quaternion.Euler(Vector3(0, 1, 0));
obj.transform.Rotate(0, 1, 0);
obj.transform.Rotate(Vector3(0, 1, 0));
obj.transform.eulerAngles +=Vector3(0, 1, 0);
obj.transform.eulerAngles.y +=1;

今回わかったこと。

・Quaternionを加えてゆこうと思ったら、掛けること(足せない)。
・RotateはQuaternionで指定しない。
・Vecter3(1, 1, 1)と(1, 1, 1)は別物
・Time.deltaTimeは「1フレーム」の事だと思ってたら何か少数値が入ってた。


以下が試したプログラム。
青いラインが成功。

function Update () {
if(round<90){
round++;
obj.transform.rotation +=(0, 1, 0);
obj.transform.rotation +=Vector3(0, 1, 0);
obj.transform.rotation +=Quaternion.Euler(0, 1, 0);
obj.transform.rotation *=Quaternion.Euler(0, 1, 0);
obj.transform.rotation +=Quaternion.Euler(Vector3(0, 1, 0));
obj.transform.rotation *=Quaternion.Euler(Vector3(0, 1, 0));
obj.transform.rotation +=(0, Time.deltaTime, 0);
obj.transform.rotation +=Vector3(0, Time.deltaTime, 0);
obj.transform.rotation *=Vector3(0, Time.deltaTime, 0);
obj.transform.rotation +=Vector3.up*Time.deltaTime;
obj.transform.rotation *=Vector3.up*Time.deltaTime;

obj.transform.rotation.y +=1;
obj.transform.rotation.y +=Time.deltaTime;
obj.transform.rotation.y +=Vector3.up*Time.deltaTime;

obj.transform.Rotate(0, 1, 0);
obj.transform.Rotate(Vector3(0, 1, 0));
obj.transform.Rotate(Quaternion.Euler(0, 1, 0));
obj.transform.Rotate(Quaternion.Euler(Vector3(0, 1, 0)))
obj.transform.Rotate(0, Time.deltaTime, 0);
obj.transform.Rotate(Vector3(0, Time.deltaTime, 0));
obj.transform.Rotate(Vector3.up*Time.deltaTime);
obj.transform.Rotate(Vector3.up, Time.deltaTime);

obj.transform.eulerAngles +=(0, 1, 0);
obj.transform.eulerAngles +=Vector3(0, 1, 0);
obj.transform.eulerAngles +=Quaternion.Euler(0, 1, 0);
obj.transform.eulerAngles *=Quaternion.Euler(0, 1, 0);
obj.transform.eulerAngles +=Quaternion.Euler(Vector3(0, 1, 0))
obj.transform.eulerAngles +=(0, Time.deltaTime, 0);
obj.transform.eulerAngles +=Vector3(0, Time.deltaTime, 0);
obj.transform.eulerAngles +=Vector3.up*Time.deltaTime;

obj.transform.eulerAngles.y +=1;
obj.transform.eulerAngles.y +=Time.deltaTime;
obj.transform.eulerAngles.y +=Vector3.up*Time.deltaTime;
}



ちなみに、何か別の方法なら回転しそうなのは以下。
y=1.756921まで回転してた。
obj.transform.Rotate(0, Time.deltaTime, 0);
obj.transform.Rotate(Vector3(0, Time.deltaTime, 0));
obj.transform.Rotate(Vector3.up*Time.deltaTime);
obj.transform.Rotate(Vector3.up, Time.deltaTime);
obj.transform.eulerAngles +=Vector3(0, Time.deltaTime, 0);
obj.transform.eulerAngles +=Vector3.up*Time.deltaTime;
obj.transform.eulerAngles.y +=Time.deltaTime;
これ、うまくゆかないのって、もしかしたら僕のTime.deltaTimeの理解が間違っているからかもね。

以上。

2013年8月21日水曜日

intをfloatで割るとint

いや、これ、本職のプログラマなら当然だろ!
って感じだと思うんだけど、身の程知らず&経験則だけでプログラム作ってると、こういう単純な計算は意外と疑わないんですよ。

今回は270/100.0が2.7にならなくて困った。

回転部分をやってたから、Quarternionがまーた悪さをしとるな!
って思ってたー!

これ、気付くのに3日かかった!

2013年7月24日水曜日

ビルトインぼやき

サイズの変更できないビルトイン配列ってのがありますね。

で、定義の仕方は、こう。
var hairetu = new int[10];
これで、int用の10列の配列ができるわけです。

ところが・・・・
var hairetu : int[];
こういう宣言も可能なわけですが・・・

これって長さ「0」のサイズ変更出来ない配列っていう意味なんじゃないんですか???

それ、意味無くないですか?

回転に続き、配列の挙動に右往左往な日々でございます。

2013年7月17日水曜日

AwakeがStartに負けた!

前提:
static varにドラッグしてGameIbjectを登録できなかった。
普通のvarに入れてから改めでstaticに代入してた。

こんな感じ。
どの関数にも入れてないから、Awakeで実行されるはずー。
static var num :int =8;
var objsTmp =new GameObject[num];
static var objs =new GameObject[num];
for (var l:int=0; l<num; l++){
objs[l] = objsTmp[l];
}

(ちなみに、staticの配列を定義する時に使っている"num"をstaticにしないで使うと、
上記"objsTmp"には使えるけれど、staticなobjsでは使えない!)


と、こ、ろ、が!

Startでこれを利用しようとしたら、何故かnullが帰ってくる。

Updateを使って代入タイミングをみると最初のフレームではまだnullのまま。
あれー?
Awake > Start > Update
の順で実行されるんじゃなかったっけ?
ちなみに、最初の1フレーム目だけnullで後は正常に代入されていた。


Updateでも間に合ってないって...

とりあえずStartを最初にyieldしたら読めた。
なんでこうなるのかわかんないけど、動くからいいかー。

追記=========
これは、間に合ってないんじゃなかった。

オブジェクトA・・・変数をAwakeで定義するスクリプトを保持
オブジェクトB・・・オブジェクトAの変数をStartで参照

という構成だったので、つまりはオブジェクトの表示タイミングが違ったために起こったわけです。
最初からシーンに表示していても、これは起こるので、現在は、オブジェクトAのAwake処理の最後に、終了フラグを仕込んで、オブジェクトBのスクリプトのStartはそちらのフラグを見て実行するように変更しています。

2013年7月15日月曜日

Unity:2次元配列

配列についてはいずれまとめて書きたいけど、今のところ困っていた二次元配列ができたのでメモ。

var test :int[,];
test = new int[10,10];
test[1,1]=2;
print(test[1,1]);


ちなみに、何に困っていたのかというと、二次元配列にGameObjectとbooleanを混ぜて入れようとしてた。
けどまあ、上記の書き方を見ればわかるけど、違う要素を一緒にはやっぱりできない。
GameObjectへの参照と、そのGameObjectの状態を一緒に格納しようと思ったんだけど・・・。
つまり、二次元配列って複数の配列を束ねるものだと思ってた

ちなみに、以下の記述方法だとダメだった。

var test = int[10,10];

2013年7月14日日曜日

Blenderはおいといて・・・

結局、ちょっとBlenderを勉強しながらやってると、プログラムが進まないので、Unityで仮組みしてしまうことにした。

しかし・・・・BlenderよりUnityの方がオブジェクトの配置とか楽なのはなんで・・・

Unity:マテリアルの色を変える

こんな感じ。
本当はマテリアル自体を変更したかったんだけど・・・。
怪我の功名ということです。

//マテリアルは後で直接指定する
var mat : Material;
var index : int = 0;

function Start ()
{
//とりあえず最初は青
//"=Color"でマテリアルのどのプロパティを変更するのか決める
//Color.blueでどの色にするか決める。この記述方法はラクチンでいい。
mat.SetColor("_Color", Color.blue);
}

//とりあえず、ボタンを押すと色が変わる。
function Update ()
{
    if (Input.GetMouseButtonDown(2))
    {
        index++;
        if (index > 1) index = 0;
        if (index == 1) mat.SetColor("_Color", Color.red);
        if (index == 0) mat.SetColor("_Color", Color.blue);
    }
}

2013年7月10日水曜日

Blender四苦八苦:スケーリング

BlenderのスケールがUnityに持ってくると消える!

例えばキューブを、スケールを使って棒にしたとすると、Unityではキューブに戻っちゃう。
棒を作りたければ、EditModeでVertexをいじらないきゃだめ!

まあ、何にせよスケーリングは色々と悪さをするから、全部1なのにこした事は無いんだけど・・・

Blender四苦八苦:モデルのスムージング

Blenderでやったオブジェクトのスムージングが
Unityに継承されない!

調べたところ・・・
http://forum.unity3d.com/threads/130542-Flat-Shading-in-Blender-Imported-Mesh

ダメみたい!

エッジをスプリットしろって・・・

BlenerのオブジェクトはUnityに持ってゆくと、全部スムージングがかかった状態になります。

BlenderのファイルをUnityで直接読む

http://d.hatena.ne.jp/tueda_wolf/touch/20120120/p1

UnityのAssetフォルダにブチ込めば読めるらしい。

...

読めました。
あっけなく。

テクスチャなんかは別途張り込まなければならないけど、UVは来てるから楽チン。

気がかりなのは、.blndファイルがマテリアルとかテクスチャを内臓してること。
ファイルが壊れたら一発アウト。
あと、容量的にも不利なんじゃないかなー。調べてないけど。

でも、とりあえずテンション上がった!
Blenderの扱いにはまだ心が折れがちだけど。

2013年7月8日月曜日

2013年7月7日日曜日

2013/7/7

大雑把に作りたいゲームの流れだけ考えた

でも

細かい部分のプログラムを書こうと思ったら

必要なオブジェクトを作らざるを得ない

けど自宅に使い慣れた3Dソフトが無い

というわけで

Blenderのチュートリアルをこなした

モデリングはひと通り
マテリアルを当てたところまで

次回

テクスチャ

アニメーション

2013年7月1日月曜日

Blenderチュートリアル開始

3DモデリングにはBlenderを使ってみることにしました。

Blenderはとりあえず、見た目がいい!



で、チュートリアルがあったので、開始しました。
http://www.blender3d.biz/index.html

んですが・・・
AutoDesk製の3Dソフトを使っていると、Maya/XSI/Maxそれぞれショートカットキーが違っていてイライラしていたものです。
しかし!Blenderのショートカットは違いすぎ!

あと、テンキーショートカット必須!

ノートPCで作業しているので、ビューの切り替えもままならないんですよ。
(ビューの切り替え系は全てテンキー使用)

あと、マウスの使い方変すぎ!

右クリックで選択?

はまだいいとして・・・

左クリックは謎の「3Dカーソル」とやらの移動。
なんだそれ!
答えはPivotが常に出ているという状態なんですがね。

先が思いやられますよ。

普段お高いソフトを使っていて、これからBlender触ってみようという人は、フリーソフトのヤンチャぶりに驚くといいと思いますよ。

---<追記>2013/7/7
あの変なセンターカーソルとやらをリセットするには、
Shift_C

2013年6月30日日曜日

Metasequoiaはあかん

Unity用にモデリングしようと思って、フリーのモデリングソフトを探して最初に見つかったのが、

Metasequoia

インストールして、起動。


・・・
仕事で、Maya > SI > Max > XSIと変遷して来ましたが・・・。
このUIはあかんやつだ!
無理無理。

というわけで、現在Blenderをダウンロード中。

2013年6月22日土曜日

Android端末(Nexus7)にビルドして出力してみる

どうやらUnityからAndroid端末への出力は簡単らしい

のでやってみる。
基本的なセットアップ方法は。
http://docs-jp.unity3d.com/Documentation/Manual/android-sdksetup.html

Android SDKをインストール

ここからダウンロード
http://developer.android.com/sdk/installing/index.html

手持ちのAndroid端末のOSバージョンを確認。
ダウンロードしたファイルを解凍してSDK Manager.exeを起動。
OSバージョンに合ったファイルを選択してインストール。

僕のは4.2.2だったからこんな感じ。
ちなみに、画像はインストール済みの図だから、右側の欄がInstaledになっている。
あと、インストール項目の自動判別が行われるようで、チェックしたものが全部入るわけではなさそう。

UnityにSDKのパスを通す

Edit > Preference > External Tool >Android SDK Location
に、SDKをインストールしたパスを入れる。
<任意のパス>\adt-bundle-windows-x86_64-20130522\sdk
こんな感じ?

UnityのBuild SettingをAndroidにする

何故か画面キャプチャできないので、文字で。

File > Build Setting
で開いたウインドウの下の方にあるAndroidというのを選択。

さあ動け!File > Build and Run
動かないです。

Couldn't Find Android Device

Android 端末を開発者モードにする

調べると、そういうことだそうです。
http://webhoric.com/android/how-to-nexus7-developer-options

開発者モードにしたぜ!
さあ動け!File > Build and Run
動かないです。

Android 端末のUSBドライバを入れる

調べるとそういうことだそうです。
http://blogs.yahoo.co.jp/momo_poem/67257950.html

Nexus7のドライバはここから。
http://www.asus.co.jp/Tablet/Nexus/Nexus_7/#download

インストールしたぜ!
さあ動け!File > Build and Run
動かないです。

adbで端末の接続を確認

調べると、どうもAndroid端末が接続されているかどうか調べるのに、adbというコマンドを使うようです。
http://note.chiebukuro.yahoo.co.jp/detail/n128056
Windowsコマンドプロンプトに以下のように打ち込めと。
adb devices
....コマンドとして認識していない・・・・。

http://wghost.org/it/android/android-adb-shell-usb/
ああ、さっきインストールしたAndroid SDKのplatform-toolsフォルダにパスを通せばいいのか!

...パスの通し方わかりません
http://blog.cnu.jp/2009/11/06/windows-7-path/

通った!adbと・・・動かない・・・

再起動したら動きました。
が・・・Nexus7は認識されていないご様子。

なんだなんだー、えーっと・・・
http://blog.livedoor.jp/moonlight_aska/archives/50743650.html

というわけでこの方法でadb認識しましました。
何でカメラなんだ!

期待しないで・・・!File > Build and Run
うううううう!動いた!
表示方向が縦横逆だけど動いた!
マウス用にしかプログラム書いてないのに、タッチで動いた!
うわああああい!

超カンタンだったね!

2013年6月20日木曜日

2013年6月19日水曜日

GameObject と gameObject

色んな説明の文章を読んでて、適当に流していたんだけれど、ずっとちょっとひっかかってた・・・。
GameObject と gameObject の違いって何??
スクリプト中で宣言した、全てのパブリック変数は、ゲームオブジェクトのインスペクタ上で編集可能、又は、リンク可能となります。スクリプトを記述する際、ゲームオブジェクトの全てのメンバにアクセスできます。ゲームオブジェクトのクラスメンバリストはここで確認できます。 コンポーネントがゲームオブジェクトに付加されていた場合、スクリプトからメンバ名を指定する事で、直接コンポーネントにアクセスできます。例えば、transformとタイプする事はgameObject.transformとタイプする事と同じです。 特にゲームオブジェクトへの参照を指定しなくても、コンパイラによってgameObjectを指定していると推測されます。
thisとタイプする事で、記述中のスクリプトコンポーネントにアクセスできます。this.gameObjectとタイプすると、そのスクリプトが付加されたゲームオブジェクトを参照します。単に、gameObjectとタイプしても、同様に参照できます。論理的にはthis.transformとtransformは同じ意味です。もし、ゲームオブジェクトのメンバに含まれないコンポーネントにアクセスする場合は、次のページで説明するgameObject.GetComponent()を使用しなければなりません。
参照:http://ws.cis.sojo-u.ac.jp/~izumi/Unity_Documentation_jp/Documentation/Manual/GameObjects.html

つまりどういうことかっていうと。
"Test"というオブジェクトにくっつけたスクリプトに以下のように記述します。
print(GameObject);
print(gameObject.transform);
print(transform);

★ちなみにGameObject.transformという書き方はエラーが出て実行できませんでした。
で、実行結果はというと・・・
UnityEngine.GameObject
Test (UnityEngine.Transform)
Test (UnityEngine.Transform)
GameObject
何か、もんやりと誰とは無しにGameObject・・・とデータの型をつぶやいている感じ。

gameObject
そのスクリプトが属しているオブジェクトに変換される

transform
これだけでも、そのスクリプトが属しているオブジェクトのtransformに変換される(便利機能ってとこ?)

-------------------------------------------------------------------------
ちなみに・・・以下のprint文の実行結果はというと。
//intはGameObject同様に型の結果だけが出ている感じ
print(int); ----> System.Int32

//これは実行エラー。んじゃあ、Transformって一体どんな時に使うんだ??
print(gameObject.Transform);

--------------------------------------------------------------------------
というわけで、この項目で結局わからんのでほっといてる事。
・GameObjectって型宣言以外でどう使うの?
PlayerScript.js内での記述の選択肢としては、3つあります。
(1) GameObject.Find("North").GetComponent(SomeScript);
(2) gameObject.Find("North").GetComponent(SomeScript);
(3) transform.Find("North").GetComponent(SomeScript);
結果、
(1)(2)ゲーム空間全体を検索してしまうようで、NorthBを指定したはずがNorthAが選択されてました。
(3)PlayerA、PlayerBの各々の子である、NorthA、NorthBを指定できました。
参照:http://blog.be-style.jpn.com/article/57118009.html 
このあたりも気になるところ

・Transformとtransformの違い・・・・

道のりは長い・・・




2013年6月16日日曜日

ぐるぐる回転させる時に困ったこと

ぐるぐる回転させようと思って下の様に書いたところ・・・
obj.transform.rotation.y += 10;

なぜかわからんけど(多分ジンバルの関係だと思う)、180度くらいの所でスピードが鈍って、更には停止してしまう。
調べて以下のように直したら回った。
obj.transform.Rotate(0, 10, 0);

多分、オイラーとクォータニオンの違いだと思うんだけど、よーわからん。

回転難しい

回転難しすぎるので、徐々にメモしつつ理解してゆこう。


回転には
・オイラー角
・クォータニオン
があるそうな。

というわけで、公式リファレンスを見てみるか。
回転を表現するやつら
transform.eulerAngles・・・・・オイラー角としての回転値
transform.rotation・・・・・・・ローカル座標での回転値
transform.Rotate・・・・・・・・オブジェクトを相対的に回転させます


んで、基本的には全部クォータニオンで内部的には処理されておる・・・と・・・

回転を相対的にアニメートさせたいなら、Rotateを使えと。
// ローカルX軸で1秒に1度回転
transform.Rotate(Time.deltaTime, 0, 0);
transform.Rotate(Vector3.right * Time.deltaTime);
transform.Rotate(Vector3.right, Time.deltaTime);
//ワールドで回したいならSpace.Worldを入れとく
transform.Rotate(Time.deltaTime, 0, 0, Space.World);


同じ事なのに3つも記述方法があるのかい!

とはいえRotationを使ってこんな風にしてもよい。
var yRotation : float = 5.0;
function Update () {
yRotation += Input.GetAxis("Horizontal");
transform.eulerAngles = Vector3(10, yRotation, 0);
}


面倒くさい感じはわかった。

角度の表し方
transform.rotation = Quaternion.identity;・・・・ワールド座標でリセット

これは便利機能?いつ使うんだろ。

これがムカつく・・・どう違うのさ・・・
var rotation = Quaternion.Euler(0, 30, 0);
var rotation = Quaternion.Euler(Vector3(0, 30, 0));


そもそも、Quaternion.Eulerっていう書き方がよくわからん・・・
クォータニオンをオイラーで表現するってこと?

って思ってたらEulerEuler.Anglesってのが・・・
それぞれ解説は
eulerAngles・・・・・回転のオイラー角を返す。
Euler・・・・・・・・オイラー角を設定します。オブジェクトを回転させるときに使います。
参照:http://docs-jp.unity3d.com/Documentation/ScriptReference/Quaternion.html

で、どういう風に使えるかというと・・・。
rotation.eulerAngles = Vector3(0, 30, 0);・・・こちらは変数にくっつけるやつ
var rotation = Quaternion.Euler(0, 30, 0);・・・でこちらは機能としてQuaternionにくっつけるやつ

この例だけではイマイチわからんな!

・・・あー・・・rotation.eulerAnglesってのはVariantsつまり変数ってことかー。
で、Quaternion.Eulerってのは関数なわけね。
rotation.eulerAngles = Vector3(0, 30, 0);
は、rotation.eulerAnglesという変数の中に角度を代入しておると。
var rotation = Quaternion.Euler(0, 30, 0);
こちらは、変数の中にQuaternion.Euler()関数を使って角度を代入しておると。

じゃあ、Quaternion.Eulerが吐き出す値はクォータニオンなの?オイラー角なの?
いや、待てよ・・・それは関係ないのか!
何気なく、「回転を表現する」って書いたけど、こいつらは・・・
transform.eulerAngles・・・・・変数
transform.rotation・・・・・・・変数
transform.Rotate・・・・・・・・関数

ってことなのか。やっとリファレンスが"Variables(変数)"と"Functions(関数)"に別れている意味がわかった・・・かも。
つまり、回転にRotateを使うってことは、それは関数の機能を使うってことで、rotationを使うと回転させる機能自体は自分で作らなきゃいけないってことかー。

あ、だから、Quaternion.Euler()っていう書き方は、Quaternionっていう「名前」の関数のEulerっていう機能を呼び出しているって考えればいいのか。
わかりやすいんだかわかりにくいんだか微妙だけど。


いや、つまり何が問題でこんなメモを作ったかというと・・・。

transform.rotation = Quaternion.AngleAxis( 130, Vector3(1, 0, 0));
print(transform.rotation);
print(transform.eulerAngles);

とした時に、以下の様な結果になるわけです。
(0.9, 0.0, 0.0, 0.4)
(50.0, 180.0, 180.0)

オイラーだと何故かYとZに180ずつ入ってしまうと。
かと言って、クォータニオンでは角度がわからん・・・。

で、何で角度を取りたいかというと、回転制限をかけたいんです。・・・・うーむ。どうしたものか・・・。 

<解決案1>角度の変化量を別の変数に入れとくか・・・ 

オブジェクトの取得

画面上にボタンがいっぱいあって、それぞれのボタンを押したら押したボタンが反応するようにしたい。
で、ボタンの動作は色々あるから、単純に一つのスクリプトで動きを管理するんじゃなくて、それぞれのオブジェクトにスクリプトを用意しておいて、オブジェクト自身に付けられたスクリプトを動かしたいんです。



じゃあPanelを親にすればいいじゃないかという話もありますが、何となくそうしたいのです。

・子の検索
自分の子から「Find」できるのが「FindChild」です。
GameObject retChild = gameobject.transform.FindChild("子の名前").gameObject;

・名前で検索 
unity 画面上(階層上)からgameobjectを取得するには「Find」を使います。
GameObject target = GameObject.Find("ゲームオブジェクト名");

・階層で検索 
以下のように階層で指定することもできます。
GameObject target = GameObject.Find("root/box/target1");


なんとなくですが、階層で検索するのが使いやすそうですね。できれば、正規表現での検索とかあると今後楽そうですが・・・。とりあえずはこれで。

<追記>----------------------------
スクリプトがくっついているオブジェクト自体の取得
this.gameObject

プログラム初心者がやってます

このブログは、自分のメモ用が主なので、説明不足だったり、情報が間違ったりする場合があるので、(まあ誰も見ないとは思いますが)注意が必要です。

よろしく。