
Japanese: 
[MIKE] 皆さんこんにちは
今回のビデオでは Unity の
Data-Oriented Technology Stack
略して DOTS 実装の
概要を説明します
ここでは昔ながらのゲーム
『Pong』の実装を
取り上げます
このプロジェクトでは
Unity 2019.3.0f1 と
最新のエンティティや
新しい構文などを
使用しています
本題に入る前に Data-Oriented
Technology Stack の
ユースケースである『Pong』
について少し説明します
『Pong』はとてもシンプルで
DOTS の実装例としては
物足りないかもしれませんが
結果としては 興味深い
プロジェクトになりました
実行する構文や
素晴らしい処理を
紹介するだけでなく
新しい構文についても
非常にわかりやすく
学ぶことができます
私がこのゲームを作成し
プロジェクトに変換して
解説ビデオを作成しました
これがそのプロジェクトです
2D に見えますが実際は
3D オブジェクトです
2D ではなく 3D を使用したのは
DOTS Physics の実装である
新しい Unity Physics を
使用したかったからです

English: 
[MIKE] Hello everyone, 
and welcome to this video,
which is an overview
of the DOTS implementation,
or Data-Oriented
Technology Stack in Unity:
The implementation
of the classic game, Pong.
This project is using 
Unity 2019.3.0f1,
and the latest entities, and
the new syntax and stuff like that.
Now, before I get started it might 
be worth talking a little bit
about Pong as a use case for 
the Data-Oriented Technology Stack.
Pong is a very simple game;
it is really kind of overkill
to try to make
a DOTS implementation of it,
but it was sort of a fun project.
And really it just kind of shows
some of the syntax
and some of the cool things 
we could do,
and to learn some of the new syntax,
just a very simple thing.
And I was making this anyway, so
I figured I'd turn this into a project
and make the video about it.
Now, here in my project, it looks 2D,
however this is 
actually just 3D objects.
And I did 3D instead of 2D
because I wanted to utilize
the new Unity Physics, which is 
the DOTS Physics implementation.

Japanese: 
3D オブジェクトを使用することで
さらにシンプルになります
コライダーなどの要素を
追加するだけで
すぐにゲームを開始できます
ここでパッケージマネージャーに
移動すると
現在有効になっている
項目を確認できます
絶対に欠かせないのは
Entities です
使用しているバージョンを
ここで確認できます
これにより計算やジョブなど
さまざまなことを
実行できるようになります
Hybrid Renderer がないと
作成したエンティティが
レンダリングされず
表示されません
このプロジェクトでは
Unity Physics や
DOTS Physics などを使用します
すでにいくつかの要素が
ここに表示されています
壁が複数ありますがこれも
3D オブジェクトです
あちこちに移動させるための
パドルもいくつかあります
スフィアオブジェクトの
ボールもあります
ここにあるのは Game Manager
ゲームオブジェクトです
このクラスのほかに
MonoBehavior があり
ここにユニバーサル
またはグローバル変数
設定などの要素が
格納されます
プレイヤーのスコアの配列が
設定されているのがわかります
いくつかの UI 要素も
すでに設定されています

English: 
And so by having 3D objects,
it just makes it simpler.
I can just throw colliders
and stuff on there,
and we're off to the races.
Now, if I go up
to my Package Manager here,
we can take a look 
at what's currently enabled.
The things that I absolutely 
need is I need Entities,
and you can see the version
I'm using here.
That's going to give me bursts to 
mathematics, jobs and all that stuff.
I need the Hybrid Renderer,
or else the entities I create
will not be rendered, 
won't be visible.
And I am using Unity Physics...
or DOTS Physics or whatever...
here in my project.
Alright, so something's
already happened here.
So I've got some walls...
again 3D objects...
I have some paddles that we're 
going to be using to move around,
I have a ball 
which is just a sphere,
and I have this Game Manager 
GameObject which has this class on it,
this monobehavior, 
that's just going to store
some of my universal or global
variables, and settings, 
and stuff like that.
You can see I've got an array
for the player's scores,
and some UI stuff here,
and that's all kind 
of set up already.

Japanese: 
ゲームビューを
見てみましょう
すべてに unlit シェーダーを
適用しているため
このような見た目になります
これが作業開始前の
フレームワークです
では Game Manager を開き
すでに記述されているコードの
一部を確認します
残りのコードも
これから記述しますが
これは DOTS 専用ではなく
私が以前に作成したものです
この Game Manager は
シングルトンデザインの一種です
賛否両論ある方法であることは
理解していますが
私はこの手段が
気に入っています
ここでは パブリックの
GameObject プレハブを使用します
他にも複数の変数があり
左右移動の範囲を決める xBound
上下移動の範囲を決める yBound や
ボールの移動速度
ポイントが入ってから
ボールをリスポーンするまでの
待機時間を定義します
次は PlayerScores の設定です
プレイヤー 1 プレイヤー 2 と
するのではなく
配列にしました
今後複数のプレイヤーなどを
追加する可能性があるためです
そのため非常にシンプルです
プレイヤーのスコアの
UI テキストでも同様です

English: 
And if I look at the Game view,
I just sort of see this,
I put an unlit shader 
on everything,
and so it just kind 
of looks like this.
And this is the framework 
by which we're going
to go ahead and get started.
I'm going to go ahead 
and open my Game Manager,
and just take a look at some 
of the code that's already written.
I'll be writing the rest of the code,
but this isn't DOTS specific,
I just already had this written out.
And so this Game Manager
is a sort of singleton design,
and I know people
have mixed feelings about that,
but that's the way I like to do stuff.
And I'm going to have a public
GameObject Prefab here,
some variables to define my left
and right xBound and yBound,
how fast the ball will go,
how long do we wait to respawn
once someone scores a point.
And then we have the playerScores,
and I made this an array, instead 
of just doing player 1, player 2,
because maybe in the future
we'll add more than one player,
or whatever, so I just made it
so it's fairly simple there.
And the same for our UI Text
for the scores of the players.

Japanese: 
ここには Entity と
EntityManager の変数があります
これについては後ほど
関連が出てきたら説明します
いくつかの遅延は
定義済みです
このスクリプトでは
コルーチンを使用します
メモリを割り当てる新しい
WaitForSeconds を
毎回指定するのではなく
これらを事前に
定義しています
Awake 内にはシングルトン
パターン全体があります
ここでは別の
Game Manager が存在している
場合はそちらを実行して
こちらを削除するよう
指定しています
そうしないとこれはメインの
Game Manager になります
プレイヤーのスコアの配列を
初期化し
カウントダウンに対する遅延を
宣言して初期化した後
CountdownAndSpawnBall
コルーチンを実行します
ボールがゴールに入るたびに
呼び出される
パブリックメソッドも
ここにあります
プレイヤーのスコアを更新した後
UI を更新すると
CountdownAndSpawnBall が
再度呼び出されます
このコルーチン内では基本的に
カウントダウンするだけです
Get Ready 3 2 1 の後
SpawnBall を呼び出します

English: 
I have some variables here,
an Entity and an EntityManager...
we'll talk about this
once they become relevant.
And then I just predefined 
some delays.
This script is going 
to use a coroutine,
and instead of saying a new
WaitForSeconds each time,
which allocates memory.
I'm just going to define 
these ahead of time.
Here inside my Awake
is the whole singleton pattern.
I'm going to say,
"Hey, if there already is
another Game Manager in existence,
then just go ahead 
and delete this one," otherwise
this becomes
the main Game Manager.
We initialize 
our player score array,
we declare and initialize 
our delays for our countdown,
and then we start this coroutine
CountdownAndSpawnBall.
I also have a public method here
that's going to be called
whenever the ball
ends up in a goal,
that's going to update
whatever players score,
and then update the UI, 
and again CountdownAndSpawnBall.
Inside this coroutine, we're 
basically just going to countdown,
get ready, 3, 2, 1, 
and then we SpawnBall.

Japanese: 
ここにはまだ何もないので
後でそのコードを記述します
Game Manager は
このように非常にシンプルです
特に複雑なことはありません
必要なのは対象のコードを
記述しておくことだけです
ではプロジェクトに
戻りましょう
最初は最も簡単な
ことから始めましょう
上と下の壁を選択して
エンティティに変換し
物理演算で
処理できるようにします
ここでは物理演算要素を
追加する必要はありません
実際には DOTS Physics の
要素のことです
物理演算の形状や本体などを
追加する必要はありません
実際に何か行われるかと言えば
これらが自動的に追加されます
ここに「Box Collider」
ここに「Rigidbody」が
設定されているためこれらを
エンティティに変換すると
対応する DOTS 要素に
自動的に変換されます
次に Bouncy Physics Material を
ここにドロップします
組み込みの物理演算を
使用するためです
ボールを跳ね返らせることが
目的です
ここでそれが行われるように
いずれかのパドルに
ボールがヒットするようにします
次に「Add Component」 >

English: 
And right now, nothing is in here yet,
we'll write that code later.
So Game Manager, 
pretty straightforward,
nothing too spectacular there,
mostly just wanted
to have that code already written.
Alright, so let's go back
to our project here.
The first thing I'm going
to do is the easiest,
I'm going to go ahead and take 
my upper and lower walls,
and I'm going to turn these 
into entities
so that they can work with Physics.
Now, I don't need to add
Physics stuff here.
As a matter of fact...
sorry, DOTS Physics stuff here...
I don't need to add a Physics shape
and a Physics body, and stuff.
Actually, what's going to happen 
is those will be
added automatically because 
I have a Box Collider here,
and a Rigidbody here
so when I convert these to entities,
they will automatically be converted
to the DOTS equivalent for me.
One thing I am going to do here,
I am going to go ahead
and just drop 
a Bouncy Physics Material on here,
because we're going to be using
the built-in Physics.
I'm going to want 
the ball to bounce around.
I'm going to have this hit
one of my paddles
so just want to have that here.
Then what I'm going 
to do is I'm just going

Japanese: 
「DOTS」 > 「Convert to Entity」
を選択します
これで実行時に壁が
自動的にエンティティに
変換されます
再生ボタンをクリックしてみます
新しいエンティティや要素を
いくつか作成すると初回は
ここで数秒かかる
場合があります
再生ボタンをクリックすると
上の壁が消えて
下の壁は残っていますが上の壁は
エンティティに変換されました
「Window」 > 「Analysis」 >
「Entity Debugger」を選択して
Entity Debugger に移動すると
上の壁があることを確認できます
ご覧のとおり
変換されて自動的に
物理演算要素が
設定されています
ここで上の壁に戻ると
「Convert To Entity」が
あります
プレハブなので
適用するだけです
下の壁も同様です
続いてパドルです
パドルにもいくつか
処理が必要です
まず「Box Collider」
「Bouncy」マテリアル
「Rigidbody」があります
ここに「Convert To Entity」を追加し
これらもエンティティに
変換されるようにします
ただしパドルは動かす必要も
制御する必要もあります
関連するゲームプレイがあります

English: 
to go to Add Component > DOTS,
and then Convert to Entity.
And now these walls will be 
converted to entities automatically
when I run this.
So if I were to, say, hit Play...
The first time once we create
some new entities and stuff,
it can take a couple 
of seconds there.
I hit Play and my upper wall is gone;
my lower wall's still here,
but my upper one
has been converted to an entity.
If I go to my Entity Debugger,
which I can open by going to
Window > Analysis > Entity Debugger,
I can see there is my upper wall.
There you go.
It's been converted for me,
and it has all the Physics stuff
automatically.
So I'm going to go back
to my upper wall here,
which has this Convert To Entity,
and since it's a prefab,
I'm just going to apply that,
so my lower wall has it as well.
Now, for paddles. Paddles are 
going to need a couple things.
So first off,
they have their Box Collider,
Bouncy material, Rigidbody.
I am going to add
a Convert To Entity on there,
so they'll be converted
to entities as well.
But now we need to move them,
we need to control them.
There's game play involved.

