20200519のUnityに関する記事は3件です。

UniTask2(RC版)まとめ

UniTask2

UniTaskが大きくアップデートされて、バージョン2系がRCとなりました。
今回はいち早くその変更点をまとめていきます。

Ver 2.0.7-rc7準拠で書いています。変更があり次第また直します。

破壊的変更

まずは1系からの破壊的変更。導入時に気をつける必要があるところです。

名前空間の変更

名前空間がUniRx.AsyncからCysharp.Threading.Tasksに変更されました。
もともとUniRxのライブラリの一部だった名残なのですが、今回のアップデートで完全に名残がなくなりました。

UniTaskのawait2度漬け禁止

同じUniTaskに対しての2回以上のawaitが明確に禁止となりました。
IValueTaskSource準拠の挙動なので、これは本家ValueTaskと同じ挙動です。

UniTaskの2回以上のawait禁止
private async UniTaskVoid DoAsync(CancellationToken token)
{
    try
    {
        var uniTask = GetAsync("https://unity.com/ja", token);

        // 1回目のawaitは問題ない
        await uniTask;

        // 同じオブジェクトに対して2回以上のawaitはできない
        // (InvalidOperationExceptionが発行される)
        await uniTask;
    }
    catch (InvalidOperationException e)
    {
        Debug.LogException(e);
    }
}

private async UniTask<string> GetAsync(string uri, CancellationToken token)
{
    var uwr = UnityWebRequest.Get(uri);
    await uwr.SendWebRequest().ConfigureAwait(cancellation: token);
    return uwr.downloadHandler.text;
}

Preserve()

もし同じUniTaskを2回以上awaitする必要があるならば、Preserve()を利用しましょう。

Preserve()
private async UniTaskVoid DoAsync(CancellationToken token)
{
    try
    {
        var uniTask = GetAsync("https://unity.com/ja", token);

        // Preserve()で何回でもawait可能なUniTaskに変換
        var reusable = uniTask.Preserve();

        await reusable;
        await reusable;
    }
    catch (InvalidOperationException e)
    {
        Debug.LogException(e);
    }
}

AsyncOperationawaitするときのConfigureAwait廃止

AsyncOperationawaitするときに利用できていたConfigureAwaitが廃止となりました。
これからはIProgress<float>CancellationTokenを指定したい場合はToUniTask()またはWithCancellation()を利用する必要があります。

private async UniTask<string> GetAsync(string uri, CancellationToken token)
{
    using (var uwr = UnityWebRequest.Get(uri))
    {
        // CancellationTokenを指定
        await uwr.SendWebRequest().WithCancellation(token);
        return uwr.downloadHandler.text;
    }
}
// IProgress<float>を指定したい場合(あとついでにCancellationToken)
var urw2 = UnityWebRequest.Get("https://unity.com/ja");
await urw2.SendWebRequest()
    .ToUniTask(
        Progress.Create<float>(x => Debug.Log(x)),
        cancellationToken: token);

UniTask.Lazyの戻り値の変更

上記の多重await禁止の変更をうけて、UniTask.Lazyの戻り値がAsyncLazyに変換されました。

public static AsyncLazy Lazy(Func<UniTask> factory)
public static AsyncLazy<T> Lazy<T>(Func<UniTask<T>> factory)

使い勝手としてはあまり変わってはいません。

UniTask.WhenAnyの戻り値変更

WhenAnyの戻り値も変更されました。

public static async UniTask<(int winArgumentIndex, (bool hasResult, T0 result0), (bool hasResult, T1 result1), (bool asResult, T2 result2))> 
WhenAny<T0, T1, T2>()
public static UniTask<(int winArgumentIndex, T1 result1, T2 result2, T3 result3)> WhenAny<T1, T2, T3>()

UniTask.DelayFrameの戻り値変更

UniTask.DelayFrameの戻り値がUniTask<int>からUniTaskに変更されました。

既存機能への追加機能とか

全体的なパフォーマンスの向上

全体的にパフォーマンスが向上しています。
内部でUniTaskAsyncMethodBuilderRunnerの再利用が自動的に行われるようになり、ゼロアロケーションで動作するようになりました。

