$30 off During Our Annual Pro Sale. View Details »

存在しないアセットへの参照と
未公開アセットでのネタバレに
どう立ち向かうか / How to prevent missing assets and spoilers by assets

Kuniwak
PRO
February 03, 2023

存在しないアセットへの参照と
未公開アセットでのネタバレに
どう立ち向かうか / How to prevent missing assets and spoilers by assets

弊社における3大バグの一角であるマスターデータとアセットの不整合を早期発見するライブラリの仕組みを紹介します。クラッシュや見た目の問題を引き起こす存在しないアセットへの参照や、データ解析によるネタバレを招くネタバレアセットの混入にお困りの方はぜひ聞いてみてください。

https://meetup.unity3d.jp/jp/events/1387

Kuniwak
PRO

February 03, 2023
Tweet

More Decks by Kuniwak

Other Decks in Programming

Transcript

  1. ଘࡏ͠ͳ͍Ξηοτ΁ͷࢀরͱ

    ະެ։ΞηοτͰͷωλόϨʹ

    Ͳ͏ཱͪ޲͔͏͔
    $"VOJUZ,VOJXBL %F/"$P -UE

    View Slide

  2. ,VOJXBL
    VOJUZNFUBDIFDLΛ࡞ͬͨਓɻ
    ήʔϜ։ൃ͔Βۤ͠ΈΛऔΓআ͖͍ͨɻ
    Ͱ੩తղੳثΛ։ൃ͍ͯ͠Δɻ
    2

    View Slide

  3. ఻͍͑ͨ͜ͱ
    3

    View Slide

  4. ΞηοτͱϚελʔσʔλͷෆ੔߹ͷ༧๷ʹ͸

    Ϛελʔσʔλ͔Βࢀর͞ΕΔ͢΂ͯͷ

    ΞηοτΛ೺ѲͰ͖ΔΑ͏ʹ͢ΔͱΑ͍
    4

    View Slide

  5. ༻ޠͷఆٛ
    5

    View Slide

  6. Ϛελʔσʔλ
    ήʔϜͷৼΔ෣͍ΛܾΊΔύϥϝʔλͷ͏ͪɺ

    શϢʔβʔͰڞ༗͞Ε͍ͯͯมಈ͠ͳ͍΋ͷɻ

    දͰදݱ͞ΕΔ͜ͱ͕ଟ͍ɻ
    6

    View Slide

  7. ΩϟϥΫλʔ*% ໊લ )1 ΞΠίϯ
    'PP 'PP
    #BS" #BS
    #BS# #BS
    Ϛελʔσʔλͷྫ

    View Slide

  8. Ξηοτ
    lΞηοτͱ͸ɺήʔϜ΍ΞϓϦέʔγϣϯΛ࡞੒͢ΔͨΊʹɺ

    6OJUZϓϩδΣΫτͰ࢖༻͢ΔΞΠςϜͷ͜ͱɻΞηοτ͸ɺ

    %ϞσϧɺςΫενϟɺεϓϥΠτɺα΢ϯυΤϑΣΫτɺ

    ԻָͳͲɺϓϩδΣΫτͷࢹ֮త·ͨ͸ௌ֮తཁૉΛද͠·͢z
    8
    https://docs.unity3d.com/ja/current/Manual/AssetWorkflow.html

    View Slide

  9. ΞηοτΞυϨε
    ΞηοτΛҰҙʹಛఆ͢Δจࣈྻɻ"EESFTTBCMFTͷ

    ΞυϨεͰ΋ྑ͍͠ɺ"EESFTTBCMFTͱಉ༷ͷ

    ΞηοτγεςϜ͕ൃߦ͢ΔΞυϨεͰ΋Α͍ɻ
    9

    View Slide

  10. ฐࣾͷήʔϜ͕Ϛελʔσʔλ͔Β

    ࢀর͞ΕΔΞηοτΛಡΈࠐΉ·ͰͷྲྀΕ
    10

    View Slide

  11. 11
    ϚελʔσʔλʹΞηοτ΁ͷ

    ෦෼จࣈྻ͕هࡌ͞Ε͍ͯΔ
    ෦෼จࣈྻʹ৭ʑҾͬ෇͚ͯ

    ΞηοτΞυϨε͕׬੒͢Δ
    ͜ͷΞηοτΞυϨεΛ΋ͱʹ

    Ξηοτ͕ಡΈࠐ·ΕΔ
    ΩϟϥΫλʔ*% ʜ ΞΠίϯ
    ʜ 'PP
    ʜ #BS
    ʜ #BS
    ΩϟϥΫλʔ*%ͷ

    ΞΠίϯͷΞηοτ

    ΞυϨεΛੜ੒
    "TTFUT*DPOT#BSQOH

    View Slide

  12. 12
    ΩϟϥΫλʔ*% ʜ ΞΠίϯ
    ʜ 'PP
    ʜ #BS
    ʜ #BS
    "TTFUT*DPOT'PPQOH
    "TTFUT*DPOT#BSQOH
    "TTFUT*DPOT#BSQOH
    ΞηοτΞυϨε

    View Slide

  13. ฐࣾͷ๊͍͑ͯͨ՝୊
    13

    View Slide

  14. w Ϛελʔσʔλʹଘࡏ͠ͳ͍ΞηοτΛ

    ࢀর͍ͯ͠Δ΋ͷ͕͋Δ
    w Ϛελʔσʔλ͔Βࢀর͞Εͯ

    ͍ͳ͍Ξηοτ͕ଘࡏ͢Δ
    14
    ϚελʔσʔλͱΞηοτͷෆ੔߹

    View Slide

  15. w Ϛελʔσʔλʹଘࡏ͠ͳ͍ΞηοτΛ

    ࢀর͍ͯ͠Δ΋ͷ͕͋Δ
    w Ϛελʔσʔλ͔Βࢀর͞Εͯ

    ͍ͳ͍Ξηοτ͕ଘࡏ͢Δ
    15
    ϚελʔσʔλͱΞηοτͷෆ੔߹
    ήʔϜ͕Ϋϥογϡ͢Δɺ͋Δ͍͸ҙਤ͠ͳ͍

    දݱʢςΫενϟͷܽଛ౳ʣʹͳͬͯ͠·͏

    View Slide

  16. w Ϛελʔσʔλʹଘࡏ͠ͳ͍ΞηοτΛ

    ࢀর͍ͯ͠Δ΋ͷ͕͋Δ
    w Ϛελʔσʔλ͔Βࢀর͞Εͯ

    ͍ͳ͍Ξηοτ͕ଘࡏ͢Δ
    16
    ϚελʔσʔλͱΞηοτͷෆ੔߹
    ެ։͢΂͖Ͱͳ͍Ξηοτ͕Ξηοτόϯυϧʹ

    ؚ·Εͯ͠·͍ɺղੳ͞ΕͯωλόϨͯ͠͠·͏

    View Slide

  17. w Ϛελʔσʔλʹଘࡏ͠ͳ͍ΞηοτΛ

    ࢀর͍ͯ͠Δ΋ͷ͕͋Δ
    w Ϛελʔσʔλ͔Βࢀর͞Εͯ

    ͍ͳ͍Ξηοτ͕ଘࡏ͢Δ
    17
    ϚελʔσʔλͱΞηοτͷෆ੔߹

    View Slide

  18. 2ͳͥෆ੔߹͕ى͜Δͷ͔
    18

    View Slide

  19. "ΞηοτͱϚελʔσʔλ͸
    ฒྻʹ։ൃ͞Ε͍ͯΔ͔Β
    19
    Ϛελʔ͍ͬͨ͡
    ΞηοτͰ͖ͨ
    Ϛελʔ͍ͬͨ͡
    ΞηοτͰ͖ͨ ΞηοτͰ͖ͨ
    Ϛελʔ͍ͬͨ͡

    View Slide

  20. ෆ੔߹Λ๷͙ͨΊʹ͸
    w ଘࡏ͠ͳ͍ΞηοτΛࢀর͍ͯ͠Δ

    ϚελʔσʔλΛݟ͚ͭΒΕΔΑ͏ʹ͢Δ
    w Ϛελʔσʔλ͔Βࢀর͞Ε͍ͯͳ͍

    ΞηοτΛݟ͚ͭΒΕΔΑ͏ʹ͢Δ
    20

    View Slide

  21. ฐࣾͷͱͬͨΞϓϩʔν
    21

    View Slide

  22. 22
    "TTFU.BTUFS*OUFHSBUJPO5FTU
    "MM"TTFUT&YJTU"OE3FGFSFODFE
    "MM"TTFUT&YJTU"OE3FGFSFODFE T


    "MMFMFNFOUTFYJTUPOCPUI4FUT
    "TTFUT4USFBNJOH"TTFUT#BS$POTU
    "TTFUT4USFBNJOH"TTFUT#B[
    3VO"MM 3VO4FMFDUFE 3FSVO'BJMFE $MFBS3FTVMUT
    1MBZ.PEF &EJU.PEF
    &YBNQMF ⎋
    5FTU3VOOFS
    5FTU3VOOFS

    View Slide

  23. ෆ੔߹Λݟ͚ͭΔͨΊʹඞཁͳ΋ͷ
    23
    ࢀর͞Ε͏ΔΞηοτ͢΂ͯͷ

    ΞηοτΞυϨε
    ଘࡏ͢ΔΞηοτ͢΂ͯͷ

    ΞηοτΞυϨε
    ൺֱ͢Δͱ

    ෆ੔߹͕Θ͔Δ

    View Slide

  24. ඞཁͳ΋ͷʹඞཁͳ΋ͷ
    24
    ϚελʔσʔλશମΛಘΔ"1*
    Ϛελʔσʔλ͔ΒಘΒΕΔΞηοτ

    ΞυϨεશͯΛܭࢉ͢Δ"1*
    ͋ΔΞηοτ͔Βࢀর͞Ε͏Δ

    ͢΂ͯͷΞηοτΛܭࢉ͢Δ"1*
    ଘࡏ͢ΔΞηοτ͔ΒΞηοτ

    ΞυϨεΛٯࢉ͢Δ"1*
    ࢀর͞Ε͏ΔΞηοτ͢΂ͯͷ

    ΞηοτΞυϨε
    ଘࡏ͢ΔΞηοτ͢΂ͯͷ

    ΞηοτΞυϨε
    ൺֱ͢Δͱ

    ෆ੔߹͕Θ͔Δ

    View Slide

  25. ඞཁͳ΋ͷʹඞཁͳ΋ͷ
    25
    ϚελʔσʔλશମΛಘΔ"1*
    Ϛελʔσʔλ͔ΒಘΒΕΔΞηοτ

    ΞυϨεશͯΛܭࢉ͢Δ"1*
    ͋ΔΞηοτ͔Βࢀর͞Ε͏Δ

    View Slide

  26. ࣮ݱͨ͜͠ͱ
    26

    View Slide

  27. Ϛελʔσʔλ͔ΒಘΒΕΔ͢΂ͯͷ

    ΞηοτΞυϨεΛܭࢉ͢Δ"1*Λ

    ࣮૷͢Δ͜ͱʹͨ͠΋ͷͷʜ
    27

    View Slide

  28. ϥϯλΠϜίʔυͷ͞·͟·ͳͱ͜Ζʹ

    ΞηοτΞυϨεͷܭࢉॲཧ͕ॻ͔Ε͍ͯͯ஍ࠈ
    28

    View Slide

  29. ؤுͬͯ΍Γ͖͕ͬͨͱͯ΋ͭΒ͍ʜ
    29

    View Slide

  30. ϥϯλΠϜίʔυͷ͞·͟·ͳͱ͜Ζʹ

    ΞηοτΞυϨεͷܭࢉॲཧ͕ೖΒͳ͍Α͏ʹ

    ڽूͤ͞ΔϥΠϒϥϦΛ։ൃ͢Δ͜ͱʹͨ͠
    30

    View Slide

  31. ࣮૷ͨ͠ϥΠϒϥϦΛ

    ར༻ͨ͠ͱ͖ͷྲྀΕ
    31

    View Slide

  32. 32
    ΩϟϥΫλʔ*% ʜ ΞΠίϯ
    ʜ 'PP
    ʜ #BS
    ʜ #BS
    "TTFUT*DPOT'PPQOH
    "TTFUT*DPOT#BSQOH
    "TTFUT*DPOT#BSQOH
    ΞηοτΞυϨε
    ৽ͨʹΞηοτ͕௥Ճ͞ΕͨͷͰ
    ΞηοτΞυϨεΛ৽ઃ͍ͨ͠

    View Slide

  33. 33
    "TTFUT*DPOTJDPO/BNFQOH
    ΞηοτΞυϨεΛ෼ղͯ͠ߟ͑Δ
    ݻఆจࣈྻ ݻఆจࣈྻ
    ύϥϝʔλ

    View Slide

  34. ෼ղ͞ΕͨΞηοτΞυϨε͔ΒܭࢉنଇΛ
    4DSJQUBCMF0CKFDUͱͯ͠࡞੒͢Δ
    34
    "TTFUT*DPOTύϥϝʔλQOH
    ܭࢉنଇ

    View Slide

  35. 35
    *OTQFDUPS
    J
    &YBNQMF3FTPMWFS 3BX3FTPMWFS4FFE1BSBNT

    0QFO
    ʜ
    ʜ
    {}
    ʮܕύϥϝʔλ DPEF
    ʯʹ͸ʮJOUʯ΍ʮ'PP#BSʯ
    ͷΑ͏ͳίʔυʹॻ͘ͷͱಉ͡ه๏Ͱೖྗ͍ͯͩ͘͠͞
    Ϋϥε໊ &YBNQMF3FTPMWFS
    ϥϕϧ
    ύϥϝʔλએݴ
    ύϥϝʔλ
    ΞηϯϒϦ
    ܕ
    NTDPSMJC
    4ZTUFN4USJOH
    *OTQFDUPSͰΆͪΆͪຒΊΔ
    ύϥϝʔλ

    View Slide

  36. 36
    ηάϝϯτ
    ηάϝϯτ
    ηάϝϯτछผ
    ݻఆจࣈྻ
    4UBUJD
    ηάϝϯτ
    ηάϝϯτछผ
    ύϥϝʔλࢀর
    "TTFUT*DPOT
    1BSBNFUFS
    ύϥϝʔλ4ZTUFN4USJOH
    ϑΥʔϚοτ 5P4USJOH
    ͰจࣈྻԽ
    ηάϝϯτ
    ηάϝϯτछผ
    ݻఆจࣈྻ
    4UBUJD
    QOH
    $ϑΝΠϧΛ࡞੒
    ݻఆจࣈྻ
    ύϥϝʔλ
    ݻఆจࣈྻ

    View Slide

  37. 37
    ηάϝϯτ
    ηάϝϯτ
    ηάϝϯτछผ
    ݻఆจࣈྻ
    4UBUJD
    ηάϝϯτ
    ηάϝϯτछผ
    ύϥϝʔλࢀর
    "TTFUT*DPOT
    1BSBNFUFS
    ύϥϝʔλ4ZTUFN4USJOH
    ϑΥʔϚοτ 5P4USJOH
    ͰจࣈྻԽ
    ηάϝϯτ
    ηάϝϯτछผ
    ݻఆจࣈྻ
    4UBUJD
    QOH
    $ϑΝΠϧΛ࡞੒
    ຒΊऴΘͬͨΒίʔυੜ੒

    View Slide

  38. 38
    [global::PathResolver.ResolverGenerated(Label="StreamingAssets")]


    public static class ExampleResolver1


    {


    public static string Resolve(global::System.String param1)


    {


    var result = new StringBuilder();


    result.Append(ResolveSegment0());


    result.Append(ResolveSegment1(param1));


    result.Append(ResolveSegment2());


    return result.ToString();


    }


    public static string ResolveSegment0()


    {


    return "Assets/Icons/";


    }


    public static string ResolveSegment1(param1)


    {


    return param1.ToString();


    ੜ੒͞Εͨίʔυ

    View Slide

  39. 39
    [global::PathResolver.ResolverGenerated(Label="StreamingAssets")]


    public static class ExampleResolver1


    {


    public static string Resolve(global::System.String param1)


    {


    var result = new StringBuilder();


    result.Append(ResolveSegment0());


    result.Append(ResolveSegment1(param1));


    result.Append(ResolveSegment2());


    return result.ToString();


    }


    public static string ResolveSegment0()


    {


    return "Assets/Icons/";


    }


    public static string ResolveSegment1(param1)


    {


    return param1.ToString();


    ੜ੒͞Εͨίʔυ
    ύϥϝʔλΛ༩͑ͯΞηοτΞυϨεΛܭࢉ
    ݻఆจࣈྻ෦෼
    ύϥϝʔλ෦෼
    ݻఆจࣈྻ෦෼

    View Slide

  40. 40
    [global::PathResolver.ResolverGenerated(Label="StreamingAssets")]


    public static class ExampleResolver1


    {


    public static string Resolve(global::System.String param1)


    {


    var result = new StringBuilder();


    result.Append(ResolveSegment0());


    result.Append(ResolveSegment1(param1));


    result.Append(ResolveSegment2());


    return result.ToString();


    }


    public static string ResolveSegment0()


    {


    return "Assets/Icons/";


    }


    public static string ResolveSegment1(param1)


    {


    return param1.ToString();


    ੜ੒͞Εͨίʔυ
    BUUSJCVUFΛ͚͓͍ͭͯͯ͢΂ͯͷܭࢉنଇΛ

    ಘΒΕΔΑ͏ʹ͓ͯ͘͜͠ͱ͕ޙͰॏཁʹͳΔ
    ʢ୯ͳΔJOUFSQPMBUFETUSJOHʹ͠ͳ͍ཧ༝ʣ

    View Slide

  41. 41
    var char2 = MasterData.GetCharacter(2);


    var address = ExampleResolver1.Resolve(char2);


    Debug.Log(address); // "Assets/Icons/Bar.png"
    ήʔϜͷϥϯλΠϜίʔυ

    View Slide

  42. 42
    var char2 = MasterData.GetCharacter(2);


    var address = ExampleResolver1.Resolve(char2);


    Debug.Log(address); // "Assets/Icons/Bar.png"
    ήʔϜͷϥϯλΠϜίʔυ
    ϚελʔσʔλΛಡΈࠐΉ

    View Slide

  43. 43
    var char2 = MasterData.GetCharacter(2);


    var address = ExampleResolver1.Resolve(char2);


    Debug.Log(address); // "Assets/Icons/Bar.png"
    ήʔϜͷϥϯλΠϜίʔυ
    Ϛελʔσʔλ͔ΒΞηοτΞυϨεΛܭࢉ
    ΞηοτΞυϨεΛ΋ͱʹΞηοτΛಡΈࠐΉ

    View Slide

  44. 44
    static IDictionary>


    ResolverMap => new Dictionary>


    {


    {


    typeof(ExampleResolver1),


    () => ExampleResolver1.GetList(

    MasterData.GetAllCharacters())


    },


    // ...


    };


    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ

    View Slide

  45. 45
    static IDictionary>


    ResolverMap => new Dictionary>


    {


    {


    typeof(ExampleResolver1),


    () => ExampleResolver1.GetList(

    MasterData.GetAllCharacters())


    },


    // ...


    };


    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ΞηοτΞυϨεͷܭࢉنଇ͸ͨ͘͞Μ

    ͋ΔͷͰίϨΫγϣϯʹ·ͱΊΔΑ͏ʹ͢Δ

    View Slide

  46. 46
    static IDictionary>


    ResolverMap => new Dictionary>


    {


    {


    typeof(ExampleResolver1),


    () => ExampleResolver1.GetList(

    MasterData.GetAllCharacters())


    },


    // ...


    };


    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ΞηοτΞυϨεͷܭࢉنଇʹ͢΂ͯͷ

    ϚελʔσʔλΛೖྗͯ͠ɺࢀর͞ΕΔ

    ͢΂ͯͷΞηοτΞυϨεΛܭࢉ͢Δؔ਺

    View Slide

  47. 47
    static IDictionary>


    ResolverMap => new Dictionary>


    {


    {


    typeof(ExampleResolver1),


    () => ExampleResolver1.GetList(

    MasterData.GetAllCharacters())


    },


    // ...


    };


    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ͜ΕΛΞηοτΞυϨεͷܭࢉنଇ͝ͱʹॻ͘

    View Slide

  48. 48
    static IDictionary>


    ResolverMap => new Dictionary>


    {


    {


    typeof(ExampleResolver1),


    () => ExampleResolver1.GetList(

    MasterData.GetAllCharacters())


    },


    // ...


    };


    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ͢ΔͱϚελʔσʔλ͔Βܭࢉ͞ΕΔ

    ͢΂ͯͷΞηοτΞυϨεΛೖखͰ͖Δ

    View Slide

  49. 49
    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    [Test]


    public void AllAssetsExistAndReferenced()


    {


    var resolvers = TypeCache.GetTypesWithAttribute

    ();


    var addressesRead = new HashSet(

    resolvers.SelectMany(resolver => ResolverMap[resolver]()));


    var addressesExist = SomeAssetSystem.GetAllAssetAddresses();


    SetAssert.AreEqual(addressesExist, addressesRead);


    }

    View Slide

  50. [Test]


    public void AllAssetsExistAndReferenced()


    {


    var resolvers = TypeCache.GetTypesWithAttribute

    ();


    var addressesRead = new HashSet(

    resolvers.SelectMany(resolver => ResolverMap[resolver]()));


    var addressesExist = SomeAssetSystem.GetAllAssetAddresses();


    SetAssert.AreEqual(addressesExist, addressesRead);


    }
    50
    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ܭࢉ͞ΕͨΞηοτΞυϨεͱଘࡏ͢ΔΞηοτͷ

    ΞηοτΞυϨεΛಥ͖߹Θͤͯ֬ೝ͢Δϝιου

    View Slide

  51. 51
    [Test]


    public void AllAssetsExistAndReferenced()


    {


    var resolvers = TypeCache.GetTypesWithAttribute

    ();


    var addressesRead = new HashSet(

    resolvers.SelectMany(resolver => ResolverMap[resolver]()));


    var addressesExist = SomeAssetSystem.GetAllAssetAddresses();


    SetAssert.AreEqual(addressesExist, addressesRead);


    }
    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    લड़ͷͱ͓Γίʔυੜ੒͞ΕͨΞηοτΞυϨεͷ

    ܭࢉنଇʹ͸BUUSJCVUF͕͍͍ͭͯΔͷͰ͢΂ͯΛऔಘͰ͖Δ

    View Slide

  52. 52
    [Test]


    public void AllAssetsExistAndReferenced()


    {


    var resolvers = TypeCache.GetTypesWithAttribute

    ();


    var addressesRead = new HashSet(

    resolvers.SelectMany(resolver => ResolverMap[resolver]()));


    var addressesExist = SomeAssetSystem.GetAllAssetAddresses();


    SetAssert.AreEqual(addressesExist, addressesRead);


    }
    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ͢΂ͯͷܭࢉنଇ͔Βࢀর͞Ε͏ΔΞηοτͷΞυϨεΛܭࢉ͢Δ
    ΋֬͠ೝ͔Β࿙Ε͍ͯΔܭࢉنଇ͕͋Δͱྫ֎ʹͳΔͷͰؾ෇͚Δ

    View Slide

  53. 53
    [Test]


    public void AllAssetsExistAndReferenced()


    {


    var resolvers = TypeCache.GetTypesWithAttribute

    ();


    var addressesRead = new HashSet(

    resolvers.SelectMany(resolver => ResolverMap[resolver]()));


    var addressesExist = SomeAssetSystem.GetAllAssetAddresses();


    SetAssert.AreEqual(addressesExist, addressesRead);


    }
    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ͳΜΒ͔ͷΞηοτγεςϜ͔Β͢΂ͯͷΞηοτͷΞυϨεΛऔಘ͢Δ

    View Slide

  54. 54
    [Test]


    public void AllAssetsExistAndReferenced()


    {


    var resolvers = TypeCache.GetTypesWithAttribute

    ();


    var addressesRead = new HashSet(

    resolvers.SelectMany(resolver => ResolverMap[resolver]()));


    var addressesExist = SomeAssetSystem.GetAllAssetAddresses();


    SetAssert.AreEqual(addressesExist, addressesRead);


    }
    ෆ੔߹Λ֬ೝ͢Δίʔυʢʣ
    ࢀর͞ΕΔΞηοτͷΞυϨεͷू߹ͱ

    ଘࡏ͢ΔΞηοτͷΞυϨεͷू߹͕

    Ұக͠ͳ͚Ε͹ɺଘࡏ͠ͳ͍Ξηοτ΁ͷ

    ࢀর΍ωλόϨΞηοτ͕͋ΔͱΘ͔Δ

    View Slide

  55. 55
    "TTFU.BTUFS*OUFHSBUJPO5FTU
    "MM"TTFUT&YJTU"OE3FGFSFODFE
    "MM3FTPMWFST$PWFSFE
    3VO"MM 3VO4FMFDUFE 3FSVO'BJMFE $MFBS3FTVMUT
    1MBZ.PEF &EJU.PEF

    5FTU3VOOFS
    5FTU3VOOFS
    <5FTU>ͷ͍ͭͨϝιου͸5FTU3VOOFS

    ΢Οϯυ΢͔Β࣮ߦͰ͖Δ

    /PUIJOH

    View Slide

  56. 56
    "TTFU.BTUFS*OUFHSBUJPO5FTU
    "MM"TTFUT&YJTU"OE3FGFSFODFE
    "MM"TTFUT&YJTU"OE3FGFSFODFE T


    "MMFMFNFOUTFYJTUPOCPUI4FUT
    "TTFUT4USFBNJOH"TTFUT#BS$POTU
    "TTFUT4USFBNJOH"TTFUT#B[
    3VO"MM 3VO4FMFDUFE 3FSVO'BJMFE $MFBS3FTVMUT
    1MBZ.PEF &EJU.PEF

    5FTU3VOOFS
    5FTU3VOOFS
    ෆ੔߹͕ͳ͚Ε͹྘ͷ

    νΣοΫϚʔΫ͕ͭ͘

    /PUIJOH

    View Slide

  57. "TTFU.BTUFS*OUFHSBUJPO5FTU
    "MM"TTFUT&YJTU"OE3FGFSFODFE
    "MM"TTFUT&YJTU"OE3FGFSFODFE T


    .JTTJOHFMFNFOUT FYUSBFMFNFOUTPGBMMFMFNFOUT
    NJTTJOH "TTFUT4USFBNJOH"TTFUT'PP4FDPOE
    NJTTJOH "TTFUT4USFBNJOH"TTFUT'PP4FDPOE
    3VO"MM 3VO4FMFDUFE 3FSVO'BJMFE $MFBS3FTVMUT
    1MBZ.PEF &EJU.PEF
    /PUIJOH
    5FTU3VOOFS
    5FTU3VOOFS
    ෆ੔߹͕͋Ε͹੺ͷ

    ΤϥʔϚʔΫ͕ͭ͘

    ෆ੔߹ͷৄࡉ͕Θ͔Δ
    57

    View Slide

  58. 6OJUZ5FTU'SBNFXPSLͷςετ͸
    $-*͔Β΋࣮ߦͰ͖ΔͷͰෆ੔߹ͷ

    ֬ೝ͸ࣗಈఆظ࣮ߦ͕͓͢͢Ί
    58

    View Slide

  59. ಋೖޙͷޮՌ
    59

    View Slide

  60. ࠓճઆ໌ͨ͠࢓૊ΈͰͷޮՌ͸·ͩະܭଌ
    ͨͩ͠ݩͱͳͬͨ·ͩચ࿅͞Ε͍ͯͳ͍࣌୅ͷ

    ࣮૷͸ΞηοτͱϚελʔσʔλͷෆ੔߹Λ

    ܶతʹݮΒͨ͠ʢʹ͸ͳΒͳ͔ͬͨʣ
    60

    View Slide

  61. ·ͱΊ
    61

    View Slide

  62. ·ͱΊ
    62
    ΞηοτͱϚελʔσʔλͷෆ੔߹ͷ༧๷ʹ͸

    Ϛελʔσʔλ͔Βࢀর͞ΕΔ͢΂ͯͷ

    ΞηοτΛ೺ѲͰ͖ΔΑ͏ʹ͢ΔͱΑ͍

    View Slide

  63. એ఻
    63
    ࠓճ঺հͨ͠ΞηοτͱϚελʔσʔλͷ

    ෆ੔߹ͷ֬ೝ͸੩తݕࠪͱݺ͹ΕΔ΋ͷͰ͢ɻ
    %F/"͸ήʔϜ෼໺ͷ੩తݕࠪʹྗΛೖΕ͍ͯ·͢ɻ

    ڵຯ͕͋ͬͨΒͥͻ͓੠͕͚͍ͩ͘͞ʂ
    https://twitter.com/orga_chem

    View Slide