Japanese: 
そこでいくつか要素を
作成する必要があります
まずパドルは動くように
しなければなりません
つまりプレイヤーからの入力を
読み取る必要があります
パドルが認識する入力内容を
定義する必要があります
そのためキーボードのどのキーを
認識するかを示す
データが必要です
さらにパドルを動かすための
システムが必要です
データも定義する必要があります
入力内容に基づいて
どのように動かして何を実行すると
結果はどうなるでしょうか
いくつかの設定が必要です
ではこのコードを
記述してみましょう
「Scripts」フォルダーの
「Data Components」フォルダーに
いくつかスクリプトがあります
現時点ではすべて空です
これらは作成しただけなので
作成方法の
説明は省略します
まず最初に
「PaddleInputData」を開きます
これは各パドルが認識する
キー操作を定義する
データになります
またパドルをプレイヤーなどに
見立てることもできます
この設定方法は
非常にシンプルになります
2 人のプレイヤーで同じ
キーボードを使用することにします

English: 
And so I need 
to create a few things.
So first off, 
my paddles need to move,
which means they need
to read input from the player.
My paddles need to define
what input they care about.
So I need some data to say,
hey, which keys on the keyboard
am I looking for?
Furthermore, I need a system
to move my paddles,
and I need some data to define,
okay, well based on my input,
how am I moving? What am I doing?
What are the results of this?
So just a few things there.
So let's go ahead 
and write this code.
So in my Scripts folder,
I have a Data Components folder,
and I've got some scripts in here.
These are all empty right now.
I just created them so you don't have
to watch me create those,
and so the first thing 
I'm going to do is
I'm going to go 
to my PaddleInputData.
This is going to be the data 
that defines what keystrokes
each paddle cares about.
Or you could think of a paddle
as a player, or whatever.
So the way I want to set this up
is this is going to be very simple.
Two players are going to play
using the same keyboard.

Japanese: 
たとえば W キーと S キーで
左側のプレイヤー
上矢印キーと下矢印キーで
右側のプレイヤーを動かすので
非常にシンプルなままです
『Pong』の基本的なゲーム操作です
重要な設定情報を
格納するデータ構造を
作成します
それからキーボードの音が
うるさくて申し訳ありません
ヘッドフォンをご利用の方は音量を
下げた方がよいかもしれません
メカニカルキーボードを
使用しているためです
いつもキーを強くたたいてコードを
記述するのが好きなので
音がとてもうるさくなります
まず「public Struct」と書き
「PaddleInputData」と続けます
これが重要なデータです
IComponentData 型を指定します
こんな感じです
IComponentData を
使用しているのは
先頭で Unity.Entities を
使用しているからです
ここで注意すべき点は何でしょうか
ここでは 2 つの重要な
コードに注意します
「public KeyCode」と書いて
upKey を指定します
その後「public KeyCode」と書くと
自動的に構成されるため
downKey を指定します
できました
ではこの使い方を説明します
オーサリングスクリプトを
作成します

English: 
So let's say the W and S key
moves my left-hand player,
and the Up and Down arrows
move my right-hand player,
keeping it very simple here.
So just a basic game of Pong.
So I'm going to create a data struct
that's going to store
that configuration information
that I care about.
And I do apologize,
I have a very loud keyboard,
so if you're wearing headphones,
you may want to turn it down,
but I'm using 
a mechanical keyboard...
I always like my code
to be strongly typed,
so I use a very loud keyboard.
So I'm going to say public struct,
then I'm going 
to say PaddleInputData...
this is the data I care about...
and this is going to be
a type IComponentData.
There we go.
And if you're curious
how I have IComponentData,
it's because I'm using Unity.Entities
up top here.
And so what do I care about here?
Well, I'm going to care
about two key codes.
I'm going to say public KeyCode
and I'm going to have an upKey,
and then I'm going to have
a public KeyCode...
framed it for me automatically...
downKey. There we go.
Now, how do I use this?
So I could create 
an authoring script,

English: 
basically it's a MonoBehaviour that's
going to, at runtime or whatever, say,
"Oh, this is being converted,
let me, through a code,
add these components
and configuration data or whatever."
Or I can have Unity 
generate one for me.
So I'm going to use 
this new attribute...
this is some new syntax,
GenerateAuthoringComponent...
and now back in Unity,
if I click on my paddle,
once this compiles...
right there,
I'm going to go ahead and just drag
this PaddleInputData on here,
and we can see,
alright, these are our keys.
And I'll fill these out 
in a second here.
The next thing is, alright,
so this is the input data,
but once we read the input,
we need to give 
this paddle some data
that's going 
to define how it moves...
what does that input translate to?
So I'm going to come here to this
PaddleMovementData,
and I'm going to do the same here.
So I'm just going to go ahead
and create a public struct

Japanese: 
基本的には MonoBehaviour で
実行時などには
「これが変換されて
コードを利用すると
これらのコンポーネントや
設定データなどを
追加できるようになります」
また Unity に自動生成
させることもできます
この新しい属性を
使用します
これは新しい構文
GenerateAuthoringComponent です
Unity に戻ります
パドルをクリックすると
コンパイルされます
できました
続いてこの PaddleInputData を
こちらにドラッグするだけです
ご覧のとおり
これらはキーです
これらの入力は
すぐに終わります
次に進みます
これが入力データですが
入力を読み取ったら
動き方を定義する
データをパドルに
渡す必要があります
この入力は
何に変換されるのでしょうか
この PaddleMovementData を
こちらで開き
同じ処理を行います
「public struct」と書いて

Japanese: 
PaddleMovementData という
名前にしましょう
これは IComponentData を
継承します
続いて「public int direction」と書きます
こんな感じです
方向は上でしょうか
下でしょうか
パドルをどの方向に
動かせばよいでしょうか
さらに「public float speed」と書きます
パドルの移動速度を指定します
汎用プロパティーではなく
このように記述することで
パドルの移動速度を
変化させることができます
パワーアップを追加する
場合などに利用できます
これで少し自由度が
高まります
ここでも再度
GenerateAuthoringComponent を
使用します
では Unity に戻りましょう
2 種類のデータを
定義したので
パドルに戻ります
PaddleMovementData を
こちらにドラッグします
間違えました
こんな感じに
ドラッグするだけです
まずは「Direction」を「0」
「Speed」を「4」にします
これらのフィールドと
すべての要素が
オーサリングコンポーネントに
自動作成される仕組みを考慮し

English: 
that I'm going to call
PaddleMovementData,
like that, and it's going to be
an IComponentData.
And I'm going to say
public int direction.
I don't know why 
they didn't indent--there we go.
So am I going up,
or am I going down?
What direction is 
this paddle moving?
I'm also going to say,
public float speed...
how fast does my paddle move.
Alright, by having it like this,
instead of just 
some universal property,
paddles can move at different speeds,
if you ever wanted
to add power-ups, or whatever.
So it just gives us
a little bit of freedom there.
And again, I'm going to
GenerateAuthoringComponent 
for me here.
Alright, so I'm going
to come back to Unity,
and now that we've defined
those two pieces of data,
I'm going to go back to my paddle,
and I am just going to drag
my PaddleMovementData on here.
Oops, looks like I missed.
There we go, I'll just drag it
down there, that works.
So direction will be 0 
to start with, speed will be 4.
I like how it automatically
creates these fields
and everything
in the authoring component so

Japanese: 
パドルの移動速度は
最初は 4 にします
Paddle 0 は左側の
プレイヤーなので
W キーと S キーを使って
動かせるように
指定します
ここの下矢印を
クリックしてスクロールします
W を選択します
「Down key」には S を選択します
もっと簡単な方法も
あるかもしれません
ありました
これらはプレハブなので
この変更内容を
適用するだけです
さらに Paddle 1 でも
同様です
ただし Paddle 1 では
「W」と「S」ではなく
「Up Arrow」と「Down Arrow」を
選択します
できました
ここで再生ボタンをクリックすると
これらのパドルがエンティティに
変換されますが動くことはなく
何も起こりません
まだデータに対するロジックを
定義していないからです
この時点ではただのデータなので
このデータを処理するための
システムが必要です
何が必要かと言うと
2 つのシステムが必要です
1 つは入力内容を
読み取って

English: 
my paddle's movement speed
of 4 to start with.
So this is my Paddle 0...
my left-hand player...
so I'm going to say
that they are going to move
with the W and S keys.
So I just have to click 
this Down Arrow as these scroll past.
So there's W, and then
for my Down Key, I go to S.
There is probably a faster way
to do this, but whatever.
There it is. Okay, cool.
Now, since these are prefab,
I'm just going to go ahead
and apply those changes.
And now on Paddle 1, 
I have all these,
but Paddle 1 is not going 
to be looking for W and S,
Paddle 1 is going to be using
the Up Arrow and the Down Arrow.
Awesome.
Now, if I hit Play, these paddles
will be converted to entities,
but they're not going to move,
nothing's going to happen,
because I have not yet defined
any logic to my data.
It's just data at this point,
and I need systems
to do something with that data.
So what do I need?
Well, I need two systems.
One system is going 
to read my inputs,

Japanese: 
動きに関する情報に
変換するシステムです
もう 1 つは実際にパドルを
動かすシステムです
それではコードを見てみましょう
「Systems」フォルダーの
「PlayerInputSystem」を開きます
こちらに表示されます
ここでは処理方法を
指定します
まず最初に
「public class」と書き
さらに「PlayerInputSystem」と
続けます
「JobComponentSystem」型を
指定します
DOTS のコードの記述に
慣れている方なら
コンポーネントシステムと
ジョブコンポーネントシステムの
違いやどちらを記述すればよいかは
わかると思います
新しい構文では
これが簡略化されています
ワーカースレッドを
使用しているか
メインスレッドのコードなどを
記述しているかに関係なく
「JobComponentSystem」と
記述するだけです
メインスレッドのコンポーネント
システムやワーカースレッドの
ジョブコンポーネントシステムを
指定する必要はなくなります
このように簡略化されました

English: 
and convert that
to some movement information.
And then another system
is actually going to move them.
So I'm going to go over here
to my code, to my Systems,
and I have this PlayerInputSystem.
I'm going to open this up here.
And here is where I'm going 
to specify what do we do with this.
So I'm going to start 
by saying public class,
and I'm going to say 
PlayerInputSystem.
Alright, and this is going to be 
a type JobComponentSystem.
Now, if you're familiar
with writing any DOTS code,
you might be familiar
with component systems
versus job component systems,
and how you might write 
either of those.
So with the new syntax,
it's kind of been simplified.
So now, whether or not
you're using worker threads,
or you're writing code
for the main thread, or whatever,
you could just say 
JobComponentSystem.
You no longer have to say
component system for main thread,
and job component system
for worker threads, whatever.
So it's just been simplified there.

Japanese: 
ここで右クリックして
この抽象クラスの
実装を
指定します
OnUpdate のコードが
こちらに表示されます
ここで例外をスローするのは
避けたいので
これは削除します
次に記述するのは
「Entities.ForEach」です
以前まではコンポーネント
システム専用の構文でしたが
コンポーネントシステムでも
使用できるようになりました
シングルスレッドにも
マルチスレッドにも対応しており
ここで少し説明します
「ForEach」と記述したら
この丸かっこの中にラムダ式を
作成する必要があります
つまり基本的には
この丸かっこの中に
パラメーターのリストを
さらに丸かっこで囲んで
指定したら等号に続き
このような矢印を
追加します
その後何らかのメソッドを
定義します
最終的にはこのような
構文になります
では実際に記述してみましょう
通常私はこのように
コードを記述します