UniTaskCompletionSourceが再利用可能に

UniTaskCompletionSourceReset()メソッドが追加されました。
こちらを利用することでUniTaskCompletionSourceを再利用することができるようになりました。

AutoResetUniTaskCompletionSource追加

AutoResetUniTaskCompletionSourceも追加されました。
こちらはUniTaskCompletionSourceと挙動は同じですが、破棄したときに内部のインスタンスが自動的に再利用される仕組みになっています。

UniTaskCompletionSourceとの使い分けですが、何度も同じインスタンスを再利用するならUniTaskCompletionSourceを使う。
使い捨てで都度新しいものを使うならAutoResetUniTaskCompletionSourceを使う。
という使い分けをするとよいでしょう。

ファクトリメソッドが追加

ファクトリメソッドがいくつか追加されました。

  • UniTask.Create
  • UniTask.Defer
  • UniTask.Action
  • UniTask.UnityAction
  • UniTask.WaitUntilCanceled

PlayerLoopTiming追加

PlayerLoopTimingが追加され、次の種類となりました。

  • Initialization
  • LastInitialization
  • EarlyUpdate
  • LastEarlyUpdate
  • FixedUpdate
  • LastFixedUpdate
  • PreUpdate
  • LastPreUpdate
  • Update
  • LastUpdate
  • PreLateUpdate
  • LastPreLateUpdate
  • PostLateUpdate
  • LastPostLateUpdate

とくにLastPostLateUpdateが重要で、こちらはコルーチンにおけるWaitForEndOfFrameに相当します。
いままでUniTaskではyield return new WaitForEndOfFrame()ができなかったのですが、今回のアップデートから可能となりました。

JobHandle.WaitAsync

JobSystemJobHandleWaitAsyncが追加されました。
こちらを利用することで、任意のPlayerLoopのタイミングに切り替えてから完了待ちができます。

// WaitForEndOfFrame相当の待機をしてからComplete()
await jobHandle.WaitAsync(PlayerLoopTiming.LastPostLateUpdate);

AsyncTriggerメソッドのIUniTaskAsyncEnumerable対応

AsyncTrigger系のメソッド(this.GetAsyncCollisionEnterTriggerとか)がIUniTaskAsyncEnumerableに対応しました。

CancellationToken.WaitUntilCanceled

CancellationToken.WaitUntilCanceledという拡張メソッドが追加されました。
これを用いると、CancellationTokenからUniTaskに変換することができます。

生成されたUniTaskは、生成元になったCancellationTokenがキャンセルされたタイミングで完了状態になります。
「相手がキャンセルされるのを待つ」といった使い方ができます。

private void Start()
{
    var token = this.GetCancellationTokenOnDestroy();
    WaitForCanceledAsync(token).Forget();
}

private async UniTaskVoid WaitForCanceledAsync(CancellationToken token)
{
    await token.WaitUntilCanceled();
    Debug.Log("Canceled!");
}

DoTweenのawaitに対応

DoTweenawaitにも対応しました。

private void Start()
{
    MoveAsync().Forget();
}

private async UniTaskVoid MoveAsync()
{
    // 直列実行
    await transform.DOMove(transform.position + Vector3.up, 1.0f);
    await transform.DOScale(Vector3.one * 2.0f, 1.0f);

    // UniTask.WhenAllで並行実行して終了待機
    await
    (
        transform.DOMove(Vector3.zero, 1.0f).ToUniTask(),
        transform.DOScale(Vector3.one, 1.0f).ToUniTask()
    );
}

新機能

UniTaskAsyncEnumerable/IUniTaskAsyncEnumerable

UniTaskAsyncEnumerableUniTask2の目玉機能です。

IUniTaskAsyncEnumerable<T>C# 8.0IAsyncEnumerable<T>UniTaskとして実装したものです。
なんとこちらはC# 7.x系のUnityでも利用可能になっています。

何をするためのものかというと、「非同期処理を複数個まとめて扱う」ことができるようになる機能です。
ObservableIObservable<T>)と似ていますが、こちらはPull型として機能するという違いがあります。

