Needle Engineでのスクリプティング

Typescript、Javascript、C#の違い、類似点、重要な概念。

以下のガイドでは、C#、Javascript、Typescript間のいくつかの主な違いを強調しています。これは、Webエコシステムに慣れていない開発者にとって特に役立ちます。

Typescriptの書き方を学ぶための便利なリソースもいくつかあります。

C#、Javascript、またはTypescript間の主な違い

CSharpまたはC#は静的型付けされたコンパイル言語です。これは、コードが実行される前に、コンパイル(翻訳)されてILまたはCILという中間言語になる必要があることを意味します。この中間言語は、機械語に少し近いです。ここで理解すべき重要な点は、コードが分析され、コンパイラによって強制される特定のチェックとルールに合格しなければならないということです。C#言語のいずれかのルールに違反するコードを書いた場合、Unityでコンパイラエラーが発生し、アプリケーションは実行すら開始しません。コンパイラエラーがあると、Play-Modeに入ることはできません。

一方、Javascriptはランタイムで解釈されます。つまり、無効なコードを書いてエラーを引き起こす可能性がありますが、それらのエラーはプログラムが実行されるまで、またはエラーのある正確な行を実行しようとするまで表示されません。たとえば、var points = 100; points += "hello world";と書いても、ブラウザでコードを実行するまで誰も文句を言いません。

Typescriptは、Microsoftによって設計された言語で、javascriptにコンパイルされます。 これは、例えば型安全のような多くの機能を追加します。つまり、Typescriptでコードを書くとき、型を宣言することができ、その結果、例えば無効な代入を行ったり、予期しない型のメソッドを呼び出したりしようとしたときに、コンパイル時にエラーを得ることができます。以下でJavascriptとTypescriptにおける型について詳しく読んでください。

型 — あるいはその欠如

素のJavascriptには、(今日現在)の概念がありませんlet points = 100と宣言した変数が、アプリケーションの後半でまだ数値であるという保証はありません。つまり、Javascriptでは、後でコードでpoints = new Vector3(100, 0, 0);を代入することは完全に有効なコードです。あるいはpoints = nullpoints = myRandomObjectでも構いません。これがどういうことかお分かりでしょう。コードを書いている間はこれで全く問題ありませんが、後でpoints -= 1と書いたときに、コードが実行されるとひどくクラッシュする可能性があります。その時、アプリケーションが既に実行されているブラウザでエラーが発生します。

上述のように、Typescriptは型を定義するための構文を追加することで、その問題を修正するために作成されました。

Typescriptを書くとき、基本的にまだJavascriptを書いていることを理解することが重要です。そして、例えばエラーのある行の上に//@ts-ignoreを追加したり、すべての型をanyとして定義したりすることで、すべての型チェックと安全チェックを回避することは可能ですが、これは絶対にお勧めできません。型は、実際にエラーが発生する前にエラーを見つけるのを助けるために存在します。サーバーにウェブサイトをデプロイしてから、後でユーザーや訪問者から、実行中にアプリがクラッシュしたという報告を受けることは、決して望ましくないでしょう。

素のJavascriptには型が提供されていませんが、**JSDoc**を使用することで、javascriptの変数、クラス、メソッドに型アノテーションを追加することはできます。

変数

C#では、型を使用するか、varキーワードを使用して変数を記述します。 例えば、int points = 100;と書くか、 あるいはvarを使用してコンパイラに正しい型を推論させることができます:var points = 100

JavascriptまたはTypescriptでは、変数を宣言するための現代的なオプションが2つあります。 再代入する予定の変数にはletを使用します。例えばlet points = 100; 再代入できないようにしたい変数にはconstを使用します。例えばconst points = 100;

varに注意 Javascriptでもvarキーワードに出くわすかもしれませんが、その使用は推奨されておらず、現代的な代替手段はletです。var vs letについて詳しく学んでください。