English: 
And I'm going to Right Click,
and I'm just going to say,
"Hey, you know what,
implement this abstract class for me,"
which is going to give me
my OnUpdate code here.
And I don't want to
throw an exception there,
so I'm going to delete that.
And so now what I'm going 
to say is Entities.ForEach.
This used to be
component system-only syntax,
but now we can use 
that with job component systems
for a single thread 
or multithreaded,
and I'll show you here, 
how, momentarily.
And so I'm going to say ForEach,
and now inside these parentheses,
we need to create a lambda expression.
So basically what that means
is in between these parentheses,
we are going to have 
a list of parameters
inside some parentheses,
and then an equal sign,
and then an arrow like this,
and then we're going
to define some method.
That's ultimately 
this sort of syntax.
Now, I like to write that like this,
so I'll generally write my code,
it looks like this.

English: 
That's just how
I like to look at it there.
So I put my parameters in here,
and then what I do
with those parameters inside here.
So what parameters do I need?
Well, I need a PaddleMovementData,
which I'm going to call moveData,
and I need PaddleInputData,
which I'm going to call inputData.
There we go.
And then I'm going 
to do something here.
Now, this in and of itself
isn't quite right
because I need to tell the system
am I manipulating this data,
or am I only reading this data,
which is important because
if Unity's trying 
to schedule other jobs,
trying to line up
the correct order to do things,
it needs to know if you're not going
to be writing to some data,
you're only going to read it,
so that it can allow multiple things
to access it at the same time.
That's all reading it, or whatever,
so that you can make 
more efficient code.
So moveData, 
we're going to write to.
So this PlayerInputSystem
is going to read from our inputData,

Japanese: 
これはあくまでも
私の方法です
パラメーターはここに記述し
その処理方法は
この中に記述します
必要なパラメーターは
PaddleMovementData です
ここでは moveData という名前にします
PaddleInputData も必要です
これは inputData という名前にします
できました
では次に
進みましょう
これ自体は
最善ではありません
このデータを操作するのか
読み取るだけなのかを
システムに指定する
必要があるからです
これは重要です
なぜなら Unity は他のジョブを
スケジュールしたり
適切な処理順を
決めたりする際に
複数の処理で同時に
データにアクセスできるように
目的がデータの書き込みではなく
読み取りのみであることを
認識する必要があるからです
ここでは読み取りのみなので
より効率的なコードを
記述できます
そのため moveData は
書き込み先になります
この PlayerInputSystem は
inputData からデータを

English: 
and write to our moveData,
but it's not going 
to write to inputData.
So since we're writing to moveData,
I'm going to say ref--reference...
PaddleMovement moveData.
Since I only read-only access
to my PaddleInputData,
I'm going to say in.
So there you go, ref for writing to,
in for reading from.
Also, all of our ref variables,
need to come first in our list,
and then our in variables 
come second.
So I couldn't do in and then ref,
I have to have all my refs,
and then all my ins.
There we go.
So inside here, what am I doing?
So I'm going to say
moveData.direction = 0.
Basically just clear out
any remaining direction.
And then I want it to be
a positive 1, if I'm going up,
and a negative 1, if I'm going down.
So I'll say moveData.direction...
it helps if I spell it right-- +=
and then I'm going 
to say Input.GetKey,
and I'm basically going to do
a condensed if statement...

Japanese: 
読み取り moveData に
書き込みますが inputData には
書き込みません
moveData に書き込むので
「ref PaddleMovementData
moveData」と記述します
PaddleInputData は
読み取り専用アクセスなので
「in」と記述します
「ref」は書き込み先
「in」は読み取り元を表します
さらにすべての ref 変数を
リストで先に記述してから
in 変数を指定する
必要があります
in の後に ref は指定できません
必ずすべての ref が
in の前に来るようにします
できました
この中では何を実行しますか
次のように記述します
「moveData.direction = 0」
方向のデータが残らないよう
基本的に消去するようにします
上に動かす
場合は 1
下に動かす場合は -1 にします
「moveData.direction」と記述し
「+=」と正しく入力したら
「Input.GetKey」と続けます
基本的には短縮形の
if ステートメントを使用します

Japanese: 
三項演算子を使用します
tertiary ではなく
3 を意味する
ternary です
「inputData.upKey」と記述します
続いて疑問符を入力します
このキーの処理方法を指定します
押した場合は
値 1 を追加し
押さなかった場合は値 0 を
追加することになります
つまり upKey を押さなければ
方向は 0 のままになり
押した場合は
1 になります
この行をコピーして
貼り付けます
下に動かす場合は
「-= Input.GetKey(inputData.downKey)」
と記述します
できました
downKey の処理方法は
押した場合は値 1
押さなかった場合は 0 になります
できました
ここで必要な処理は
以上です
ここで JobHandle を
返す必要があるので
「return inputDeps」と
入力します
ではここで何点か
チェックしましょう

English: 
a ternary operator,
I believe it's called...
not tertiary, 
that means three--ternary.
So I'm going to say inputData.upKey.
And then I'm going 
to say question mark.
So am I pressing this key, question.
If I am, then I'm going 
to add a value of 1,
if I'm not, I'm going 
to add a value of 0.
So if I'm not pressing the Up Key,
my direction will remain 0,
and if I am, 
my direction will become 1.
And I'm just going to copy this line,
I'm going to paste it.
For moving down, I'm going to say
-= inputData.downKey.
There we go.
So am I pressing the Down Key?
If I am, a value of 1,
otherwise a value of 0.
There we go.
So that's all we really need 
to do there.
Now, this needs us 
to return a JobHandle,
so I'm just going to say
return input Dependencies.
So we're just going 
to pass it through.

Japanese: 
まずこの構文が機能することを
明確にします
これは最善の構文ではありません
理由は後で説明します
2 点目に実際には
まだ実行されないことです
これは構文が変更されたことが
原因です
以前はこれで
十分でした
これが新しい構文で現在
注意すべき点です
このように「Entities.ForEach」と
記述しても
まったく動作しません
メインスレッドで実行するか
Job System で
スケジュールを設定して
ワーカースレッドで実行するかを
指定する必要があります
そのためスケジュールを
設定する場合やワーカースレッドで
マルチスレッド実行する場合は
「.Schedule」と記述して
「inputDeps」を渡します
ただしこれには
メインスレッドの要素が必要です
Input クラスへのアクセスのため
メインスレッドに置く必要があります
ワーカースレッド外部の要素に
アクセスするからです
ここで「.Run」と記述し
これをメインスレッドで実行するよう
指定します

English: 
Now, one, I want to make it clear
that this syntax works...
it's not the greatest syntax,
and I'll talk about why.
And, two, this isn't actually
going to run yet
because of the way 
the syntax has changed.
This used to be enough
and that was that.
So this is kind of a gotcha 
right now with the new syntax.
So saying Entities.ForEach,
just like this,
isn't quite going to work.
We need to tell it, do we want 
this to run on the main thread,
or do we want to schedule 
this with our Job System
to run on worker threads
so if we want to schedule it,
if we want it to run multithreaded
on worker threads,
we would say .Schedule and we pass in
maybe our input dependencies.
However, this needs 
main thread stuff.
This is accessing the Input class
so it needs to be on the main thread
because it's accessing things that 
exist outside of our worker threads.
So I'm going to instead say .Run
and .Run is going to say,
okay, run this on the main thread.

English: 
Now, since this is running
on the main thread,
the way I'm handling my reading 
and job input dependencies
and returning job input 
dependencies isn't quite right
because the next system
in the chain is going to say...
What happened in the previous chain?
Am I waiting for anything?
Is there any asynchronous work
that needs to be wrapped up
before it's my turn?
So it's going to have some delays
while it's doing
some thread safety checks,
and stuff like that.
So we can simplify this a bit.
I could say, for instance, 
here at the top
inputDeps.Complete.
And then I could say
return new JobHandle.
So wrap up everything 
this one's doing
and return a new one
and let these continue on.
That's one way I could do it.
Another way I could do it is...
and maybe a better way, yet...
is to use the new attribute,
which is AlwaysSynchonizeSystem,
and then I could return back
inputDeps like this.

Japanese: 
これはメインスレッドで
実行されているため
読み取りデータやジョブの
inputDeps を処理して
ジョブの inputDeps を
返す方法がいまいちです
チェーン内の次の
システムでは
前のチェーンでの処理を確認します
何を待っているのでしょうか
順番が来る前にまとめる必要のある
非同期の処理は
あるのでしょうか
そのためスレッドセーフの
チェックなどの
実行中にある程度の遅延が
発生します
これを少しだけ簡略化できます
たとえばこの先頭に
「inputDeps.Complete」と
記述しています
次に「return new JobHandle」
と記述します
すべてをまとめると
新しいジョブが返されて
これらが続行されます
これはそのための方法の 1 つです
もう 1 つの方法は
改善されている可能性もありますが
AlwaysSynchronizeSystem という
新しい属性を使用して
このように inputDeps を
返すことも可能です

Japanese: 
ただし処理内容を完全に
明確化するうえでは
AlwaysSynchronizeSystem を使用して
inputDeps のみを残して
既定値を
返すだけとするのが
最善の方法だと
思います
できました
基本的には inputDeps は
使用しません
ここでは既定値のみを
返して常に
システムを
同期させます
メインスレッドだからです
この処理の前に行う必要がある
メインスレッドの処理を
すべて完了させた後に
この処理を実行して次のシステムが
処理を実行できるようにします
これにより Unity の
スケジューラーでこの処理を
最適化できるようになります
このコードはこのように
記述しています
よくわからない場合は
ドキュメントをご覧ください
実のところこれは
新たな方法であり
処理速度が若干
上がります
以上が入力システムです
これは入力を読み取り
データに書き込みます
では実際にパドルを
動かしてみます
ここで Unity に戻ります

English: 
However, maybe the best way to do it...
I think the best way to do it,
so that it's completely clear
what you're doing...
is to utilize our 
AlwaysSynchronizeSystem,
and leave just 
input dependencies alone,
and just return back default.
There we go.
Alright, so basically, we are not
using input dependencies 
for anything,
we're just returning back
some default here
and we are always 
synchronizing our system
because it's main thread,
and so we are going to finish up
any main thread work
that has to happen before this one,
then we're going to do this one,
and then the next system 
can do its thing,
so the Unity scheduler 
can optimize this.
So that is the way 
I'm writing this code.
If that doesn't make a lot of sense,
just check out the documentation.
Basically, this is kind of new ways
that we can look at this stuff
to maybe handle it 
a little bit faster.
So that's my input system,
so that's going to read in my inputs
and write to my data.
Now, how do we actually
move these paddles.
So I'll come back to Unity here.

English: 
And I have a PaddleMovementSystem,
which I'll wait 
for this code to compile.
There we go, code compiled.
And I'll open this up,
and our PaddleMovementSystem
is now going to take that inputData
and do something with it.
Again, we're going to look 
at some of this new syntax,
and some gotchas, 
and things like that.
So I'm going to say public class
PaddleMovementSystem,
just like that, and this one
is going to be a JobComponentSystem.
Again, like that, and I am going
to implement the abstract class.
There we go.
And what I'm going to say,
so first off, I need some stuff
that's going to make
my calculations work smoothly.
So first off, I'm going to declare
a variable float deltaTime,
and that's going to equal 
Time.DeltaTime. There we go.
And I'm also going 
to say float yBound...
so what's our upper 
and lower y bounds
because we're going to clamp
the paddle's position...
and that is going to be equal 
to our GameManager.main.yBound,