image.png

Observableとの使い分け

ObservablePush型なのに対して、UniTaskAsyncEnumerablePull型です。
そのためUniTaskAsyncEnumerableでは非同期処理の実行タイミングを受信側でコントロールできるというメリットがあります。

UniTaskAsyncEnumerableで複数の非同期処理を扱う
private async void Start()
{
    var token = this.GetCancellationTokenOnDestroy();

    var uris = new[]
    {
        "https://www.google.com/",
        "https://unity.com/ja",
        "https://github.com/"
    };


    // URIのリストに対してアクセスしてデータをとってくる
    // ただし常に実行される通信は同時に1つであり、
    // 前回のものが完了しないと次の通信に進まない
    await uris.ToUniTaskAsyncEnumerable()
        // 通信完了を待機してメッセージを発行する
        .SelectAwait(async x => await FetchAsync(x))
        .ForEachAsync(x => Debug.Log(x), token);
}


private async UniTask<string> FetchAsync(string uri)
{
    using (var uwr = UnityWebRequest.Get(uri))
    {
        await uwr.SendWebRequest();
        if (uwr.isNetworkError || uwr.isHttpError)
        {
            throw new Exception($"Error>{uwr.error}");
        }

        return uwr.downloadHandler.text;
    }
}

対するObservablePush型のため、多数のObserverに対してメッセージをブロードキャストするのに向いています。

複数個の非同期処理を管理する場合は基本にはUniTaskAsyncEnumerableを使う。
イベント駆動を制御する場合にはObservableを使う。

という使い方をするとよいでしょう。

ForEachAsync/ForEachAwaitAsync

C# 8.0であればawait foreachが使えるのですが、それが使えないUnityバージョンでは代替としてForEachAsyncを利用します。
感覚としては、IObservable<T>に対するSubscribe()に似ています。
ですがこちらは「ForEachAsync()の完了をさらにawaitで待つ」といったことが可能となります。

ForEachAsync
private async void Start()
{
    var token = this.GetCancellationTokenOnDestroy();

    // EveryUpdate()は毎フレームのタイミングで完了するUniTaskを返す
    await UniTaskAsyncEnumerable.EveryUpdate()
        .Select((_, x) => x)
        // 5回まで実行する
        .Take(5)
        // ForEachAsyncで待機する
        .ForEachAsync(async _ => Debug.Log(Time.frameCount), token);

    Debug.Log("Done!");
}

また、ForEachAsyncの他にForEachAwaitAsyncもあります。
こちらはデリゲートの内部でasync/awaitが利用でき、この非同期処理が完了するまで次のメッセージを取りに行きません。

ForEachAwaitAsync
await UniTaskAsyncEnumerable.EveryUpdate()
    .Select((_, x) => x)
    // 5回まで実行する
    .Take(5)
    // ForEachAwaitAsyncで待機する
    .ForEachAwaitAsync(async _ =>
    {
        // 10フレーム待ってから次のメッセージを取りに行く
        await UniTask.DelayFrame(10, cancellationToken: token);
    }, token);

注意:ForEachAsyncasync/awaitする

ミスしそうな点として、ForEachAsyncasync/awaitを書いてしまうことです。
こちらの場合、コンパイルエラーとならずに動作してしまうのにForEachAwaitAsyncと動作がまったく異なってしまいます。

UniTask2 RC4でこちらの挙動はコンパイルエラーとなるようになり、安全になりました。

もしForEachAsyncを使いつつ、UniTaskVoidなasync/awaitを使いたい(非同期処理だけどその結果待ちをせずに次のMoveNextAsync()を呼んで欲しい)場合はUniTask.Voidを併用しましょう。