ただし、constで宣言された変数でも、それが(例えば)カスタム型である場合は、値を代入することが可能であることに注意してください。以下の例を考えてみてください。

上記は完全に問題のないTypescriptコードです。なぜなら、myPosition自体を再代入しているのではなく、myPositionxメンバーだけを操作しているからです。一方、以下の例は許可されません。ランタイムエラーまたはtypescriptエラーが発生します。

型の使用またはインポート

Unityでは、通常、コードの先頭にusingステートメントを追加して、プロジェクトで参照されているアセンブリから特定のネームスペースをインポートします。あるいは、特定のケースでは、ネームスペースから名前付きの特定の型をインポートすることもあります。 以下の例を見てください。

これは、Typescriptでパッケージから特定の型をインポートする方法です。

特定のパッケージからすべての型をインポートして名前を付けることもできます。これは時々見かけるかもしれません。

プリミティブ型

Vector2, Vector3, Vector4... C#の経験があるなら、クラスと構造体の違いについてご存知かもしれません。クラスが参照型であるのに対し、構造体はカスタムの値型です。つまり、文脈によってはスタックに割り当てられ、メソッドに渡される際にはデフォルトでコピーが作成されます。 C#の以下の例を考えてみてください。

positionという名前のVector3でメソッドが呼び出されます。メソッド内で、渡されたベクトルpositionが変更され、xが42に設定されます。しかし、C#では、このメソッドに渡されている元のベクトル(2行目を参照)は変更されていません。xは引き続き0になります(4行目)。

Javascript/Typescriptでは事情が異なります。こちらにはカスタムの値型はありません。つまり、Needle Engineやthree.jsでベクトルに出くわした場合、常に参照型となります。 typescriptの以下の例を考えてみてください。

違いがわかりますか?ベクトルやすべてのカスタムオブジェクトは実際には参照型であるため、元のposition変数(3行目)を変更したことになり、xは今や42です。

これはメソッドだけでなく、変数を使用する際にも理解しておくことが重要です。 C#では、以下のコードはVector3の2つのインスタンスを生成し、一方を変更してももう一方には影響しません。

Typescriptで同じことを行うと、コピーは作成されず、代わりに同じmyVectorインスタンスへの参照が得られます。

ベクトル演算と演算子

C#では演算子オーバーロードを使用できますが、残念ながらJavascriptでは利用できません。これは、C#でVector3をこのように乗算できる一方で:

同じ結果を得るためには、Vector3型のメソッドを使用する必要があります(少しボイラープレートコードが増えます)。

等価性チェック

緩やかな比較と厳密な比較

C#では、2つの変数が同じかどうかをチェックしたい場合、次のように書くことができます。

Javascript/Typescriptでは、=====の間に違いがあります。===は型をより厳密にチェックします。

2番目の変数playerIsNullOrUndefined==を使用していることに気づくでしょう。これは緩やかな等価性チェックを行い、この場合、nullundefinedの両方がtrueになります。詳細については、こちらを参照してください。

イベント、バインディング、そしてthis

C#でイベントを購読(サブスクライブ)する場合、次のように行います。

TypescriptとJavascriptでは、メソッドをリストに追加する際、「thisをバインドする」必要があります。これは本質的に、thisを(通常は)現在のクラスインスタンスに明示的に設定するメソッドを作成することを意味します。これを実現する方法は2つあります。

ここではEventList型を使用していることに注意してください。これはNeedle Engineのイベントを宣言するための型です(EventListは、私たちのEditor統合と使用する際に、UnityEventまたはBlenderのイベントリストにも自動的に変換されます)。

これを行うための短く推奨される構文は、アロー関数を使用することです。

同じことを実現するための、より冗長な「古典的な」方法もあります。これは手動でthisをバインドすることです(そして、後でイベントリストから再び削除するために、メソッドを変数に保存します)。

次は何ですか?

このページはAIによって自動的に翻訳されました

Last updated