Japanese: 
PaddleMovementSystem を使います
このコードがコンパイルされるまで
待ちます
コンパイルが完了しました
これを開きます
PaddleMovementSystem で
inputData を取得して
処理することにします
では改めて
この新しい構文と
問題点などを
見ていきましょう
「public class PaddleMovementSystem」
と記述します
ここでは「JobComponentSystem」と続けます
もう一度このように
抽象クラスを実装します
こんな感じです
まずここで必要なのは
計算を円滑に動作させることです
「float deltaTime」と
変数を宣言して
「= Time.DeltaTime;」と
続けます
こんな感じです
さらに「float yBound」
と記述します
Y 値の上限と
下限です
これはパドルの位置の範囲を
固定するためです

Japanese: 
そして「= GameManager.
main.yBound」と記述します
これでこのデータを使用できます
次にここでジョブを
スケジュールします
Entities.ForEach を
スケジュールします
今回はマルチスレッドと
ワーカースレッドで
これをスケジュールします
最後までこの方法ではやりませんが
構文を確認できるように
最初はこの方法で
始めます
「JobHandle」と記述して
「myJob =」と続けます
今回ここでは
「Entities.ForEach」と記述します
つまりこの Entities.ForEach の
結果を JobHandle に代入します
さらにEntities.ForEach の中に
このような構文を記述します
こんな感じです
ここで少し
驚くことでしょう
なぜならこのようにした場合
「これでは
JobHandle が返されない」と
考えることになるからです
少しお待ちください
どの変数に注意すべきでしょうか
まず注意すべきは
「Translation」です
これは位置を指定する
新しい方法です
Translation は
上下左右といった

English: 
there we go, 
so we'll just have that data.
And next, we are going
to schedule a job here,
we're going 
to schedule Entities.ForEach.
This time, for now anyway,
I'm going to schedule this
on multithreads, on worker threads.
Now, I'm not going 
to keep it that way,
but we're going to start that way,
just so you can see the syntax.
So I'm going to say JobHandle,
and I'll say maybe myJob =,
and this time now,
I'm going to say Entities.ForEach.
So I'm assigning the result of this 
Entities.ForEach to a JobHandle.
And so inside Entities.ForEach,
again, we have the syntax like so.
Just like this.
Now, it's going to freak out 
for a moment
because it's going to say,
down here it's going to be thinking,
"Hey, this doesn't 
return a JobHandle."
I'll get to that in a moment.
So what variables do I care about?
So first off, 
I care about translation,
which is just our new way
of saying the position.
So translation, how we moving
left and right,

Japanese: 
動きを指定します
さらに「in PaddleMovementData」と続けて
パラメーターの名前は data にします
これは in なので
この時点では書き込まずに
ただ読み取るだけです
これで Translation に
書き込みます
続いてこの中で
「trans.Value」と記述します
位置を表わす値です
「.y」は Y 方向の位置を表します
そして基本的には
動きの速度と方向
デルタ時間から計算した値を
現在の y の値に加算します
その後 値が範囲内に収まるように
調整します
ここで「math.clamp」と
記述してその中に
このように記述します
「clamp」の中に
Translation の現在の
y の値を指定した後
「+ (data.speed
* data.direction)」と記述して
上下に動かします
さらに「* deltaTime」と続けます

English: 
up and down, whatever.
And in PaddleMovementData,
which I'm just going to call data
because it's in,
we're not writing to it now,
we're just reading from it,
and we are going to
now write to our translation.
Now, inside here, I'm going 
to go ahead and say trans.Value...
the value of my translation...
.y-- so what is our y's position.
And so we are going to add this,
basically, movement speed,
and direction, and delta time
to our current y value,
and then we're 
also going to clamp it.
So I'm going to say math.clamp
and inside clamp...
which I'm going to write like that...
inside clamp I'm going to say
well, our current y value
of the translation,
plus data.speed
times data.direction...
are we going up or going down...
times deltaTime, there we go.

Japanese: 
これが値になります
さらに続けて記述するのは
下限である
「- yBound」と上限である
「yBound」です
これで値が範囲内に収まるように
調整されます
計算結果をここで調整しています
現時点でまだ
完了ではありません
なぜなら JobHandle を
要求しているのに
JobHandle が作成されないからです
そのためスケジュールが必要です
すでに説明したように
これをスケジュールします
この処理には
inputDeps を使います
そして最後に「return myJob」と記述します
できました
これが JobComponentSystem の
作成方法です
システムの照会の後には
多数のワーカースレッドでの
実行がスケジュールされている
実行内容が
記述されています
以上になりますが
コードはまだ
完成ではありません
なぜならこのシステムはまだ
非常にシンプルだからです

English: 
So that's going to be the value.
And then I am going to say,
okay, what's our lower bound...
negative yBound--and our upper bound 
is positive yBound.
So that's just going 
to clamp it for us.
So clamping the results 
of this here.
Now, this whole thing
is still freaking out
because it's saying,
"Hey, this is asking for a JobHandle.
None of this creates a JobHandle."
So I need to schedule this,
so I'm going to do
like I said with the other one,
schedule this and it's relying on
these input dependencies.
And then at the end of this,
I can just say return myJob.
There we go.
And this is the way in which 
I can create a JobComponentSystem
that has a system query,
and then some execution
that is then scheduled to run
on a bunch of worker threads,
and things like that.
Now, all of that being said,
I'm not going 
to keep my code like this.
The reason for that is that 
this system is very, very simple.

Japanese: 
パドルを上下に
動かして上限と下限を
固定しただけです
さらにパドルは
2 つしかありません
そのため実行には
ごくわずかな時間しか
かからないでしょう
実際のところこのジョブを
スケジュールして
ワーカースレッドで実行するのに
かかる時間は処理する
だけの場合よりも
長くなります
今のところ
ジョブなどのスケジュールには
それほど時間はかからず
かなり効率的なプロセスですが
このシステムは非常に
シンプルです
要するに役に立ちません
そのためワーカースレッドでの
実行はメインスレッドでの
実行に比べると
効率が下がります
それがこのコードです
これは構文を理解してもらうために
作成したものですが
これをもっと効率的に実行するには
「Run」と記述します
そして既定値を返します
ここに「AlwaysSynchronizeSystem」
と記述します

English: 
It is simply moving a paddle,
moving something up and down,
and clamping its bounds.
Furthermore, 
there are only two paddles.
So this is going to take, basically,
a negligible amount of time,
an infinitesimal amount of time.
As a matter of fact, 
the amount of time
it takes to schedule this job
and run it on a worker thread
is greater than the amount of time
it takes to actually just do the work.
Now, that being said,
scheduling jobs and stuff like that
doesn't take that long,
it's a fairly efficient process,
but that's how simple 
this system is.
It basically does nothing.
So as such, it's less efficient
to run this on worker threads
than it is to just run it
on the main thread.
So that's what I'm going to do.
So here I showed you this just so 
you could see the syntax of it,
but it's just more efficient
just to run this, just to say Run,
and return back default,
and up here, 
to do our AlwaysSynchronize.

English: 
It's just faster that way,
so that's what we're going to do.
So now, again, we're just running it
on the main thread
because it's a very simple,
very fast thing to do.
Now, we're going 
to come back to Unity,
going to let this all compile.
I will make sure my paddles
has the data it needs--it does.
And I'm going to hit Play.
Now, the ball's not going to move,
or anything like that.
We are going to see this countdown,
because that's just built 
into the Game Manager there.
But more importantly, I can see
that W and S moves my left paddle...
that it is clamped.
Up and Down move my right paddle,
which is also clamped.
There we go, 
so paddle movement is done.
Fantastic. Alright.
So now, it's time 
to move on to the ball.
Now, with our ball here,
we want to just add, again,
some Physics stuff,
this will eventually
be turned into a prefab
which will be spawned 
by the Game Manager,
and stuff like that, as an entity,
but I just have it
in my scene to start with.
And so the first thing I need to do

Japanese: 
処理時間が短くなるので
この方法を使用します
繰り返しますがこれをメイン
スレッドのみで実行するのは
非常にシンプルかつ
高速だからです
では Unity に戻って
全体をコンパイルします
パドルに必要なデータが
あることを確認します
再生ボタンをクリックします
現段階ではボールは
動きません
カウントダウンが表示されますが
これは Game Manager に
組み込まれているからです
しかしもっと重要なのは
左側のパドルが 指定した範囲内を
W キーと S キーで動くことです
上矢印キーと下矢印キーで
右側のパドルも動きます
こんな感じです
パドルの動きは問題ありません
すばらしいですね
先に進みます
では次にボールに
移りましょう
ボールを選択した状態で
もう一度物理演算要素を
いくつか追加します
これは最終的に
プレハブに変換され
Game Manager によって
エンティティとして
スポーンされます
ただしまずはシーン内に
作成します
最初にやらなければならないことは

English: 
is I'm going to set up
the Physics on my ball.
Now, I could go back to my 3D Physics
by NVIDIA PhysX, built-in Physics,
and do like a Sphere Collider
and a Rigidbody, and whatever,
but I'm actually going to do
the DOTS way of doing this.
So I'm going to go 
to the DOTS > Physics,
and I'm going to add a Physics Body,
which is like a Rigidbody,
and it's going to say,
"Hey, you're adding a Physics body,
but this isn't being converted.
So it's not going to do anything.
Good luck."
I'll fix that in a second.
But I'm going to come 
down here,
and this is going to be 
a Dynamic body,
I don't want any drag 
or damping, linear or angular.
For now, I'm going to give this
an initial linear velocity.
This will eventually equal 0,
[inaudible] the spawner to do that.
I don't need to have 
any angular velocity.
I'm going to say no
to gravity to start with,
and I don't need to override
mass distribution or custom tags,
or anything like that.
The next thing I'm going to do
is I'm going to go ahead
and add a Physics Shape,
which is basically our collider.
And this is going to be a Sphere,

Japanese: 
ボールに物理演算を
設定することです
ここで組み込みの NVIDIA PhysX による
3D 物理演算に立ち戻って
Sphere Collider や Rigidbody などを
使うこともできますが
ここでは DOTS を使用した
方法で実行します
「DOTS」 > 「Physics」
に移動して
「Physics Body」を追加します
これは Rigidbody と似ています
ここには「Physics Body を
追加していても
変換されていないため
処理が実行されない」という注意が
表示されています
これはすぐに修正できます
ですが下の方に
移動します
これは「Dynamic」になります
位置方向も回転方向も
抗力や減衰の設定は不要です
ここでは最初の
線形速度を指定します
これは最終的に 0 になります
スポナーが処理します
角速度の指定は
不要です
最初は重力をなしに
設定します
また質量分布やカスタムタグなどの
オーバーライドは
不要です
次に実行するのは
「Physics Shape」の追加です
基本的にはこれが
コライダーになります
これは「Sphere」に変更して

Japanese: 
ここはクリアします
float 要素にわずかに小数
オフセットがあります
これらを 0 に設定します
ここに Physics Material
テンプレートを追加するか
自分で設定できます
摩擦係数は 0 にして
「Minimum」に設定します
「Restitution」は「Maximum」に
設定してよく弾むようにします
衝突フィルターを
設定できます
これはボールのレイヤーにない
あらゆる要素と衝突する
特殊なボールのレイヤーに
属しています
そのため 2 つ以上の
ボールがあり
ボール同士を
衝突させたくない場合に
使用しますがこのケースは
そうではないため
この部分は
変更しません
ここでこのエラーを
解消するために
ここに「Convert To Entity」を
追加します
できました
この時点で再生ボタンを押すと
ボールが動いて
跳ね返るはずです
押しました
うまくいきました
ボールが動き跳ね返るようになり
物理演算がエンティティに
変換されています
次にやるべきことは
2 つあります