private async void Start()
{
    var token = this.GetCancellationTokenOnDestroy();

    await UniTaskAsyncEnumerable.EveryUpdate()
        .Select((_, x) => x)
        .Take(5)
        // 非同期処理を登録できるがこのasync/awaitの結果を
        // 待たずにForEachAsyncはすぐ次のメッセージを取りに行く
        .ForEachAsync(_ => UniTask.Void(async () =>
        {
            Debug.Log("before await:" + Time.frameCount);
            // ForEachAwaitAsyncはここのawaitを待つ
            await UniTask.DelayFrame(10, cancellationToken: token);
            Debug.Log("after await:" + Time.frameCount);
        }), token);

    Debug.Log("Done!");
}

UniTaskAsyncEnumerableの作り方

UniTaskAsyncEnumerableはさまざまな方法で生成することができます。

ファクトリメソッド

  • Return
  • Repeat
  • Empty
  • Throw
  • Never
  • Range
  • EveryUpdate
  • Timer
  • TimerFrame
  • Interval
  • IntervalFrame
  • EveryValueChanged

他のデータ構造から変換

  • IEnumerable<T>
  • IObservable<T>
  • Task<T>
  • UniTaskT>

uGUIコンポーネントから変換

uGUIイベントからの変換
public class FromUGui : MonoBehaviour
{
    [SerializeField] private Button _button;

    private void Start()
    {
        var token = this.GetCancellationTokenOnDestroy();

        // 連打防止ボタン
        // 1回ボタンを押したら2秒間無反応になる
        _button.OnClickAsAsyncEnumerable()
            .ForEachAwaitWithCancellationAsync(async (_, ct) =>
            {
                Debug.Log("Clicked!");
                await UniTask.Delay(2000, cancellationToken: ct);
            }, token);
    }
}

AsyncTriggerを利用する

this.GetAsyncCollisionEnterTrigger()など。

Channel

ChannelGoにおけるChannelと同義です。
挙動としてはObservableにおけるSubjectに相当します。

なお、Channelは内部でメッセージをキューイングします。

Channelの例
 private void Start()
{
    // Channel作成
    var channel = Channel.CreateSingleConsumerUnbounded<int>();

    // Channelを読み取るときはReaderを使う
    var reader = channel.Reader;

    // メッセージの待受
    WaitForChannelAsync(reader, this.GetCancellationTokenOnDestroy()).Forget();

    // 書き込むときはWriteを使う
    var writer = channel.Writer;

    // IObserver<T>.OnNext() に相当
    writer.TryWrite(1);
    writer.TryWrite(2);
    writer.TryWrite(3);

    // IObserver<T>.OnCompleted() に相当
    writer.TryComplete();

    // TryComplete()に例外を渡すと IObserver<T>.OnError() に相当
    // writer.TryComplete(new Exception(""));
}

private async UniTaskVoid WaitForChannelAsync(ChannelReader<int> reader, CancellationToken token)
{
    try
    {
        // 1回だけ読み取るならReadAsync
        var result1 = await reader.ReadAsync(token); // UniTask<int>
        Debug.Log(result1);

        // 完了するまで読み続けるなら ReadAllAsync
        // IObservable<T>.Subscribe() に相当
        await reader.ReadAllAsync() // IUniTaskAsyncEnumerable<int>
            .ForEachAsync(x => Debug.Log(x), token);

        Debug.Log("Done");
    }
    catch (Exception e)
    {
        Debug.LogException(e);
    }
}

AsyncReactiveProperty

AsyncReactivePropertyUniRxReactivePropertyUniTask版です。
ベースとしてIUniTaskAsyncEnumerable<T>が利用されています。
ReactivePropertyはベースがIObservable<T>

基本的な使い方はReactivePropertyと変わりません。

AsyncReactiveProperty
private void Start()
{
    var token = this.GetCancellationTokenOnDestroy();

    // AsyncReactiveProperty生成
    var asyncReactiveProperty = new AsyncReactiveProperty<string>(null);

    // 待受開始
    WaitForAsync(asyncReactiveProperty, token).Forget();

    // Valueプロパティに値をセットすると
    // MoveNextAsync() が次に進む
    asyncReactiveProperty.Value = "Hello!";

    // Dispose()するとこのAsyncReactivePropertyが完了する
    asyncReactiveProperty.Dispose();
}

