はいはい。前編はHaxe Advent Calendarで (http://qiita.com/nobkz/items/ce6bbf56d0f0cbad2e13 )やりました。今回は後編を書きます。
(ちなみに、福岡で開催されている、八時間作品制作会で、3時間程度かけてつくりました。のこりの5時間は歯医者とか音楽制作とかに費しますた。)
ちなみに今回作ったゲームはこちらです。
Haxe + Unity3d 後編
画像素材の準備
まずこんな感じで準備
ちなみにPagesでテキトーに図形配置して、選択してCommand + Cでコピー
んで、プレビューappでクリップボードから新規作成
で作りますた。
Sprite EditorでSprite分割
んで、準備した画像をUnityへドラッグアンドドロップして、追加した画像を選択Inspectorで
こんな感じに設定する。 (Texture type -> Sprite、 Sprite Mode -> Multiple)に選択する。
んでSprite Editorボタンをクリックして、
んで、Sliceして、Applyする。
するとSpriteが分割されます。
Spriteを配置、Animationを作る
さて、できたSpriteをこんな感じでScene画面に配置します。
Scene画面はこんな感じ
階層構造はこんな感じ
さてここで、Animationを付けていくのですが、ここで注意なのが、 Sceneに置いているGameObjectの同じ名前のオブジェクトを複数作らないでください 。それをするとAnimation Editorで困ります。
んで、HierarchyのHumanを選択したまま、Window -> Animationを選択します。
そうするとAnimation Editorが出てきてキーフレームでAnimationを作成できます。
今回は、
- 走るアニメーション
- 棒人間が壊れるアニメーション
- ゴールした時のアニメーション
を準備しました。
Mecanimでアニメーション遷移の管理
さて、Mecanimでアニメーション遷移を管理します。
window -> Animatorを選択
すると、先程作ったAnimationClipが配置されて、いるはずです。
そしてこんな感じに設定しますた。
んで各遷移(矢印の)Inspector設定はこんな感じです。
Human -> break
Human -> goal
物理演算設定
- Humanにはbox Collider2dとRigidBody
- あとテキトーにCollider2dは設定
スクリプティング
だいたいHaxeで書きますた。
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");
}
}
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);
}
}
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を書いた。
package unityEngine;
@:native("UnityEngine.Animator") extern class Animator extends Behaviour {
function GetBool(name:String) : Bool;
function SetBool(name:String, value:Bool) : Void;
}
package unityEngine;
@:native("UnityEngine.Collision2D") extern class Collision2D extends Behaviour {
var gameObject : unityEngine.GameObject;
}
今度、Unity4.3の分の修正して、プルリク送っておくか...
あと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呼び出す設定もついでに。
これで、Humanのbreaking()メソッドが呼びだされます。
追記2:HaxeをビルドしたC#のソース
こんな感じ。読めなくはない。
#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さんです。よろしくお願いします。