English: 
and I'll just clear out...
there's a slight decimal offset there
for the float stuff...
I'm just going to set those to 0.
And I could add
a Physics Material Template here,
or I can just add a-- 
set it up myself.
So I just want there 
to be zero friction,
and I'll set that up to minimum,
and I want maximum restitution...
super duper bouncy, there we go.
And I could set up 
some collision filters
like, this belongs 
to a special ball layer
that only collides with everything
that's not on the ball layer, 
or whatever,
so that maybe 
if I had more than one ball
and I didn't want them
to collide with each other,
but I don't have that, 
I don't need that,
so I'm going 
to leave that as it is.
Now, to get rid of this error here,
I am going to go ahead
and add the Convert To Entity stuff
right there.
Cool.
So at this point, if I hit Play,
that ball should move around
and bounce around.
There it goes. Cool. Alright.
So it's moving, it's bouncing,
with physics being converted 
to an entity.
So the next thing 
I need to do is two things.

Japanese: 
1 つはボールがゴールに入って
プレイヤーに得点が
入ったかを検出し
それを Game Manager に
認識させることです
もう 1 つはボールの速度を
徐々に上げることです
それは本来の『Pong』とは
違いますが
私もこのゲームを
プレイしていたので
相当上手なプレイヤー同士なら
いつまでもゲームが終わらず
多少飽きることはわかります
そのためゲームが進むにつれて
ボールの速度が上がると
面白くなると思います
そのために新しい
コンポーネントを追加します
最初はこの BallTag
コンポーネントです
これをここで開きます
最初に
「GenerateAuthoringComponent」と
記述します
続いて「public struct BallTag」と
記述します
これは IComponentData です
これをタグとして使用しています
「Tag」という単語が
入っているのでわかります
そしてここにはデータが
ありません

English: 
So the ball, one, needs to detect,
"Hey, has the ball reached the goal,
so has the player scored?
Let's let the Game Manager 
know about it."
The other thing is the ball
is going to speed up over time.
Now, that is not a Pong mechanic,
but basically I was playing the game
and realized that if two players
are decently good at this game,
the game can go forever,
and that's kind of boring, so
just making the ball speed up
as the game goes on is,
in my mind, pretty fun.
So I'm going to add
some new components to do that.
So the first thing
is this BallTag component.
I'm going to open this up here,
and I'm just going
to start by saying
GenerateAuthoringComponent.
This is going to be
a public struct BallTag,
which is an IComponentData.
Now, I'm using this as a tag,
which I like to just put 
the word tag on it, so you know.
And what I mean by that
is there's no data in here.

Japanese: 
これにはデータが格納されません
クエリとして使用して
移動と速度を含む
ボールの要素を
照会するだけです
ここにデータは
必要ありません
識別のためだけに
使用されます
次に記述先として
SpeedIncreaseOverTimeData
を使用します
これをここで開いたら
「GenerateAuthoringComponent」
ともう一度記述します
「public struct SpeedIncrease」
と記述します
もっと短い名前の方がよいですね
「OverTimeData」と続けます
これも IComponentData です
できました
この中に 1 つ
必要なものがあります
「public float」が必要です
通常であれば
IComponentData に 1 つの値が
格納されている場合
Value と名付けることは
珍しくありません
PaddleMovementSystem にも
「trans.Value」が
使われているように
割と一般的です

English: 
This does not store any data,
I'm just going to use this in queries
to say, "Hey, find me everything
that has maybe, say, a translation,
and a velocity, and is also a ball."
So I don't need to have 
any data in here,
this is purely 
for identification purposes.
So the next one 
I'm going to write to
is going to be my
SpeedIncreaseOverTimeData.
So I'll just pop this open here,
and again, I'm going to say
GenerateAuthoringComponent.
This is going to be
public struct SpeedIncrease...
I could have picked a shorter name...
OverTimeData,
also an IComponentData.
There we go.
And inside here,
basically, I need one thing.
So I just need a public float.
Now, speaking of standards,
it's pretty normal that if you have
a IComponentData
with a single thing in it,
you name it Value.
And we saw this
with the PaddleMovementSystem
where we have trans.Value,
and that's pretty common.

English: 
Doing Value is normal, 
but in my opinion,
if what your value is
is not particularly clear,
then give it a name.
So for instance, if I do
SpeedIncreaseOverTimeData.Value,
what is that value?
Is that the maximum speed?
Its speed per interval?
What's the interval?
What does that mean?
And so what I'm going to say
is increasePerSecond
is what I'm going to name this,
so that it's very obvious...
"Ah, this is the speed increase
per second. Cool."
So that's how I'm going to do this.
Now that I have that
and I have the BallTag,
I can create my system
that's going to speed the ball up.
And so I'm going 
to let this compile.
And then this is going to be
my IncreaseVelocityOverTimeSystem.
And I know a lot of people 
might be like,
"Oh, is it velocity or is it speed?"
Because one's scalar 
and one's vector.
Whatever. Basically, 
we're speeding stuff up,
and get over it.

Japanese: 
Value にするのが
一般的ですが個人的に
値が不明瞭になる場合は
名前を付けた方が
よいと思います
たとえば SpeedIncreaseOverTimeData.Value
と名付けた場合
その値は何の値でしょうか
最大スピードでしょうか
インターバルごとのスピードでしょうか
インターバルはどの程度で
それはどういう意味でしょうか
ここでは「increasePerSecond」
と指定します
この名前を付けることで
非常に明確になります
1 秒あたりの加速度です
わかりやすいですね
このように記述しました
これを記述して BallTag を
作成できたら
ボールの速度を上げる
システムを作成できます
ではこれを
コンパイルします
次に使うのは
IncreaseVelocityOverTimeSystem です
多くの方が velocity なのか
speed なのかと
思うでしょう
一方はスカラーで
もう一方はベクトルだからです
何であれ基本的には
ボールの速度を上げて
対処します

Japanese: 
IncreaseVelocityOverTimeSystem で
これをこのように
「JobComponentSystem」と
指定します
IDE を使用して
これを実装できるので
ここでは入力が不要です
こんな感じです
さらに再度
「float deltaTime = Time.DeltaTime」
と続けます
これらを利用できるようにするには
「Entities.ForEach」と
記述します
ForEach の中に
式を指定します
こんな感じです
この中で目的のデータを
指定します
まず最初に
PhysicsVelocity を
参照します
続いて「vel」と記述します
これを変更するためです
「in SpeedIncreaseOverTimeData」
と続けて
パラメーターの名前は data にします
「in」なのはデータを
変更するのではなく
読み取るだけだからです

English: 
So here is my
IncreaseVelocityOverTimeSystem,
and I'm going to make this
a JobComponentSystem,
just like this.
And I'm going to allow the IDE
to implement that for me,
so I don't have to type.
There we go, 
and I'm going to say, again,
float deltaTime = Time.DeltaTime.
Just want to have those things
available to me.
And then I'm going to say
Entities.ForEach.
Here we go, ForEach.
And I will set up my expression...
like so.
And inside here, the data
that I am going to be looking at...
So, first off, I'm going to 
reference my PhysicsVelocity,
there we go, 
which I'll just call vel
because I'm going 
to be modifying this one.
And then I'm going to say
in SpeedIncreaseOverTimeData,
which I'll call data, and that's in
because I'm not going to be modifying,
I'm just going 
to be reading from it.

Japanese: 
この中では値と
モディファイアーを計算します
「float2」と記述して
モディファイアーという名前をつけて
「= new float2」と記述します
その中に
「data.increasePerSecond
* deltaTime」と記述します
こんな感じです
modifier のスペルが
間違っていました
直りました
誰も注意しませんでしたね
そしてこれが
この特定のインターバルの
モディファイアーになるように
記述します
そこで「float2 newVel」と記述して
「= vel.Linear」と続けて
線形速度「.xy」を指定します
Z は不要です
現在の速度はどうなるでしょうか
角速度や回転ではなく
XY での線形速度を取得します
それをここで取得したら
その後続けて

English: 
So inside here, I needed to calculate
what my value is, or my modifier is.
So I am going to say float2,
which I'll call modifier,
= new float2.
And inside here I'm going to say
data.increasePerSecond
times deltaTime.
Just like so.
Alright, and so we're going to have...
oh, I spelled modifier wrong.
There we go.
No one warned me.
And then I'm going to say,
alright, so that's going 
to be my modifier
for this particular interval.
And so I'll say float2 newVel
is going to equal vel.Linear...
that's the linear velocity--.xy.
We don't need the Z.
So basically what 
is our current velocity?
Grab the linear, not the angular 
velocity or its rotations,
its linear velocity in the xy.
I'm going to grab that here,
and then we're simply going to say

Japanese: 
「newVel += math.lerp」
と記述します
よくある線形補間です
線形補間の範囲を
負のモディファイアーと
正のモディファイアーで指定して
「math.sign(newVel)」の値に基づいて
補間後の値を決定します
これで基本的に
速度が上がります
またはこの新しい速度が
指定されます
次に「vel.Linear.XY = newVel」
と記述します
ここで見直してみましょう
まず
速度を取得して
increasePerSecond で
調整した後に
それを返しています
これはメインスレッドになります
理由はまったく同じです
ボールは 1 つです
実際にワーカースレッドで
実行する意味はありません
非常に高速なので

English: 
newVel += math.lerp...
everyone's favorite,
linear interpolation, lerp...
and I'm going to lerp 
between negative modifier
and positive modifier,
based on math.sign...
the sign function--newVel.
Alright. So this is basically
going to increase our speed,
or give us basically, 
this new velocity.
Then I'm going to say
vel.Linear.xy = newVel.
So I'll just write it back.
So basically, 
we're grabbing a velocity,
we're modulating it
by this increasePerSecond,
and then we are 
sending that back there.
Now, this is going to be main thread
for very much the same reasons
of there's one ball,
there's really no point in 
running this
on worker threads, it's very fast,

Japanese: 
「Run」と記述するだけです
こんな感じです
次に「return default」と
記述するだけです
既定値を返す処理を書いたので
さらに「AlwaysSynchronizeSystem」
と記述します
さてここで
あまり詳しくない方のために
このコードの仕組みを
簡単に説明します
「math.sign」では
たとえば左または
下に動かす場合に
この負のモディファイアーを
使用して
左に動かします
右に動かす場合は
正のモディファイアーです
0 より大きくするので
正のモディファイアーを
使用します
つまり
簡単に言うと
左または下に動かす場合は
負の値を使用して
右または上に動かす場合は
正の値を使用します
このようにスピードを
減衰させることなく
どの方向に対しても
スピードを上げています
以上です
現段階で考える
もう 1 つのポイントとして
本題から逸れるかもしれませんが

English: 
so I'm just going to say Run.
Like so.
And then I'm just going to say
return default,
and since I'm returning default,
I'm going to go ahead and do
my AlwaysSynchronizeSystem, like so.
Alright, now, 
if you're not familiar,
if you're looking at this code
and saying, "What is happening here?"
math.sign,
we're basically going to say,
okay, well, if we're moving 
to the left or downward or whatever,
then we're going to be using
this negative modifier
to move us leftward.
If we're moving to the right,
positive modifier,
so we're above zero, we're going 
to be using the positive modifier.
So just in case, you're looking 
at that and being like,
"What's happening here?"
If we're going left or down,
we're using negative.
If we're going right or up,
we're using positive,
and that way 
we're not damping our speed,
we're increasing it
in whichever way we're going.
Cool.
Another thing you might be
thinking at this point...
I know it's maybe just tangential...
is why did we have 
two different systems,