private async UniTaskVoid WaitForAsync(
    IReadOnlyAsyncReactiveProperty<string> asyncReadOnlyReactiveProperty,
    CancellationToken token)
{
    // Valueプロパティで現在値を取得可能
    var current = asyncReadOnlyReactiveProperty.Value;
    Debug.Log(current);

    // IUniTaskAsyncEnumerable<T>として扱える
    var result = await asyncReadOnlyReactiveProperty
        // null以外の値がセットされるのを待つ
        .FirstOrDefaultAsync(x => x != null, cancellationToken: token);

    Debug.Log(result);
}

UniTask.Linq

IUniTaskAsyncEnumerable<T>にはLINQメソッドが用意されています。
使えるメソッドは次です。

同期型

  • AggregateAsync
  • AllAsync
  • AnyAsync
  • AsUniTaskAsyncEnumerable
  • AverageAsync
  • Buffer
  • Append
  • Prepend
  • Cast
  • Concat
  • ContainsAsync
  • CountAsync
  • DefaultIfEmpty
  • Distinct
  • DistinctUntilChanged
  • Do
  • ElementAtAsync
  • ElementAtOrDefaultAsync
  • Except
  • FirstAsync
  • FirstOrDefaultAsync
  • ForEachAsync
  • GroupBy
  • GroupJoin
  • Intersect
  • Join
  • LastAsync
  • LastOrDefaultAsync
  • LongCountAsync
  • MaxAsync
  • MinAsync
  • OfType
  • OrderBy
  • OrderByDescending
  • Reverse
  • Select
  • SelectMany
  • SequenceEqualAsync
  • SingleAsync
  • SingleOrDefaultAsync
  • Skip
  • SkipLast
  • SkipWhile
  • SumAsync
  • Take
  • TakeLast
  • TakeWhile
  • ToArrayAsync
  • ToDictionaryAsync
  • ToHashSetAsync
  • ToListAsync
  • ToLookupAsync
  • ToObservable
  • Union
  • Where
  • Zip
  • CombineLatest
  • Pairwise
  • Queue
  • SkipUntilCanceled
  • TakeUntilCanceled
  • Publish

非同期型

AwaitAsyncがついているものはasync/awaitを内部で利用できます。

  • AggregateAwaitAsync
  • AllAwaitAsync
  • AnyAwaitAsync
  • AverageAwaitAsync
  • CountAwaitAsync
  • DistinctAwait
  • DistinctUntilChangedAwait
  • DoAwait
  • FirstAwaitAsync
  • FirstOrDefaultAwaitAsync
  • ForEachAwaitAsync
  • GroupByAwait
  • GroupJoinAwait
  • JoinAwait
  • LastAwaitAsync
  • LastOrDefaultAwaitAsync
  • LongCountAwaitAsync
  • MaxAwaitAsync
  • MinAwaitAsync
  • OrderByAwait
  • OrderByDescendingAwait
  • SelectAwait
  • SelectManyAwait
  • SingleAwaitAsync
  • SingleOrDefaultAwaitAsync
  • SkipWhileAwait
  • SumAwaitAsync
  • TakeWhileAwait
  • ToDictionaryAwaitAsync
  • ToLookupAwaitAsync
  • WhereAwait
  • ZipAwait

こちらはCancellationTokenを内部で必要とするときに使います。

  • AggregateAwaitWithCancellationAsync
  • AnyAwaitWithCancellationAsync
  • AverageAwaitWithCancellationAsync
  • CountAwaitWithCancellationAsync
  • DistinctAwaitWithCancellation
  • DistinctUntilChangedAwaitWithCancellation
  • DoAwaitWithCancellation
  • FirstAwaitWithCancellationAsync
  • FirstOrDefaultAwaitWithCancellationAsync
  • ForEachAwaitWithCancellationAsync
  • GroupByAwaitWithCancellation
  • GroupJoinAwaitWithCancellation
  • JoinAwaitWithCancellation
  • LastAwaitWithCancellationAsync
  • LastOrDefaultAwaitWithCancellationAsync
  • LongCountAwaitWithCancellationAsync
  • MaxAwaitWithCancellationAsync
  • MinAwaitWithCancellationAsync
  • OrderByAwaitWithCancellation
  • OrderByDescendingAwaitWithCancellation
  • SelectAwaitWithCancellation
  • SelectManyAwaitWithCancellation
  • SingleAwaitWithCancellationAsync
  • SingleOrDefaultAwaitWithCancellationAsync
  • SkipWhileAwaitWithCancellation
  • SumAwaitWithCancellationAsync
  • TakeWhileAwaitWithCancellation
  • ToDictionaryAwaitWithCancellationAsync
  • ToLookupAwaitWithCancellationAsync
  • WhereAwaitWithCancellation
  • ZipAwaitWithCancellation

