Unity4.3新機能とか Haxeで何かつくったはなし。(後編 : 3時間程度で2Dのクソゲーを作た。 )

  • 31
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はいはい。前編はHaxe Advent Calendarで (http://qiita.com/nobkz/items/ce6bbf56d0f0cbad2e13 )やりました。今回は後編を書きます。

(ちなみに、福岡で開催されている、八時間作品制作会で、3時間程度かけてつくりました。のこりの5時間は歯医者とか音楽制作とかに費しますた。)

ちなみに今回作ったゲームはこちらです。

http://www.unitygames.jp/game/ug7000803

Haxe + Unity3d 後編

画像素材の準備

まずこんな感じで準備

sample.png

ちなみにPagesでテキトーに図形配置して、選択してCommand + Cでコピー

スクリーンショット 2013-12-15 23.09.43.png

んで、プレビューappでクリップボードから新規作成

スクリーンショット 2013-12-15 23.12.02.png

で作りますた。

Sprite EditorでSprite分割

んで、準備した画像をUnityへドラッグアンドドロップして、追加した画像を選択Inspectorで

スクリーンショット 2013-12-15 23.13.38.png

こんな感じに設定する。 (Texture type -> Sprite、 Sprite Mode -> Multiple)に選択する。

んでSprite Editorボタンをクリックして、

スクリーンショット 2013-12-15 23.16.56.png

んで、Sliceして、Applyする。

スクリーンショット 2013-12-15 23.17.44.png

するとSpriteが分割されます。

スクリーンショット 2013-12-15 23.21.23.png

Spriteを配置、Animationを作る

さて、できたSpriteをこんな感じでScene画面に配置します。

Scene画面はこんな感じ

スクリーンショット 2013-12-15 23.19.08.png

階層構造はこんな感じ

スクリーンショット 2013-12-15 23.20.56.png

さてここで、Animationを付けていくのですが、ここで注意なのが、 Sceneに置いているGameObjectの同じ名前のオブジェクトを複数作らないでください 。それをするとAnimation Editorで困ります。

んで、HierarchyのHumanを選択したまま、Window -> Animationを選択します。

スクリーンショット 2013-12-15 23.27.17.png

そうするとAnimation Editorが出てきてキーフレームでAnimationを作成できます。

スクリーンショット 2013-12-15 23.28.06.png

今回は、

  • 走るアニメーション
  • 棒人間が壊れるアニメーション
  • ゴールした時のアニメーション

スクリーンショット 2013-12-15 23.30.12.png

を準備しました。

Mecanimでアニメーション遷移の管理

さて、Mecanimでアニメーション遷移を管理します。

window -> Animatorを選択

スクリーンショット 2013-12-15 23.32.38.png

すると、先程作ったAnimationClipが配置されて、いるはずです。

そしてこんな感じに設定しますた。

スクリーンショット 2013-12-15 23.31.32.png

んで各遷移(矢印の)Inspector設定はこんな感じです。

Human -> break

スクリーンショット 2013-12-15 23.34.56.png

Human -> goal

スクリーンショット 2013-12-15 23.35.01.png

物理演算設定

  • Humanにはbox Collider2dとRigidBody
  • あとテキトーにCollider2dは設定

スクリプティング

だいたいHaxeで書きますた。

HumanController.hx
package ;
import unityEngine.MonoBehaviour;
import unityEngine.Transform;
import unityEngine.Time;
import unityEngine.Vector3;
import unityEngine.GameObject;
import unityEngine.Animator;
using UnityHelper;

class HumanController extends MonoBehaviour{
    public var speed : Single;
    public var force : unityEngine.Vector2;
    public var anim : Animator;

    public function Update(){
        if( !this.anim.GetBool("breaked") &&  !this.anim.GetBool("goal") ){
            this.getTransform().Translate(speed, 0.0, 0.0);
            if( unityEngine.Input.GetMouseButton(0) ){
                untyped __cs__("this.rigidbody2D.AddForce(force)");
            }
        }
    }

    public function breaking(){
        unityEngine.Application.LoadLevel("Start");
    }
}
Box.hx
package;

import unityEngine.MonoBehaviour;
import unityEngine.Collision2D;

class Box extends MonoBehaviour{
    public function OnCollisionEnter2D(coll : Collision2D){
        var humanController : HumanController = coll.gameObject.GetComponent();
        humanController.anim.SetBool("breaked",true);
    }
}
Goal.hx
package;

import unityEngine.MonoBehaviour;
import unityEngine.Collision2D;

class Goal extends MonoBehaviour{
    public function OnTriggerEnter2D(coll : Collision2D){
        var humanControlelr : HumanController = coll.gameObject.GetComponent();
        humanControlelr.anim.SetBool("goal",true);
    }
}

Animatorと、Collider2Dのクラスがhx-unityに実装されてなかった!

なので必要最小限のexternを書いた。

Animator.hx
package unityEngine;
@:native("UnityEngine.Animator") extern class Animator extends Behaviour {
    function GetBool(name:String) : Bool;
    function SetBool(name:String, value:Bool) : Void;
}
Collider2D.hx
package unityEngine;
@:native("UnityEngine.Collision2D") extern class Collision2D extends Behaviour {
     var gameObject : unityEngine.GameObject;
}

今度、Unity4.3の分の修正して、プルリク送っておくか...

あとHxmlとか

一応、こんな感じになった。

build.hxml
-lib unity3d
-cp src/
-cs cs
-D no-compilation
HumanController
CameraScript
Opening
Box
Goal

あと、こまごま色々やって完成!!!

えっとあとは、

  • パラメータの調節 ( 大してやってない。 )
  • Title画面つくって、Scene遷移とか

やって完成。

まとめ。

Unity3dの2D機能について

個人的には2Dは以前のバージョンのUnityよりかた作りやすくなっていると思います。

Haxe と Unity3dについて

よかった点

  • 意外と書きやすかった。Haxeのコンパイラの補完機能のお陰
  • 型推論などのHaxeの言語機能が素晴しい

悪かった点

  • ライブラリが不十分なところもあるので、ところどころextern書かないと行けない。

以上です。ここまで読んでくれた方ありがとうございました!

追記

あ、Animation Editor上で、Event呼び出す設定もついでに。

スクリーンショット 2013-12-16 0.22.43.png

スクリーンショット 2013-12-16 0.22.55.png

これで、Humanのbreaking()メソッドが呼びだされます。

追記2:HaxeをビルドしたC#のソース

こんな感じ。読めなくはない。

HumanController.cs

#pragma warning disable 109, 114, 219, 429, 168, 162
public  class HumanController : global::UnityEngine.MonoBehaviour, global::haxe.lang.IHxObject 
{
    public    HumanController(global::haxe.lang.EmptyObject empty) : base()
    {
        unchecked 
        {
        }
        #line default
    }


    public    HumanController() : base()
    {
        unchecked 
        {
        }
        #line default
    }


    public static   object __hx_createEmpty()
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            return new global::HumanController(((global::haxe.lang.EmptyObject) (global::haxe.lang.EmptyObject.EMPTY) ));
        }
        #line default
    }


    public static   object __hx_create(global::Array arr)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            return new global::HumanController();
        }
        #line default
    }


    public  float speed;

    public  global::UnityEngine.Vector2 force;

    public  global::UnityEngine.Animator anim;

    public virtual   void Update()
    {
        unchecked 
        {
            #line 15 "src/HumanController.hx"
            if ((  ! (this.anim.GetBool("breaked"))  &&  ! (this.anim.GetBool("goal"))  )) 
            {
                #line 17 "src/HumanController.hx"
                ((global::UnityEngine.Transform) (global::haxe.lang.Runtime.getField(this, "transform", 1167273324, true)) ).Translate(((float) (this.speed) ), ((float) (0.0) ), ((float) (0.0) ), ((global::UnityEngine.Space) (default(global::UnityEngine.Space)) ));
                if (global::UnityEngine.Input.GetMouseButton(0)) 
                {
                    #line 18 "src/HumanController.hx"
                    this.rigidbody2D.AddForce(force);
                }

            }

        }
        #line default
    }


    public virtual   void breaking()
    {
        unchecked 
        {
            #line 24 "src/HumanController.hx"
            global::UnityEngine.Application.LoadLevel("Start");
        }
        #line default
    }


    public virtual   bool __hx_deleteField(string field, int hash)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            return false;
        }
        #line default
    }


    public virtual   object __hx_lookupField(string field, int hash, bool throwErrors, bool isCheck)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            if (isCheck) 
            {
                #line 10 "src/HumanController.hx"
                return global::haxe.lang.Runtime.undefined;
            }
             else 
            {
                #line 10 "src/HumanController.hx"
                if (throwErrors) 
                {
                    #line 10 "src/HumanController.hx"
                    throw global::haxe.lang.HaxeException.wrap("Field not found.");
                }
                 else 
                {
                    #line 10 "src/HumanController.hx"
                    return default(object);
                }

            }

        }
        #line default
    }


    public virtual   double __hx_lookupField_f(string field, int hash, bool throwErrors)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            if (throwErrors) 
            {
                #line 10 "src/HumanController.hx"
                throw global::haxe.lang.HaxeException.wrap("Field not found or incompatible field type.");
            }
             else 
            {
                #line 10 "src/HumanController.hx"
                return default(double);
            }

        }
        #line default
    }


    public virtual   object __hx_lookupSetField(string field, int hash, object @value)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            throw global::haxe.lang.HaxeException.wrap("Cannot access field for writing.");
        }
        #line default
    }


    public virtual   double __hx_lookupSetField_f(string field, int hash, double @value)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            throw global::haxe.lang.HaxeException.wrap("Cannot access field for writing or incompatible type.");
        }
        #line default
    }


    public virtual   double __hx_setField_f(string field, int hash, double @value, bool handleProperties)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            switch (hash)
            {
                case 23697287:
                {
                    #line 10 "src/HumanController.hx"
                    this.speed = ((float) (@value) );
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                default:
                {
                    #line 10 "src/HumanController.hx"
                    return this.__hx_lookupSetField_f(field, hash, @value);
                }

            }

        }
        #line default
    }


    public virtual   object __hx_setField(string field, int hash, object @value, bool handleProperties)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            switch (hash)
            {
                case 1575675685:
                {
                    #line 10 "src/HumanController.hx"
                    this.hideFlags = ((global::UnityEngine.HideFlags) (@value) );
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                case 1224700491:
                {
                    #line 10 "src/HumanController.hx"
                    this.name = global::haxe.lang.Runtime.toString(@value);
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                case 5790298:
                {
                    #line 10 "src/HumanController.hx"
                    this.tag = global::haxe.lang.Runtime.toString(@value);
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                case 2117141633:
                {
                    #line 10 "src/HumanController.hx"
                    this.enabled = ((bool) (@value) );
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                case 896046654:
                {
                    #line 10 "src/HumanController.hx"
                    this.useGUILayout = ((bool) (@value) );
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                case 1081181713:
                {
                    #line 10 "src/HumanController.hx"
                    this.anim = ((global::UnityEngine.Animator) (@value) );
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                case 76853739:
                {
                    #line 10 "src/HumanController.hx"
                    this.force = ((global::UnityEngine.Vector2) (@value) );
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                case 23697287:
                {
                    #line 10 "src/HumanController.hx"
                    this.speed = ((float) (global::haxe.lang.Runtime.toInt(@value)) );
                    #line 10 "src/HumanController.hx"
                    return @value;
                }


                default:
                {
                    #line 10 "src/HumanController.hx"
                    return this.__hx_lookupSetField(field, hash, @value);
                }

            }

        }
        #line default
    }


    public virtual   object __hx_getField(string field, int hash, bool throwErrors, bool isCheck, bool handleProperties)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            switch (hash)
            {
                case 1635357710:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("DontDestroyOnLoad"), ((int) (1635357710) ))) );
                }


                case 1003238327:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("DestroyImmediate"), ((int) (1003238327) ))) );
                }


                case 1909937370:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("Destroy"), ((int) (1909937370) ))) );
                }


                case 304123084:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("ToString"), ((int) (304123084) ))) );
                }


                case 276486854:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetInstanceID"), ((int) (276486854) ))) );
                }


                case 1575675685:
                {
                    #line 10 "src/HumanController.hx"
                    return this.hideFlags;
                }


                case 1224700491:
                {
                    #line 10 "src/HumanController.hx"
                    return this.name;
                }


                case 2134927590:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("BroadcastMessage"), ((int) (2134927590) ))) );
                }


                case 139469119:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("SendMessage"), ((int) (139469119) ))) );
                }


                case 294420221:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("SendMessageUpwards"), ((int) (294420221) ))) );
                }


                case 89600725:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("CompareTag"), ((int) (89600725) ))) );
                }


                case 2122408236:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponents"), ((int) (2122408236) ))) );
                }


                case 967979664:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponentsInChildren"), ((int) (967979664) ))) );
                }


                case 1328964235:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponentInChildren"), ((int) (1328964235) ))) );
                }


                case 1723652455:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("GetComponent"), ((int) (1723652455) ))) );
                }


                case 5790298:
                {
                    #line 10 "src/HumanController.hx"
                    return this.tag;
                }


                case 2117141633:
                {
                    #line 10 "src/HumanController.hx"
                    return this.enabled;
                }


                case 1856815770:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("StopAllCoroutines"), ((int) (1856815770) ))) );
                }


                case 2084823382:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("StopCoroutine"), ((int) (2084823382) ))) );
                }


                case 987108662:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("StartCoroutine"), ((int) (987108662) ))) );
                }


                case 602588383:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("IsInvoking"), ((int) (602588383) ))) );
                }


                case 757431474:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("CancelInvoke"), ((int) (757431474) ))) );
                }


                case 1641152943:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("InvokeRepeating"), ((int) (1641152943) ))) );
                }


                case 1416948632:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("Invoke"), ((int) (1416948632) ))) );
                }


                case 896046654:
                {
                    #line 10 "src/HumanController.hx"
                    return this.useGUILayout;
                }


                case 1825712515:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("breaking"), ((int) (1825712515) ))) );
                }


                case 999946793:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (new global::haxe.lang.Closure(((object) (this) ), global::haxe.lang.Runtime.toString("Update"), ((int) (999946793) ))) );
                }


                case 1081181713:
                {
                    #line 10 "src/HumanController.hx"
                    return this.anim;
                }


                case 76853739:
                {
                    #line 10 "src/HumanController.hx"
                    return this.force;
                }


                case 23697287:
                {
                    #line 10 "src/HumanController.hx"
                    return this.speed;
                }


                default:
                {
                    #line 10 "src/HumanController.hx"
                    return this.__hx_lookupField(field, hash, throwErrors, isCheck);
                }

            }

        }
        #line default
    }


    public virtual   double __hx_getField_f(string field, int hash, bool throwErrors, bool handleProperties)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            switch (hash)
            {
                case 23697287:
                {
                    #line 10 "src/HumanController.hx"
                    return ((double) (this.speed) );
                }


                default:
                {
                    #line 10 "src/HumanController.hx"
                    return this.__hx_lookupField_f(field, hash, throwErrors);
                }

            }

        }
        #line default
    }


    public virtual   object __hx_invokeField(string field, int hash, global::Array dynargs)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            switch (hash)
            {
                case 1416948632:case 1641152943:case 757431474:case 602588383:case 987108662:case 2084823382:case 1856815770:case 1723652455:case 1328964235:case 967979664:case 2122408236:case 89600725:case 294420221:case 139469119:case 2134927590:case 276486854:case 304123084:case 1909937370:case 1003238327:case 1635357710:
                {
                    #line 10 "src/HumanController.hx"
                    return global::haxe.lang.Runtime.slowCallField(this, field, dynargs);
                }


                case 1825712515:
                {
                    #line 10 "src/HumanController.hx"
                    this.breaking();
                    #line 10 "src/HumanController.hx"
                    break;
                }


                case 999946793:
                {
                    #line 10 "src/HumanController.hx"
                    this.Update();
                    #line 10 "src/HumanController.hx"
                    break;
                }


                default:
                {
                    #line 10 "src/HumanController.hx"
                    return ((global::haxe.lang.Function) (this.__hx_getField(field, hash, true, false, false)) ).__hx_invokeDynamic(dynargs);
                }

            }

            #line 10 "src/HumanController.hx"
            return default(object);
        }
        #line default
    }


    public virtual   void __hx_getFields(global::Array<object> baseArr)
    {
        unchecked 
        {
            #line 10 "src/HumanController.hx"
            baseArr.push("hideFlags");
            #line 10 "src/HumanController.hx"
            baseArr.push("name");
            #line 10 "src/HumanController.hx"
            baseArr.push("tag");
            #line 10 "src/HumanController.hx"
            baseArr.push("enabled");
            #line 10 "src/HumanController.hx"
            baseArr.push("useGUILayout");
            #line 10 "src/HumanController.hx"
            baseArr.push("anim");
            #line 10 "src/HumanController.hx"
            baseArr.push("force");
            #line 10 "src/HumanController.hx"
            baseArr.push("speed");
        }
        #line default
    }


}

追記3:

あしたは、@GRGSIBERIAさんです。よろしくお願いします。

この投稿は Unity Advent Calendar 201315日目の記事です。