English: 
for our input and our movement,
because they could be 
the same system,
and I meant to bring this up earlier,
and it's just now
popping back into my mind.
And the way these 
are currently set up,
you're absolutely right.
Since these are both 
on the main thread,
one is reading in our inputs
and setting some data for movement,
and then next, is then just moving,
you could, realistically,
just make these one system.
The reason I have them
as two systems is a couple things.
You might have inputs for things 
that let's say maybe aren't paddles,
even though this is specifically 
saying PaddleInput
and PaddleMovement
We may have one input system
that reads our input
and sets a bunch of different data
on a bunch of different entities,
and then a movement system
that handles movement
for a bunch of different things.
So coupling those two things 
together
doesn't make a lot of sense logically.
It's better just 
to keep those separate.
But the second reason, really,
is that PlayerInputSystem
has to be on the main thread
because it's using Input.GetKey,
and our PaddleMovementSystem
doesn't have to be on 
the main thread.
As a matter of fact, 
if I had more paddles

Japanese: 
入力と動きの処理に
2 種類のシステムを使用した理由です
1 つのシステムでも
可能だからです
少し前にも触れましたが
また思い出しました
これらの現在の
設定は
間違っていません
どちらもメインスレッドで
処理されます
入力の読み取り
動きのデータの設定
実際に動かすことは
現実的に 1 つのシステムで
実行できます
2 つのシステムを使用する
理由はいくつかあります
具体的に PaddleInput や
PaddleMovement と
記述した場合でもパドル以外の
要素の入力である
場合があります
入力を読み取って
多数の各種エンティティに
さまざまなデータを設定する
入力システムと
多数の各種要素の動きを
処理する移動システムが
必要になります
この 2 つを 1 つにまとめるのは
あまり合理的ではありません
これらは切り離しておくことを
お勧めします
そして 2 つ目の理由については
PlayerInputSystem は
Input.GetKey を使用するため
メインスレッドに必要ですが
PaddleMovementSystem は
メインスレッドに配置する
必要がないためです
実際のところパドルの
数がもっと多い場合や

Japanese: 
処理量が増えた場合は
ワーカースレッドで実行します
そのためこれらは
切り離しておく方が賢明です
これらのシステムで実行される
処理は異なります
後で要素を追加した場合は
実行する代わりに
スケジュールすることで
マルチスレッド実行できます
1 つのシステムに
した方がシンプルで
統合も簡単なのに
なぜ 2 つのシステムを
使用するのかと
思う方もいるでしょう
確かにそのとおりですが
私がこのように作成したのは
その方が柔軟性が
高いからです
さて少し本題から
逸れましたが
IncreaseVelocityOverTimeSystem
に戻りましょう
これでコードの記述は以上です
ボールが徐々に
スピードアップします
Unity に戻って
コンパイルし
再生ボタンをクリックすると
そうなるはずです
コンパイルしています
すみません取り消します
そういえばボールにそのデータを
設定していませんでした
「Data Components」に移動して
「BallTag」を追加します
できました
「SpeedIncreaseOverTime」もです

English: 
or if this was doing more work,
I would run this on worker threads.
So it makes sense
just to keep these separate...
they're not doing 
the same thing anyway...
and later, if I add more stuff,
I can make this run multithreaded
by just scheduling it,
instead of running it.
So in case you were looking at this
and thinking to yourself,
"Why have two systems for this
when they're so very simple,
and they can so 
very easily be combined?"
You're absolutely correct,
but I wrote it that way
because that way we have
some flexibility there.
Alright, so I know that was
a bit of a tangent there,
but coming back to our
IncreaseVelocityOverTimeSystem,
this is all written out now,
and so our ball 
will speed up over time.
And if I come back to Unity
and I let this compile,
and we hit Play,
that's exactly what we should see.
So let's see this compile here.
Actually, scratch that.
It occurs to me that we never 
actually put that data on the ball.
So I'm going to go 
to my Data Components here
and I'm going to add the BallTag.
There we go.
And the SpeedIncreaseOverTime.

English: 
And let's give it a speed increase
of, say, 0.2.
So, what we're going to see here
is that's going to add
a little bit of randomness 
to our movement
and some speed increase.
So it's going to make it
a little bit harder to play.
So now it's kind of
bouncing down like that.
So now, the ball's going to move
a little bit less predictably.
Originally in Pong,
you could do corner shots
and stuff like that,
which would make it speed up
and kind of angle 
a little bit harder.
I don't have 
any mechanics like that,
but this sort of is going to 
simulate something similar to that.
Okay, so now that I have that,
the last little bit here
is I need to determine
when the ball has made it 
to the goal, and is going to score.
And so I'm going to go here
and I am going to go to my Systems,
and I'm going to go
to the BallGoalCheckSystem,
and I'm going 
to go ahead and create this.
So this is going to be
a JobComponentSystem.
Nope, not JobChunkExtension...
JobComponentSystem.

Japanese: 
加速度をここでは
「0.2」と入力します
次にここで紹介するのは
動きや加速度に
少しランダム性を
追加する方法です
これで少しゲームの
難易度が上がるでしょう
このように跳ね返ります
ボールの動きが若干
予測しにくくなります
本来の『Pong』では
コーナーショット
などが可能です
こうした技により
ボールはスピードアップして
角度が少し難しくなります
私のゲームにはそのような
メカニクスはありませんが
似たような処理を
シミュレートしていきます
さてそれができたところで
ここで最後に
ボールがゴールに入って
得点になるタイミングを
判定する必要があります
そのため「Systems」に移動して
「BallGoalCheckSystem」を開き
これを作成します
ここに「JobComponentSystem」と
記述します
いや間違えました
「JobComponentSystem」です

Japanese: 
できました
さらにここにコードが
自動的に記述されます
こんな感じです
若干異なる
構文になっています
続いて「Entities.」と記述します
もちろん「ForEach」も
記述します
このように式を
記述します
これまでに
これは何度か見ました
さてここでは
ForEach を
実行するだけではなく
BallTag もチェックしますが
その理由をここで説明します
チェック対象となる実際の
データである
クエリはまずエンティティ自体を
クエリに含めます
破棄すべき可能性があるからです
ボールはゴールに入ったら
消える必要があるため
その処理を行う
エンティティが必要になります
さらに「in Translation」と
記述して
パラメーターは「trans」
という名前にします
クエリ対象が移動を伴う
エンティティの場合は

English: 
There we go.
I'm going to let this
write out for me there.
There we go.
And so we're going to have
a slightly different syntax here.
And so I am going to say Entities.
and of course, 
I'll be doing ForEach.
And I will write out
my expression like so.
At this point, 
we've seen it a few times.
Alright, and I'm not just going 
to do ForEach,
I also want to make sure that...
I'm checking out that BallTag,
but let me explain why, here.
So the query,
the actual data that I am checking,
is first off, I want the entity 
itself as part of my query,
because I may need to destroy it.
If the ball makes the goal,
I want the ball to go away,
so I'm going to need
the entity to do that.
I'm also going to read in
its Translation,
which I'll just call trans there.
So if my query is anything
that's an entity with translation,

Japanese: 
すべてのエンティティでこの
システムが実行されますが
あまり合理的ではありません
対象はボールだけだからです
ここではクエリに BallTag を
配置しようとしましたが
それも意味がありません
データがないのです
実際に照会するものがありません
試してみると
エラーが発生します
代わりにこのように変更します
このレイヤーを作成します
改行して先頭に
ドット「.」を記述します
ここに「WithAll」と続けて
この中に「BallTag.ForEach」と
記述します
これで BallTag を含む
すべてのエンティティが
クエリの実行対象になります
これで移動を伴う
エンティティのみが取得されます
BallTag も含まれます
さらにここで実行できることが
多数あります
「WithStructuralChanges」と
記述したら
後ほど説明するので
そのままにしておきます
このままで完了という
わけではありません
もっとよい方法を
後で説明します
今はいったんこのままに
しておきます

English: 
I'm going to be running this system
on everything, every entity I have,
which doesn't make a lot of sense
because I'm only looking for the ball.
I could try to put the BallTag
in my query here,
but that doesn't make sense.
There's no data.
There's nothing to actually query.
So I'm going to get
an error if I try that.
So instead, I'm going to do this.
I'm going to layer this and I like 
to just put each of these dots
on a new line, 
so I'm going to do entities WithAll,
and inside here I'm going to say
BallTag.ForEach.
So now it's saying, "Okay, Entities,
all entities that have BallTag,
here's the query to run against."
So only get things 
that are entities with translation
that is also containing BallTag.
Furthermore, I can keep going.
There's a lot of stuff we can do here.
We can say WithStructuralChanges,
which I'm going to talk about
here in a moment,
so I'll leave this here now.
I'm not actually going to leave 
this in here permanently,
because I'm going
to show you a better way,
but we'll just leave it 
in there for now.

Japanese: 
さらに「WithBurst」と記述して
Burst コンパイルを有効化します
これは実際には
間違った名称です
通常は属性を使用して
BurstCompile などと指定します
ここでは Burst としてみます
この新しい構文を使用すると
実行していなくても
WithBurst が非推奨であるという
通知が表示されます
代わりに Burst が常に
有効になるようにします
Burst が不要な
要素に対して
任意で「WithoutBurst」を
使用することもできます
ここではこれを削除します
単に Burst を
使用したいからです
このようにしても
問題ありません
つまり「Entities」「WithAll」
「WithStructuralChanges」「ForEach」に
Entity のクエリが続く形です
以上になります
実際にはどのような処理が
実行されるのでしょうか
「float3 pos = trans.Value」と
記述します
これがエンティティの
位置になります

English: 
You could also say WithBurst
to, say, enable 
Burst compilation, right?
Now, this is a bit 
of a misnomer actually,
so normally you would 
use the attribute
to say BurstCompile, or whatever,
this is Burst, 
I want Burst, whatever.
With the new syntax,
what you'll notice if you...
well, it's not doing it now...
but you'll get a notification here
that WithBurst is being deprecated.
Instead, Burst is just going 
to be turned on all the time,
and it would be up to you
to say WithoutBurst
on the things 
that you don't want Burst.
I'm just going to leave this here
because I just wanted 
to use the Burst,
and stuff like that,
and so I have it like that,
and that's good.
So Entities WithAll BallTag
WithStructuralChanges ForEach
with our Entity query here.
Alright, so there is all that.
What are we actually 
doing with this?
Well, I'm going to say
float3 position = trans.Value.
So that's going to be
the position of this entity.

English: 
And then we'll say float bound...
so what's our boundary.
It's going to equal
GameManager.main.xBound.
There we go.
And so now, what I'm going to do
is I'm going to say,
alright, so if my pos.x
is greater than or equal to my bound,
so if I'm all the way to the right,
then what I'm going to do
is I'm going to say...
oh, there we go...
tabbing sometimes gets 
weird inside here.
I'm going to say,
"Hey, GameManager.main
the Player has Scored"
and it will be Player 0
that has scored in this situation.
And then I'm going to say
PostUpdateCommands.
Nope, that's wrong, 
that's old syntax--my apologies.
I'm going to say
EntityManager.DestroyEntity,
and I'm going to say, 
so destroy the ball.
Okay, the player scored
and we don't need this ball anymore.