補足: PushベースのUniTaskAsyncEnumerableの注意点

IUniTaskAsyncEnumerable<T>Pull型として動作します。
そのためメッセージの受信準備が整い、内部でイテレータのMoveNextAsync()が実行されたタイミングで次のメッセージを取りに行きます。

ですが、UniTaskAsyncEnumerableではメッセージ発行がPushIUniTaskAsyncEnumerable<T>も存在します(ややこしい)

  • UniTask.EveryUpdate()
  • AsyncReactiveProperty
  • AsyncTriggerより生成したもの
  • uGUIのイベントなどから変換したもの

これらはPushされてきたイベントをIUniTaskAsyncEnumerable<T>として提供します。
そのためMoveNextAsync()とタイミングが合わなかった場合は、その間に発行されたイベントは取りこぼされるという点に注意が必要です。

image.png

逆に、このイベントの取りこぼしを利用して処理を組むこともできます。

イベントの取りこぼしを利用した例
// uGUIのボタンの連打防止
// 1回ボタンを押したら2秒間無反応になる

// ForEachAwaitAsyncが待機中に発行されたメッセージは無視するという
// 性質を利用している
_button.OnClickAsAsyncEnumerable()
    .ForEachAwaitWithCancellationAsync(async (_, ct) =>
    {
        Debug.Log("Clicked!");
        await UniTask.Delay(2000, cancellationToken: ct);
    }, token);

取りこぼしが嫌なら Queue() を使おう

QueueUniTask.Linqが提供するLINQメソッドの1つです。

IUniTaskAsyncEnumerable<T>に対して先にMoveNextAsync()を実行し、その結果をキューに詰めて再度IUniTaskAsyncEnumerable<T>として提供します。
ObservableでいうところのPublish()に相当します)

Queueを使えばイベントの取りこぼしを防ぐことができるため、必要に応じて利用しましょう。

Queue
private void Start()
{
    var token = this.GetCancellationTokenOnDestroy();

    // AsyncReactiveProperty生成
    var asyncReactiveProperty = new AsyncReactiveProperty<string>("Initialize!");

    // 待受開始
    WaitForAsync(asyncReactiveProperty, token).Forget();

    // 値を設定
    asyncReactiveProperty.Value = "Hello!";
    asyncReactiveProperty.Value = "World!";
    asyncReactiveProperty.Value = "Thank you!";

    asyncReactiveProperty.Dispose();
}

private async UniTaskVoid WaitForAsync(
    IReadOnlyAsyncReactiveProperty<string> asyncReadOnlyReactiveProperty,
    CancellationToken token)
{
    // AsyncReactiveProperty はキューイングしてくれないので
    // タイミングによってはメッセージの取りこぼしが置きうる
    // 取りこぼしが嫌ならQueueを併用する
    await asyncReadOnlyReactiveProperty
        .Queue() // Queueを挟む
        .ForEachAwaitWithCancellationAsync(async (x, ct) =>
        {
            Debug.Log(x);
            // 1秒待って次の値を取りに行く
            await UniTask.Delay(1000, cancellationToken: ct);
        }, token);
}

まとめ

C# 8.0IAsyncEnumerable相当の処理をいち早くUnityでも利用できるため、かなり期待が高いアップデートとなりました。
UniTaskAsyncEnumerableAsyncReactivePropertyが刺さる人にはかなり刺さる機能でしょう(自分はさっそく使いたい)