Japanese: 
次に「float bound」と記述します
境界を指定します
「= GameManager.main.xBound」
と続けます
できました
コードの記述を
続けて
「if(pos.x >= bound)」と
記述します
つまり右に動かしたときに
どのように処理するかを
指定します
少々お待ちください
ときどきタブが使いにくい
ことがあります
「GameManager.main.PlayerScored」
と記述します
この場合はスコアを獲得した
Player 0 となります
次に「PostUpdateCommands」
と記述します
すみません間違えました
これは古い構文でした
「EntityManager.DestroyEntity」
と記述します
これでボールを
破棄します
プレイヤーがスコアを獲得したら
このボールは不要です

English: 
Otherwise, I'm going 
to say if position.x
is less than or equal 
to negative x Bound...
which in this case is just Bound...
then I'm going to say, 
alright, well,
GameManager, again, 
main.PlayerScored.
This time it was
the right-side player, Player 1.
And again, I'm going to say
EntityManager.DestroyEntity.
And again, 
we're destroying this entity.
Cool. Now, you may be thinking,
"Well, are we going 
to schedule this main thread?
Are we going to schedule
this worker thread?"
Well, hopefully you can see that
since we're using EntityManager here,
since we're referencing GameManager,
which is all on the main thread,
that this needs to be, again,
on the main thread.
So I'm just going to Run this,
and I'm going to return default.
Then I'm going to come back 
to the top and say
AlwaysSynchronizeSystem.

Japanese: 
それ以外の場合のために
「else if(pos.x <= -xBound)」と
記述します
この場合は単に「bound」ですね
よろしいでしょうか
次に記述するのは
「GameManager.main.PlayerScored」です
今回は右側のプレイヤー
Player 1 です
「EntityManager.DestroyEntity」と
もう一度記述します
繰り返しになりますが
このエンティティを破棄します
うまくできました
ここで「このメインスレッドを
スケジュールするか
このワーカースレッドを
スケジュールするか」を
考える方がいるかもしれません
ご覧のとおりここでは
EntityManager を使用しており
こちらでは GameManager を
参照しているおり
すべてがメインスレッドにあるため
繰り返しますがこれはメイン
スレッドに配置する必要があります
ここに「Run」と記述するだけです
「return default」と記述します
その後先頭に戻って
「AlwaysSynchronizeSystem」と
記述します

English: 
So this game is actually going to use
three or four main thread systems,
but we're not going to have
any worker threads
because nothing about this
is complex enough to need it.
And so there we go.
Now, this will work,
and the reason I can use
EntityManager.DestroyEntity,
anything with EntityManager
is because I'm saying
WithStructuralChanges.
So I'm saying, "Hey, let's create
a special version of this data,
that is going 
to allow me to modify it
without invalidating
the structure of data,
which is traditionally
causing errors in DOTS."
So this allows me to bypass that.
That being said,
there's another way we can do this,
and there's another way
I'm going to do this.
So WithStructuralChanges
is simple enough for simple data,
and if it was just me
writing this Pong game,
for my own personal use, 
or whatever,
I would leave it like this
because this Pong game
is a very simple game,
there's not a lot of data.
The reason I'm going to change it
is for you--you're welcome.
I don't want you thinking
that WithStructuralChanges

Japanese: 
このゲームでは 3 つか 4 つの
メインスレッドシステムを
使用する予定ですが
ワーカースレッドは使用しません
これに関しては必要になるほど
複雑ではないからです
先に進みましょう
これで動作します
EntityManager.DestroyEntity や
EntityManager を含む要素を
使用できるのは
「WithStructuralChanges」を
記述しているからです
それではこのデータの
特殊なバージョンを作成し
データの構造を
無効にせずに
データを変更できる
ように指定します
従来は DOTS でエラーが
発生していました
これならエラーを回避できます
そうは言っても
別の方法もあります
その方法についても
説明します
WithStructuralChanges は
シンプルなデータに適しています
この『Pong』ゲームを個人的に
使用するためだけに
作成しているなら
このままにします
『Pong』は非常に
シンプルなゲームなので
データも多くないからです
これを変更するのは
皆さんへの説明のためです
WithStructuralChanges を
常に使用すべきと

English: 
is the way you go all the time.
As a matter of fact,
if you're creating a game
that is more complex,
much more complex,
WithStructuralChanges can end up
causing some slowdown,
because it's making
a specialized copy of that data
that you're going to be
making structural changes against.
And so I'm going to get rid of that.
Sorry, WithStructuralChanges,
I liked you,
but you're ultimately bad for me.
And I don't want anyone here
writing code
and then later being like,
"But Mike said to do it this way,"
and yelling at me on Twitter
or anything like that.
I don't need that drama in my life.
So I instead am going 
to do it this way.
I'm going to say EntityCommandBuffer,
good ol' EntityCommandBuffer,
ecb = new EntityCommandBuffer
with an Allocator which is TempJob.
There we go,
so there's my EntityCommandBuffer.
And I'm just going to write
to this EntityCommandBuffer
all the commands that I want to do,
and then after my work here,
I'm just going to play it back,
which is the other way we do this.
So now, I'm going to come down here
to where I say
EntityManager.DestroyEntity,

Japanese: 
考えてほしくありません
実際のところ
作成するゲームが
より複雑になればなるほど
WithStructuralChanges では
動作が遅くなる場合があります
なぜならデータの特殊な
コピーを作成し
それに対して構造的な
変更を加えるからです
そのためこれを削除します
WithStructuralChanges は
便利ですが
今回は削除します
これを見た誰かが
コードを記述するときに
別の方法の方がよいと
考えて Twitter などで
私にクレームを入れるのは
やめてほしいからです
そういう展開は好みません
ともかくこの方法で進めてみます
「EntityCommandBuffer ecb =
new EntityCommandBuffer」と書き
「Allocator」を「TempJob」として
指定します
できました
EntityCommandBuffer です
この EntityCommandBuffer に
必要なコマンドを
すべて記述します
それが終わったら
再度再生してみます
それは別の方法になります
ではここで下にある
EntityManager.DestroyEntity に
移動します

Japanese: 
「ecb」と記述します
これは EntityCommandBuffer の
Destroy となるためコマンドの
バッファに追加します
ここでは ecb.DestroyEntity
となります
さらに Run の後に
コードを記述します
実行後の処理になります
EntityManager で
EntityCommandBuffer を
再生するよう指定します
つまり EntityManager に
EntityCommandBuffer に溜めた
コマンドをすべて実行するよう
指示するのです
それが完了したら
さらにコードを記述して
EntityCommandBuffer の
処理は完了です
この方法で
進めます
EntityCommandBuffer を
使用すると
処理中にデータを
構造的に変更するのではなく
データへの書き込みを
行います
繰り返しますがこれは
シンプルなケースでは
非常に有効ですが
複雑なケースでは
動作が遅くなることがあります
これがいつでも
有効な方法とは
考えないでください
そのため 2 つの方法を紹介しました
他にも多数の方法があるでしょう
進めましょう
Unity に戻って

English: 
and I'm just going to say ecb...
EntityCommandBuffer--Destroy,
so add this to our buffer
of commands to do,
ecb.DestroyEntity here.
And then after Run,
I'm going to say, alright,
now that we're done running,
and now it's time to do something.
So I say, hey, let's playback
our EntityCommandBuffer
with our EntityManager.
So "Hey, EntityManager,
do all these commands
that we recorded, now,
unspool and do all these things."
Then once we're done with that,
we can say, alright, now we're done
with our EntityCommandBuffer,
so there we go.
So this is the way 
I'm going to do it.
So EntityCommandBuffer,
we're just going to use that,
and then we're going 
to write it back
instead of making structural changes
to our data while we're working on it,
which, again, works very well
in simple situations,
but if you're not 
in a simple situation,
can cause some slowdown.
I didn't want you 
to think that's the way
I was saying to do it all the time,
so there's two ways to do it.
You've got so many options.
Alright.
And so now, 
if I come back to Unity,

English: 
I'm going to go ahead
and just let this run,
and we're going to see
that the player is going to score.
Alright, let's see what happens.
Ball's going to come in,
it's going to bounce,
and there we go, we scored a point.
The entity was destroyed,
however GameManager 
hasn't been set up
to spawn a new one 
or anything like that.
We also have an interesting error.
So if I go to my Console, 
I see this.
I see that this managed class type
GameManager is not supported.
Loading from 
a non-readonly static field
is not supported with Burst.
So we have a Burst error here.
Alright, so let's fix that.
So I talked before
about how we can disable Burst
for things that don't support it.
So that's exactly 
what I'm going to do.
Well, I can't reference GameManager
here like this,
so I'm just going to say,
"Alright, well, fine.

Japanese: 
これを実行します
プレイヤーにスコアが
入るか確かめます
どうなるか見てみましょう
ボールが入って
跳ね返り
ポイントを獲得しました
エンティティは破棄されましたが
GameManager が
新しいボールを
スポーンするようにまだ
設定されていません
興味深いエラーも発生しています
「Console」で
これを確認できます
このマネージドクラスの GameManager
はサポートされていません
読み取り専用以外の
静的フィールドからのロードは
Burst では利用できません
Burst のエラーのようですね
では修正しましょう
すでに説明したとおり
サポート対象外の要素では
Burst を無効化できます
まさにその処理を
行います
ここではこのように
GameManager を
参照することは
できないため

English: 
Then let's not use Burst
and let's move on with our lives."
So I will let this compile,
and then run it again here.
And no error. Cool.
Okay, good stuff.
I didn't do the cheating thing
where I just hide the error,
so it's gone away-- 
it's actually gone.
So the last bit of this game...
we're almost there, home stretch...
is I would like to have my GameManager
spawn this ball for me.
So I'm going to go ahead and turn 
this ball into a prefab like so.
I'm going to delete it from my scene,
I'm going to go to my GameManager
where it says what's my ball prefab,
and I'm just going 
to drop that on there like so,
and then I'm going to save my scene
and open up my GameManager again
to write this code.
So first thing I need to do
is up inside my Awake method,
is I am going to convert 
my ballPrefab into an entity in Awake
so that it's just done.

Japanese: 
Burst を使用せずに
処理するよう指定します
これをコンパイルして
再度実行します
エラーは発生しません
うまくできました
修正は完了です
エラーを隠すことはせず
実際に修正しました
ではこのゲームの最後の
部分に入ります
GameManager でボールを
スポーンするよう設定します
このボールをこのように
プレハブに変換します
これをシーンから削除して
GameManager に移動します
ボールのプレハブを選択し
それをここにドロップしたら
そのシーンを保存します
再度 GameManager を開き
このコードを記述します
まず必要なのは上にある
Awake メソッドの変更です
ここで ballPrefab を
エンティティに変換します
このようになります

English: 
And I am also going to utilize
this manager to do that
and to spawn 
new ones just like that.
Now, I am going to end up
converting this GameObject
to an entity here 
in the Awake method.
I could do that
ahead of time in the editor
using the SubScene workflow
and then just store as an entity,
but for now, this is simple,
this is straightforward,
so I'm just going 
to do it this way.
So what I'm going 
to do is, first thing,
and this syntax has 
changed a little bit.
So I'm going to say,
"Hey, EntityManager"...
right up here,
this variable EntityManager...
Manager and I used to do
world.active.EntityMirror
getEntityManager, whatever,
that syntax has 
changed a little bit.
So it's going to be
World.DefaultGameObject
InjectionWorld.EntityManager,
and that's a longer way of saying,
"When we turn 
GameObjects into entities,
give me the world
those would normally go into."

Japanese: 
このマネージャーを
利用して変換し
新しいボールを
スポーンします
以上で Awake メソッドで
GameObject を
エンティティに
変換できました
この処理は
前もってエディターで
SubScene ワークフローを使用して
エンティティとして格納できますが
現時点ではシンプルで
わかりやすいので
この方法で進めます
まずこの構文が
少し変更されています
ここで「manager」
と記述します
上にある EntityManager 型の
変数 manager のことです
以前は
world.active.EntityMirror や
getEntityManager を
使用していましたが
その構文が若干
変更されています
「World.DefaultGameObjectInjectionWorld
.EntityManager」
と記述します
長いコードですが
GameObject を
エンティティに変換する際に
通常使用するワールドを
渡すよう指定しています

English: 
Just what's our default world
for doing that,
and give me the EntityManager
of that world.
Because that's not necessarily
the active world,
that's the one that we generally
inject entities into.
So give me that, EntityManager.
Next, I need to create
a GameObjectConversionSettings,
which I'm going to call settings.
And that is going to be
GameObjectConversionSettings.FromWorld.
So give me the settings 
from a world.
Well, what world?
Well, I'm glad you asked.
World.DefaultGameObjectInjectionWorld,
and then null
for our second parameter there.
Alright, so there we go.
It's a long-winded line there,
but there we go.
And then, finally, I'm going to say,
alright, well, now I'm going to say,
"Hey, ballEntityPrefab,
you are going to equal
GameObjectConversionUtility.

Japanese: 
つまりデフォルトの
ワールドと
その EntityManager を渡します
アクティブなワールド
とは限らないため
通常エンティティの
挿入先となるワールドです
EntityManager を渡します
次に「GameObjectConversionSettings」
と記述し
settings という名前の変数を宣言します
そして「= GameObjectConversionSettings
.FromWorld」と続けます
ワールドから設定を
取得します
どのワールドでしょうか
大事な点です
「World.DefaultGameObjectInjectionWorld」
と記述し
2 つ目のパラメーターを
null にします
こんな感じです
かなり長くなりましたが
できました
最後にここでは
「ballEntityPrefab
= GameObjectConversionUtility

Japanese: 
.ConvertGameObjectHierarchy」と
記述します
GameObjectPrefab である
ballPrefab と
前述の行で宣言した
設定を渡します
このワールドでこの設定を使用して
GameObject を取得し
変換して
ここに格納します
DOTS パッケージの
新バージョンでは
最新の物理演算や
アニメーションを使用できるため
アセットのブロブなどの
値を指定できます
それはこのシンプルな
ゲームには不要な要素なので
null としますが
この構文を
発展させて
さまざまな処理を
行うことができます
しかしこれがシンプルな
変換なので GameObject の
ボールをエンティティとして渡します
非常にシンプルです
では最後に
この SpawnBall に
移りましょう
ここで「Entity ball」と記述して
新しいボールを指定して

English: 
ConvertGameObjectHierarchy."
There we go, and I'm going 
to pass in the ballPrefab,
which is our GameObjectPrefab,
and the settings
we declared in the line above it.
So take this GameObject
and, in this world,
with these settings, go ahead
and convert it, and store it here.
Now, in newer versions 
of DOTS packages
like maybe the newest Physics
and animation stuff like that,
we can provide 
values here to do stuff
like blobs for assets,
and things like that.
That's kind of beyond 
this simple game,
so I just left that as null,
but you'll see 
that this syntax can grow
and there's more stuff
we can do with this.
But this is a simple conversion...
so I have a ball that's GameObject,
give me a ball that's an entity.
Alright, pretty straightforward.
So now, the final little bit here,
I'm going to go down 
to this SpawnBall,
and here, I am simply going to say
Entity--the ball...
so give me a new ball,

English: 
is going to equal my manager,
which is my entity 
manager.Instantiate.
So make one for me.
Make me a copy 
of this ballEntityPrefab,
named ball. Cool.
And then I want to give it
some new velocity,
some new randomness to it
every time it spawns.
So I'm going to say
Vector3 dir = new Vector3.
Alright, and inside here,
I'm going to say UnityEngine...
I need to specify Random.Range,
because now there's going to be
some ambiguation
between random 
that's part of UnityEngine,
random that's part of System,
so I'm just going
to type it all out like this.
Random.Range between 0 and 2.
So I'm going to say, "Pick a number
that's either 0 or 1,"
because if I'm doing integers,
it's exclusive,
so give me values
of either 0 or 1, but never 2.
And so I'm going to say,
"Did you give me a 0?"

Japanese: 
エンティティを指定するために
「= manager.Instantiate」
と続けます
ここに ballEntityPrefab の
コピーを作成します　うまくできました
続いてボールが
スポーンされるたびに
新しい速度と
ランダム性を追加します
「Vector3 Dir = new Vector3」
と記述します
この中に
「UnityEngine」と記述します
「Random.Range」を
指定する必要があります
UnityEngine の
一部としてのランダム性と
システムの一部としての
ランダム性に曖昧さを
持たせるため
このように記述します
「Random.Range(0,2)」です
0 か 1 の値を取得するよう
指定します
引数が整数の場合は
最大値を含めないため
値は 0 か 1 です
2 にはなりません
ここで 0 かどうかを
確認します

English: 
So basically, evens or odds,
flip a coin, did you give me a 0?
If you did, then my first value
is going to be negative 1,
so I'm going to be going left.
Otherwise, positive 1, going right.
And then for my Y,
I'm going to be doing something
like UnityEngine.
Random.Range.
Now, I am not doing the same here,
where I'm going to go 0 to 2
for either left or right,
because if I did 
negative 1 or positive 1,
what effectively would happen,
is the ball would just go up and down
so it'd be doing major jumps
at 45-degree angles always,
always 45-degree angles,
and so the game would be
fairly predictable,
because it's either going to go
upper left, upper right,
lower left, or lower right.
So instead, I'm going 
to do Random.Range
and I'm just going 
to say negative .5f to .5f,

Japanese: 
偶数奇数やコインの裏表のように
0 かどうかを確認します
0 の場合は最初の値が
-1 となり
左に動きます
0 以外は +1 となり
右に動きます
Y に関しては
「UnityEngine.Random.Range」
と記述します
0 から 2 で左か右かという
形をそのまま使用する
ことはしません
-1 か +1 にすると
実質的にはボールが
上か下にしか
動きません
つまり常に 45 度の
角度でボールが
跳ね返ることになり
ゲームの意外性がかなり
薄れます
左上か右下
左下か右下にしか
動かないからです
代わりに Random.Range を
使用して
「-.5f, .5f」と指定します

Japanese: 
どちらも float なので
最大値と最小値を含み
-.5 から +.5 までの
数値が返されます
デシジョンツリーは
ないので
Y 軸に若干の
曲線変動を追加し
Z 軸は 0f とします
.normalized として
ベクトルを正規化します
同じ速度で
その方向にボールが動きます
それが完了したら
「Vector3 speed = dir *」
と記述して
先ほど作成した
「ballSpeed」を続けます
方向ベクトルにボールの速度を
掛けたものです
ここで「PhysicsVelocity」と
記述して
新しい PhysicsVelocity
コンポーネントを宣言します
velocity と名前をつけて
「= new PhysicsVelocity」と記述します
この中で新しく
「Linear = speed」と記述し

English: 
and since they're floats,
they're inclusive,
so they give me a number
between negative .5 and positive .5.
And that's it,
there's no decision tree there,
so we're just going to have
some slight arc variance there
on the y-axis, and then finally,
0f on the z-axis.
And I'm going to say normalized...
normalize that vector for me.
There we go, that way they go
the same speed no matter what.
And then once I've done that,
I'm going to say Vector3 speed
is going to be equal to
my direction vector I just created,
times ballSpeed.
There you go, so our direction vector
times the speed of the ball.
And now, I'm going 
to say PhysicsVelocity,
I'm going to declare a new
PhysicsVelocity component,
which I'm going to call velocity,
equals new PhysicsVelocity, like so.
And inside here I'm going to say
so my new Linear speed
is going to be equal to speed,

Japanese: 
「Angular = float3.zero」
と記述します
間違えました
方向を
変えないようにします
タブを修正します
間違えて Insert キーを
押したようです
できました
manager に
コンポーネントを
追加するよう指示します
コンポーネントデータを
いくつか追加します
ChunkComponentData は違います
ビデオの後半ですが
スペルミスです
次にエンティティを
指定します
このボールです
先ほど計算した
速度を指定します
こんな感じです
ボールがスポーンされるので
ここに戻ります
最後に
ballPrefab に戻って
テスト用に追加した最初の
速度を削除します
ballPrefab を
0 に設定します
「Initial Linear Velocity」です
では内容を保存して
再生ボタンを押してみましょう

English: 
and my new Angular speed
is going to be equal to float3.zero.
Not that one.
So we're going to say,
you are not turning at all.
And then I'll get my tabs right...
that's not right, I hit the Insert Key
on accident there.
There we go.
And finally, "Hey, manager,
so I want you 
to add a component for me."
So let's add some 
component data here.
And--not ChunkComponentData.
Getting late into the video
and so I am having some typos.
Then it's going to say,
"Well, what entity?"
Well, this ball 
and I want you to give it
this velocity 
that I just calculated.
So there we go.
So now, we're spawning 
this ball here,
and so I'm going to come back here.
The last bit I want to do,
is I want to go back to my ballPrefab
and remove that initial velocity
I put on there for testing.
So on my ballPrefab
I'll set that back to 0,
that Initial Linear Velocity.
I will Save everything,
and get ready to press Play.

Japanese: 
うまくいくとよいですね
どうなるでしょうか
最初はボールがなく
カウントダウンが行われます
ボールがスポーンされ
ゲーム開始です
これが『Pong』です
話しながらプレイするのは
難しいですね
問題ないようです
ボールがスポーンされ
続けます
大丈夫ですね
以上が『Pong』の
DOTS 実装例です
かなり長いビデオなので
複雑に見える
かもしれませんが
実際には
作成にそれほど時間は
かかりません
DOTS を理解していれば
非常に簡単です
実際かなりシンプルな
ゲームです
ですが
さまざまな構文や
できること
その他の重要ポイントなどを
詳細に
説明しました
これで終了です
このビデオはオンラインで参照できます

English: 
Fingers crossed.
Let's see what we get here.
So no ball to start with...
it's counting down.
And then it's going to spawn the ball,
and then, there we go.
We have Pong.
And it's hard to play
with myself while talking.
And then, yeah, there we go.
And so the ball is going 
to keep spawning,
and that's it.
Cool, so that is our
DOTS implementation of Pong.
It seems maybe 
a little bit more complex
since this was 
a decently long video,
though in reality,
it didn't take very long to make.
And once you understand DOTS,
it kind of just moves very smoothly.
So it's a fairly simple game,
in actuality.
But I wanted to make sure
that I fully explained
the various syntaxes
and the things that you could do,
and maybe some of the gotchas,
and stuff like that.
So there it is.
This repo is available online.

English: 
You can download this project
and this code,
the link will be in the description
so feel free to check that out.
Feel free to follow up
with any questions you might have.
Otherwise, hopefully, this has been
a decent video and project
for learning some 
of the new syntax.
As always, reach out 
to me on Twitter...
I'm @mikegeig or wherever else...
and just let me know 
what you create.

Japanese: 
このプロジェクトとコードは
ダウンロードできます
説明欄にリンクがあるので
参考にしてください
質問がある方はお気軽に
お問い合わせください
またこのビデオと
プロジェクトは
いくつかの新しい構文の
学習に最適です
Twitter から私に
質問してくれても構いません
@mikegeig で検索して
皆さんが作成したものを
見せてください