ただ、これの登場によってIObservable<T>との使い分けが一層ややこしくなった可能性もあります。
UniRxで苦戦していた人はおそらくUniTaskAsyncEnumerableでも苦戦するような予感が…。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

正しいプログラミングの学習方法について語る

今回は プログラミング学習について 見ていきます。 

特に独学での学習者はこれらの点を気をつけて学習したほうがいいです。

 1 完璧主義を目指してはいけない 

プログラミングの学習において、完璧主義を目指すのはほんとに自殺行為といえます。

これは学習でもそうですけど、プロダクトを作るときも同じです。 

最初は6割や7割ベースで 全然いいと思う。 

特に独学でやっている人ほど、完璧主義を目指すのはやめましょう。

 2 暗記も必要もない

学校の勉強のような、暗記も必要ないです。

覚えるのは基礎だけでいいわけで あとは

必要なときに 必要な分だけ覚えていくのがいいと思う。 

なので メソッドやライブラリなどを全部覚える必要はないです。

 3 小さい目標をつけるべし

わたしもプログラミングは全部独学で覚えたんですけど 
独学の場合だと、やはりモチベーションが続かないんですよね。 
モチベも続かないし、普通に挫折もすると思います。 

挫折しない人なんているんでしょうかね???

なので 小さいな目標を立てることが重要です。 

例えば 1日 10ページすすめるとか 

1日 1回はアウトプットするとか 

サンプルコードをやるとかね。 

因みに習慣の法則というものがありまして 

21日間 続けることが出来れば、 そのあとも継続できるようになるので 

とりあえず 3週間は続ける事が大事。

 

 4 インプットよりも アウトプットを増やしなさい

インプット学習ってみんな普通にするんですよ。 

でも アウトプットしている人はほんとに少ないです。 

みんな、 Udemyとかの動画は見ているけど 
それで終わっている人が多いからね。 

なので、アウトプットする習慣を身に付けることが最も大事。

インプットよりも、どうやってアウトプットできるかを
考えるべし。 

初心者であれば、 パイザのコードクロニクルなどが
おすすめです。

 5 とりあえず ググり癖はつけるべし

分からなければ すぐに調べる。

調べ方は色々あるけど  

目的で検索するか、 コードをコピペしていくのが基本。

で これは 誰かに質問するときも同じで 
質問するときも、 ちゃんと調べてから質問すること。 

あと 何でもかんでも、質問すればいいってわけじゃないからね。 

あんまり、質問ばっかりしていると嫌われるよん。

PS 

C#プログラミングマスター講座
発売中でーす。

只今70%OFFセールやってます。

C#が分からないと Unityもできるようにならないので 
Unityをやるひとにも おすすめです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自己紹介

こんにちは。初投稿です。
投稿の練習がてら自己紹介をします。

私は現在高校で数学の教員をやっています。
数学の授業で使えるようなソフトやページを作っています。

私がプログラミングと出会ったのは大学2年生の時に受けた授業でした。そこではRubyを扱い、全く理解できなかった私はプログラミングに興味を持つことはありませんでした。
しかし大学3年生の春、某大手通信制高校の長期インターンを始めたら、そのインターンではプログラミングを扱う機会がとても多く、扱う教材も面白く私はプログラミングへのめり込んでいきました。
インターンでは主に、HTML、CSS、JavaScript、python、Unity(C#)などを扱いました。紹介しているものも、ここら辺中心に作っています。

以下にインターン時代に作ったものを載せておきます。
円周率πの近似~モンテカルロ法~(HTML、JavaScript)
mc.png
polygons.png

教員になってから作ったものは以下のものです。
サイコロを振りまくったら本当に1/6になるのか(Unity)
ダウンロード.gif
数学の展開、因数分解をひたすらやるゲーム(Unity)
これはまだ制作途中なので画像だけです。
S__89874440.jpg
S__89874442.jpg
S__89874443.jpg
S__89874444.jpg

サイコロと数学のゲームに関しては別記事でもう少し詳しく紹介できたらなと思います。
コメントやアドバイスをいただけると幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む